[ABC_PROTO_HTTP] = &abc_io_http,
};
+// HTML attrs
static char* src_keys[] = {"src", "源", NULL};
static char* href_keys[] = {"href", "地址", NULL};
static char* action_keys[] = {"action", "动作", NULL};
static char* method_keys[] = {"method", "方法", NULL};
+static char* xmlns_keys[] = {"xmlns", NULL};
+static char* xmlang_keys[] = {"xml:lang", NULL};
+static char* lang_keys[] = {"lang", "语言", NULL};
+
+static char* http_equiv_keys[] = {"http-equiv", NULL};
+static char* content_keys[] = {"content", "正文类型", NULL};
+static char* charset_keys[] = {"charset", "字符集", NULL};
+
+static char* enctype_keys[] = {"enctype", NULL};
+
+// HTML labels
static char* html_keys[] = {"html", "网页", NULL};
static char* head_keys[] = {"head", "头部", NULL};
static char* body_keys[] = {"body", "主体", NULL};
static char* div_keys[] = {"div", "分区", NULL};
static char* img_keys[] = {"img", "图片", NULL};
+static char* meta_keys[] = {"meta", NULL};
+
+static char* center_keys[] = {"center", "居中", NULL};
static char* title_keys[] = {"title", "标题", NULL};
static char* input_keys[] = {"input", "输入", NULL};
static char* label_keys[] = {"label", "标签", NULL};
-static char* center_keys[] = {"center", "居中", NULL};
+
+static char* table_keys[] = {"table", "表格", NULL};
+static char* tr_keys[] = {"tr", "行", NULL};
+static char* td_keys[] = {"td", "列", NULL};
static char* br_keys[] = {"br", "换行", NULL};
static char* hr_keys[] = {"hr", "标题换行", NULL};
+
static char* h1_keys[] = {"h1", "标题1", NULL};
static char* h2_keys[] = {"h2", "标题2", NULL};
static char* h3_keys[] = {"h3", "标题3", NULL};
static char* p_keys[] = {"p", "段落", NULL};
static char* a_keys[] = {"a", "超链接", NULL};
+static html_attr_t html_attrs[] =
+{
+ {xmlns_keys, "", ABC_HTML_ATTR_XMLNS, 0},
+ {xmlang_keys, "", ABC_HTML_ATTR_XMLANG, 0},
+ {lang_keys, "", ABC_HTML_ATTR_LANG, 0},
+};
+
+static html_attr_t meta_attrs[] =
+{
+ {http_equiv_keys, "", ABC_HTML_ATTR_HTTP_EQUIV, ABC_HTML_FLAG_SHOW},
+ {content_keys, "", ABC_HTML_ATTR_CONTENT, ABC_HTML_FLAG_SHOW},
+// {charset_keys, "", ABC_HTML_ATTR_CHARSET, ABC_HTML_FLAG_SHOW},
+};
static html_attr_t h1_attrs[] =
{
{font_keys, "SimSong", ABC_HTML_ATTR_FONT, 0},
{font_size_keys, "16", ABC_HTML_ATTR_FONT_SIZE, 0},
+
+ {enctype_keys, "", ABC_HTML_ATTR_ENCTYPE, 0},
};
static html_label_t html_labels[] =
{
- {html_keys, ABC_HTML, 0, NULL, ABC_HTML_FLAG_CLOSE},
+ {html_keys, ABC_HTML, abc_number_of(html_attrs), html_attrs, ABC_HTML_FLAG_CLOSE},
+ {meta_keys, ABC_HTML_META, abc_number_of(meta_attrs), meta_attrs, ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE},
+
{title_keys, ABC_HTML_TITLE, 0, NULL, ABC_HTML_FLAG_CLOSE},
{head_keys, ABC_HTML_HEAD, 0, NULL, ABC_HTML_FLAG_CLOSE},
{body_keys, ABC_HTML_BODY, 0, NULL, ABC_HTML_FLAG_CLOSE},
{input_keys, ABC_HTML_INPUT, abc_number_of(input_attrs), input_attrs, ABC_HTML_FLAG_OPEN},
{label_keys, ABC_HTML_LABEL, abc_number_of(label_attrs), label_attrs, ABC_HTML_FLAG_CLOSE},
{center_keys, ABC_HTML_CENTER, 0, NULL, ABC_HTML_FLAG_CLOSE},
+
+ {table_keys, ABC_HTML_TABLE, 0, NULL, ABC_HTML_FLAG_CLOSE},
+ {tr_keys, ABC_HTML_TR, 0, NULL, ABC_HTML_FLAG_CLOSE},
+ {td_keys, ABC_HTML_TD, 0, NULL, ABC_HTML_FLAG_CLOSE},
};
static int __html_parse_obj(abc_html_t* html, abc_char_t* c);
return 0;
}
+int abc_html_post(abc_html_t** pp, abc_html_t* form, abc_obj_t* submit)
+{
+ if (!pp || !form || !form->file || !submit)
+ return -EINVAL;
+
+ scf_string_t* url;
+ scf_string_t* content;
+ abc_html_t* html;
+ abc_obj_t* action;
+ abc_io_t* io;
+ int n;
+
+ if (!strncmp(form->file->data, "http://", 7)) {
+ n = 7;
+ io = abc_io_array[ABC_PROTO_HTTP];
+ } else {
+ scf_loge("proto of '%s' NOT support\n", form->file->data);
+ return -EINVAL;
+ }
+
+ action = abc_obj_find_attr(submit, ABC_HTML_ATTR_ACTION);
+ if (!action) {
+ scf_loge("'post' should have an 'action'\n");
+ return -EINVAL;
+ }
+
+ url = scf_string_clone(form->file);
+ if (!url)
+ return -ENOMEM;
+
+ int ret = scf_string_cat_cstr_len(url, "/", 1);
+ if (ret < 0) {
+ scf_string_free(url);
+ return ret;
+ }
+
+ ret = scf_string_cat(url, action->value);
+ if (ret < 0) {
+ scf_string_free(url);
+ return ret;
+ }
+
+ scf_logi("post: %s\n", url->data);
+
+ content = abc_obj_to_string(form->root);
+ if (!content) {
+ scf_string_free(url);
+ return -ENOMEM;
+ }
+
+ html = calloc(1, sizeof(abc_html_t));
+ if (!html) {
+ scf_string_free(url);
+ scf_string_free(content);
+ return -ENOMEM;
+ }
+
+ html->io.proto = io->proto;
+ html->io.priv = NULL;
+ html->io.open = io->open;
+ html->io.close = io->close;
+ html->io.popc = io->popc;
+ html->io.post = io->post;
+
+ ret = io->post(html, url->data + n, content);
+ if (ret < 0) {
+ scf_string_free(url);
+ scf_string_free(content);
+ free(html);
+ return ret;
+ }
+
+ html->file = url;
+
+ html->n_lines = 1;
+
+ *pp = html;
+ return 0;
+}
+
int abc_html_open(abc_html_t** pp, const char* path)
{
if (!pp || !path)
if ('_' == c->c
|| '-' == c->c
- || ('a' <= c->c && 'z' >= c->c))
+ || ':' == c->c
+ || ('a' <= c->c && 'z' >= c->c)) {
scf_string_cat_cstr_len(key, c->utf8, c->len);
- else {
+
+ } else if (' ' == c->c) {
+
+ } else {
scf_loge("invalid char '%c' in HTML attribute, file: %s, line: %d\n",
c->c, html->file->data, html->n_lines);
free(c);
if ('>' == tmp)
break;
- if ('\n' == tmp) {
- scf_loge("%c:%#x, html->n_lines: %d, pos: %d\n", tmp, tmp, html->n_lines, html->pos);
- return -1;
+ if ('\n' == tmp || '\r' == tmp) {
+ scf_logw("%#x, html->n_lines: %d, pos: %d\n", tmp, html->n_lines, html->pos);
+ continue;
}
}
void (*close)(abc_html_t* html);
int (*popc )(abc_html_t* html);
- int (*post )(abc_html_t* html);
+ int (*post )(abc_html_t* html, const char* path, scf_string_t* content);
};
struct abc_html_s
};
int abc_html_open (abc_html_t** pp, const char* path);
-void abc_html_close(abc_html_t* html);
+int abc_html_post (abc_html_t** pp, abc_html_t* form, abc_obj_t* submit);
+void abc_html_close(abc_html_t* html);
int abc_html_parse(abc_html_t* html);
int content_length;
+ int cpos;
+ uint32_t chunk_flag:1;
+
int exit;
pthread_t tid;
pthread_mutex_t mutex;
continue;
}
- size_t n = strlen("Content-Length: ");
+ size_t i = strlen("Content-Length: ");
+ size_t j = strlen("Transfer-Encoding: chunked");
- if (!strncmp(p0, "Content-Length: ", n)) {
- http->content_length = atoi(p0 + n);
+ if (!strncmp(p0, "Content-Length: ", i)) {
+ http->content_length = atoi(p0 + i);
+ http->chunk_flag = 0;
scf_logi("Content-Length: %d\n", http->content_length);
break;
+
+ } else if (!strncmp(p0, "Transfer-Encoding: chunked", j)) {
+ http->content_length = 0;
+ http->chunk_flag = 1;
+
+ scf_logi("Transfer-Encoding: chunked\n");
+ break;
}
p1 += 2;
}
}
+static void http_chunk_size(abc_http_t* http)
+{
+ while (http->cpos < http->rbuf->len) {
+
+ uint8_t* p = http->rbuf->data + http->cpos;
+
+ if ('0' <= *p && *p <= '9') {
+
+ http->content_length <<= 4;
+ http->content_length += *p - '0';
+
+ } else if ('a' <= *p && *p <= 'f') {
+
+ http->content_length <<= 4;
+ http->content_length += *p - 'a' + 10;
+
+ } else if ('A' <= *p && *p <= 'F') {
+
+ http->content_length <<= 4;
+ http->content_length += *p - 'A' + 10;
+ } else
+ break;
+
+ *p = '\n';
+
+ http->cpos++;
+ }
+}
+
+static int http_filter_chunk(abc_html_t* html)
+{
+ abc_http_t* http = html->io.priv;
+
+ if (html->download)
+ return 0;
+
+ while (http->cpos < http->rbuf->len) {
+
+ http_chunk_size(http);
+
+ if (strncmp(http->rbuf->data + http->cpos, "\r\n", 2))
+ return 0;
+
+ scf_logi("rbuf->len: %ld, http->cpos: %d, http->content_length: %#x\n", http->rbuf->len, http->cpos, http->content_length);
+
+ http->cpos += 2;
+
+ if (0 == http->content_length) {
+ html->download = 1;
+ return 0;
+ }
+
+ if (http->cpos + http->content_length + 2 <= http->rbuf->len) {
+
+ http->cpos += http->content_length;
+ http->content_length = 0;
+
+ uint8_t* p = http->rbuf->data + http->cpos;
+
+ if (strncmp(p, "\r\n", 2)) {
+ scf_loge("*p: %d\n", *p);
+ return -1;
+ }
+
+ http->cpos += 2;
+ } else
+ break;
+ }
+
+ return 0;
+}
+
static void* http_thread(void* arg)
{
abc_html_t* html = arg;
if (!strncmp(http->rbuf->data + i, "\r\n\r\n", 4)) {
http->rpos = i + 4;
+ http->cpos = http->rpos;
http_parse_head(http);
break;
}
if (http->rpos > 0) {
- if (http->content_length >= 0) {
+ if (!http->chunk_flag) {
if (http->content_length == http->rbuf->len - http->rpos) {
html->download = 1;
scf_logi("http response: %s\n", http->rbuf->data);
}
} else {
+ http_filter_chunk(html);
+
+ if (html->download)
+ scf_logi("http response: %s\n", http->rbuf->data);
}
}
return 0;
}
-static int __http_open(abc_html_t* html, const char* path)
+static int __http_open2(abc_http_t** pp, const char* path)
{
- if (!html || !path)
+ if (!path)
return -EINVAL;
scf_logw("\n");
return -ENOMEM;
}
+ *pp = http;
+ return 0;
+}
+
+static int __http_open(abc_html_t* html, const char* path)
+{
+ if (!html || !path)
+ return -EINVAL;
+
+ abc_http_t* http = NULL;
+
+ int ret = __http_open2(&http, path);
+ if (ret < 0) {
+ scf_loge("open http url '%s' failed\n", path);
+ return ret;
+ }
+
#define ABC_HTTP_FILL(str) \
do { \
ret = scf_string_cat_cstr(http->wbuf, str); \
return 0;
}
+static int __http_post(abc_html_t* html, const char* path, scf_string_t* content)
+{
+ if (!html || !path || !content)
+ return -EINVAL;
+
+ abc_http_t* http = NULL;
+
+ int ret = __http_open2(&http, path);
+ if (ret < 0) {
+ scf_loge("open http url '%s' failed\n", path);
+ return ret;
+ }
+
+ ABC_HTTP_FILL("POST ");
+ ABC_HTTP_FILL(http->uri->data);
+ ABC_HTTP_FILL(" HTTP/1.1\r\n");
+
+ ABC_HTTP_FILL("Host: ");
+ ABC_HTTP_FILL(http->host->data);
+ ABC_HTTP_FILL("\r\n");
+
+ char buf[128];
+ snprintf(buf, sizeof(buf) - 1, "%ld", content->len);
+
+ ABC_HTTP_FILL("Content-Length: ");
+ ABC_HTTP_FILL(buf);
+ ABC_HTTP_FILL("\r\n");
+
+ ABC_HTTP_FILL("User-Agent: advanced-browser-core\r\n");
+ ABC_HTTP_FILL("Accept: */*\r\n");
+ ABC_HTTP_FILL("\r\n");
+
+ ABC_HTTP_FILL(content->data);
+
+ html->io.priv = http;
+
+ if (pthread_create(&http->tid, NULL, http_thread, html)) {
+ abc_http_close(http);
+ html->io.priv = NULL;
+ return -1;
+ }
+
+ scf_logw("\n");
+ return 0;
+}
+
static void __http_close(abc_html_t* html)
{
if (html)
return EOF;
}
-static int __http_post(abc_html_t* html)
-{
- scf_loge("\n");
- return -1;
-}
-
abc_io_t abc_io_http =
{
.proto = "http://",
printf("</%s>\n", obj->keys[0]);
}
}
+
+static int __abc_obj_to_string(abc_obj_t* obj, scf_string_t* s)
+{
+ scf_list_t* l;
+ abc_obj_t* attr;
+ abc_obj_t* child;
+
+ int ret;
+
+ if (!obj)
+ return 0;
+
+ if (obj->value) {
+ ret = scf_string_cat_cstr(s, " ");
+ if (ret < 0)
+ return ret;
+
+ ret = scf_string_cat_cstr(s, obj->keys[0]);
+ if (ret < 0)
+ return ret;
+
+ ret = scf_string_cat_cstr(s, "=\"");
+ if (ret < 0)
+ return ret;
+
+ ret = scf_string_cat(s, obj->value);
+ if (ret < 0)
+ return ret;
+
+ ret = scf_string_cat_cstr(s, "\"");
+ if (ret < 0)
+ return ret;
+
+ } else if (obj->keys) {
+ ret = scf_string_cat_cstr(s, "<");
+ if (ret < 0)
+ return ret;
+
+ ret = scf_string_cat_cstr(s, obj->keys[0]);
+ if (ret < 0)
+ return ret;
+ }
+
+ for (l = scf_list_head(&obj->attrs); l != scf_list_sentinel(&obj->attrs); l = scf_list_next(l)) {
+ attr = scf_list_data(l, abc_obj_t, list);
+
+ if (ABC_HTML_FLAG_SHOW & attr->flags) {
+ ret = __abc_obj_to_string(attr, s);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ if (!obj->value) {
+ if (obj->flags & ABC_HTML_FLAG_SINGLE) {
+
+ ret = scf_string_cat_cstr(s, " />\n");
+ if (ret < 0)
+ return ret;
+
+ } else if (obj->keys) {
+ ret = scf_string_cat_cstr(s, ">\n");
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ if (obj->text) {
+ ret = scf_string_cat(s, obj->text);
+ if (ret < 0)
+ return ret;
+
+ ret = scf_string_cat_cstr(s, "\n");
+ if (ret < 0)
+ return ret;
+ }
+
+ for (l = scf_list_head(&obj->childs); l != scf_list_sentinel(&obj->childs); l = scf_list_next(l)) {
+ child = scf_list_data(l, abc_obj_t, list);
+
+ ret = __abc_obj_to_string(child, s);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (ABC_HTML_FLAG_CLOSE == (obj->flags & (ABC_HTML_FLAG_CLOSE | ABC_HTML_FLAG_SINGLE))) {
+ if (obj->keys) {
+ ret = scf_string_cat_cstr(s, "</");
+ if (ret < 0)
+ return ret;
+
+ ret = scf_string_cat_cstr(s, obj->keys[0]);
+ if (ret < 0)
+ return ret;
+
+ ret = scf_string_cat_cstr(s, ">\n");
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+scf_string_t* abc_obj_to_string(abc_obj_t* obj)
+{
+ scf_string_t* s = scf_string_alloc();
+ if (!s)
+ return NULL;
+
+ int ret = __abc_obj_to_string(obj, s);
+ if (ret < 0) {
+ scf_string_free(s);
+ return NULL;
+ }
+
+ scf_logi("%s\n", s->data);
+ return s;
+}
ABC_HTML_A,
ABC_HTML_A_HREF,
- // 15
+ // 16
ABC_HTML_IMG,
ABC_HTML_FORM,
ABC_HTML_INPUT,
ABC_HTML_CENTER,
+ ABC_HTML_META,
+
+ ABC_HTML_TABLE,
+ ABC_HTML_TR,
+ ABC_HTML_TD,
+
ABC_HTML_NB, // total HTML objects
ABC_HTML_ATTR_ID,
ABC_HTML_ATTR_WIDTH,
ABC_HTML_ATTR_HEIGHT,
+
+ ABC_HTML_ATTR_XMLNS,
+ ABC_HTML_ATTR_XMLANG,
+ ABC_HTML_ATTR_LANG,
+
+ ABC_HTML_ATTR_HTTP_EQUIV,
+ ABC_HTML_ATTR_CONTENT,
+ ABC_HTML_ATTR_CHARSET,
+
+ ABC_HTML_ATTR_ENCTYPE,
};
struct abc_obj_s
uint32_t clicked:1;
};
-abc_obj_t* abc_obj_alloc(scf_string_t* file, int line, int pos, int type);
-void abc_obj_free (abc_obj_t* obj);
-abc_obj_t* abc_obj_find (abc_obj_t* root, int x, int y);
-void abc_obj_print(abc_obj_t* obj);
+abc_obj_t* abc_obj_alloc(scf_string_t* file, int line, int pos, int type);
+void abc_obj_free (abc_obj_t* obj);
+abc_obj_t* abc_obj_find (abc_obj_t* root, int x, int y);
+void abc_obj_print(abc_obj_t* obj);
+
+int abc_obj_set_attr (abc_obj_t* obj, int key, const char* value);
+abc_obj_t* abc_obj_get_attr (abc_obj_t* obj, int key);
+abc_obj_t* abc_obj_find_attr(abc_obj_t* obj, int key);
-int abc_obj_set_attr (abc_obj_t* obj, int key, const char* value);
-abc_obj_t* abc_obj_get_attr (abc_obj_t* obj, int key);
-abc_obj_t* abc_obj_find_attr(abc_obj_t* obj, int key);
+scf_string_t* abc_obj_to_string(abc_obj_t* obj);
#endif
typedef struct {
ngx_http_status_t status;
+
+ ngx_int_t chunk_CRLF;
+ ngx_int_t chunk_size;
+ ngx_int_t chunk_pos;
+ ngx_int_t chunked;
} ngx_http_abc_ctx_t;
#endif
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_http_abc.h"
-#if 0
+
static void ngx_http_abc_body_handler(ngx_http_request_t *r)
{
- ngx_chain_t out;
- ngx_buf_t* b;
- ngx_int_t rc;
-
- ngx_str_t type = ngx_string("text/html");
- ngx_str_t body = ngx_string("<html><head><title>hello</title></head><body><h1>hello world</h1></body></html>");
-
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_length_n = body.len;
- r->headers_out.content_type = type;
-
- rc = ngx_http_send_header(r);
-
- printf("%s(),%d, rc: %ld\n", __func__, __LINE__, rc);
-
- if (NGX_ERROR == rc || rc > NGX_OK || r->header_only) {
- ngx_http_finalize_request(r, rc);
- return;
- }
-
- b = ngx_create_temp_buf(r->pool, body.len);
- if (!b) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- ngx_memcpy(b->pos, body.data, body.len);
-
- b->last = b->pos + body.len;
- b->last_buf = 1;
-
- out.buf = b;
- out.next = NULL;
-
- rc = ngx_http_output_filter(r, &out);
-
- ngx_http_finalize_request(r, rc);
+ printf("%s(),%d\n", __func__, __LINE__);
}
-#endif
+
static ngx_int_t abc_upstream_create_request(ngx_http_request_t *r)
{
- printf("%s(),%d\n", __func__, __LINE__);
- ngx_buf_t* b;
- size_t len;
+ ngx_chain_t* cl;
+ ngx_buf_t* b;
+ size_t len;
- len = strlen("GET ") + r->uri.len + strlen(" HTTP/1.1\r\n");
+ len = r->method_name.len + 1 + r->uri.len + strlen(" HTTP/1.1\r\n");
len += strlen("Host: localhost\r\n");
len += strlen("User-Agent: nginx/1.20.0\r\n");
len += strlen("Accept: */*\r\n");
len += strlen("Connection: close\r\n\r\n");
+ if (r->request_body) {
+ len += strlen("Content-Length: \r\n") + r->headers_in.content_length->value.len;
+
+ for (cl = r->request_body->bufs; cl; cl = cl->next) {
+
+ len += (size_t)(cl->buf->last - cl->buf->pos);
+ }
+ }
+
+ printf("%s(),%d, len: %ld\n", __func__, __LINE__, len);
+
b = ngx_create_temp_buf(r->pool, len);
if (!b)
return NGX_ERROR;
b->last = b->pos + len;
- printf("%s(),%d, len: %ld\n", __func__, __LINE__, len);
+ u_char* p = ngx_snprintf(b->pos, len, "%V %V HTTP/1.1\r\nHost: localhost\r\nUser-Agent: nginx/1.20.0\r\nAccept: */*\r\nConnection: close\r\n\r\n", &r->method_name, &r->uri);
+
+ if (r->request_body) {
+ p = ngx_snprintf(p - 2, len, "Content-Length: %V\r\n\r\n", &r->headers_in.content_length->value);
+
+ for (cl = r->request_body->bufs; cl; cl = cl->next) {
+
+ len = (size_t)(cl->buf->last - cl->buf->pos);
- ngx_snprintf(b->pos, len, "GET %V HTTP/1.1\r\nHost: localhost\r\nUser-Agent: nginx/1.20.0\r\nAccept: */*\r\nConnection: close\r\n\r\n", &r->uri);
+ printf("%s(),%d, cl->buf->len: %ld\n", __func__, __LINE__, len);
+
+ ngx_memcpy(p, cl->buf->pos, len);
+ p += len;
+ }
+ }
r->upstream->request_bufs = ngx_alloc_chain_link(r->pool);
if (!r->upstream->request_bufs)
r->upstream->request_bufs->buf = b;
r->upstream->request_bufs->next = NULL;
+ r->upstream->request_body_sent = 0;
r->upstream->request_sent = 0;
r->upstream->header_sent = 0;
r->header_hash = 1;
ngx_http_upstream_main_conf_t* umcf;
ngx_http_upstream_header_t* uh;
ngx_http_upstream_t* u;
+ ngx_http_abc_ctx_t* ctx;
ngx_table_elt_t* h;
ngx_int_t rc;
ngx_memcpy(h->value.data, r->header_start, h->value.len);
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
+ if (!ngx_strcmp(h->key.data, "Transfer-Encoding") && !ngx_strcmp(h->value.data, "chunked")) {
+ ctx = ngx_http_get_module_ctx(r, ngx_http_abc_module);
+ ctx->chunked = 1;
+ }
+
uint8_t buf[1024] = {0};
ngx_snprintf(buf, 1023, "%V: %V\n", &h->key, &h->value);
printf("%s(),%d, %s\n", __func__, __LINE__, buf);
static void abc_upstream_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
{
printf("%s(),%d\n\n", __func__, __LINE__);
+
+ if (NGX_HTTP_POST & r->method)
+ ngx_http_finalize_request(r, rc);
+}
+
+static ngx_int_t abc_input_filter_init(void *data)
+{
+ return NGX_OK;
+}
+
+static ngx_int_t abc_input_filter(void *data, ssize_t bytes)
+{
+ ngx_http_request_t *r = data;
+
+ ngx_buf_t *b;
+ ngx_chain_t *cl, **ll;
+ ngx_chain_t *cl2;
+ ngx_http_upstream_t *u;
+ ngx_http_abc_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(r, ngx_http_abc_module);
+
+ u = r->upstream;
+
+ if (u->length == 0) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "upstream sent more data than specified in "
+ "\"Content-Length\" header");
+ return NGX_OK;
+ }
+
+ for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
+ ll = &cl->next;
+ }
+
+ cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ll = cl;
+
+ cl->buf->flush = 1;
+ cl->buf->memory = 1;
+
+ b = &u->buffer;
+
+ cl->buf->pos = b->last;
+ b->last += bytes;
+ cl->buf->last = b->last;
+ cl->buf->tag = u->output.tag;
+
+ if (u->length == -1) {
+
+ if (!ctx->chunked)
+ return NGX_OK;
+
+ u_char* p = cl->buf->pos;
+ u_char ch;
+
+ while (p < b->last) {
+ if (ctx->chunk_CRLF < 2) {
+
+ ch = *p++;
+ cl->buf->pos = p;
+
+ printf("%s(),%d, ctx->chunk_size: %ld,%#lx, ch: %d,%c\n", __func__, __LINE__, ctx->chunk_size, ctx->chunk_size, ch, ch);
+
+ if ('0' <= ch && ch <= '9') {
+
+ ctx->chunk_size <<= 4;
+ ctx->chunk_size += ch - '0';
+
+ } else if ('a' <= ch && ch <= 'f') {
+
+ ctx->chunk_size <<= 4;
+ ctx->chunk_size += ch - 'a' + 10;
+
+ } else if ('A' <= ch && ch <= 'F') {
+
+ ctx->chunk_size <<= 4;
+ ctx->chunk_size += ch - 'A' + 10;
+ } else {
+ if ('\r' == ch || '\n' == ch)
+ ctx->chunk_CRLF++;
+ }
+ } else {
+ ngx_int_t len = (size_t)(b->last - p);
+
+ if (ctx->chunk_pos + len <= ctx->chunk_size) {
+ printf("%s(),%d, ctx->chunk_size: %ld,%#lx, len: %ld\n", __func__, __LINE__, ctx->chunk_size, ctx->chunk_size, len);
+ ctx->chunk_pos += len;
+ p += len;
+ } else if (ctx->chunk_CRLF < 3) {
+ ctx->chunk_CRLF++;
+
+ len = ctx->chunk_size - ctx->chunk_pos;
+ p += len;
+
+ ctx->chunk_pos += len;
+ printf("%s(),%d, ctx->chunk_size: %ld,%#lx, len: %ld\n", __func__, __LINE__, ctx->chunk_size, ctx->chunk_size, len);
+
+ if (len > 0) {
+ cl->buf->last = p;
+
+ cl2 = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
+ if (NULL == cl2)
+ return NGX_ERROR;
+
+ cl2->buf->flush = 1;
+ cl2->buf->memory = 1;
+
+ cl2->buf->pos = p;
+ cl2->buf->last = b->last;
+ cl2->buf->tag = u->output.tag;
+
+ ll = &cl->next;
+ *ll = cl2;
+ cl = cl2;
+ }
+ } else {
+ ch = *p++;
+
+ cl->buf->pos++;
+ ctx->chunk_CRLF++;
+
+ printf("%s(),%d, ctx->chunk_size: %ld,%#lx, len: %ld, ch: %d\n", __func__, __LINE__, ctx->chunk_size, ctx->chunk_size, len, ch);
+
+ if (ctx->chunk_CRLF >= 5) {
+ ctx->chunk_CRLF = 0;
+ ctx->chunk_size = 0;
+ ctx->chunk_pos = 0;
+ }
+
+ if (cl->buf->pos == cl->buf->last) {
+ //printf("%s(),%d, 0 size buf: %p, p == b->last: %d\n", __func__, __LINE__, cl, p == b->last);
+ *ll = NULL;
+ ngx_free_chain(r->pool, cl);
+ cl = NULL;
+ }
+ }
+ }
+ }
+
+ return NGX_OK;
+ }
+
+ if (bytes > u->length) {
+
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "upstream sent more data than specified in "
+ "\"Content-Length\" header");
+
+ cl->buf->last = cl->buf->pos + u->length;
+ u->length = 0;
+
+ return NGX_OK;
+ }
+
+ u->length -= bytes;
+
+ return NGX_OK;
}
static ngx_int_t ngx_http_abc_handler(ngx_http_request_t *r)
ngx_http_abc_ctx_t* ctx;
ngx_int_t rc;
- if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_POST)))
- return NGX_HTTP_NOT_ALLOWED;
+ if (r->method & NGX_HTTP_GET) {
- r->request_body_in_file_only = 1;
+ rc = ngx_http_discard_request_body(r);
+ if (rc != NGX_OK)
+ return rc;
-// rc = ngx_http_read_client_request_body(r, ngx_http_abc_body_handler);
- rc = ngx_http_discard_request_body(r);
- if (rc != NGX_OK)
- return rc;
+ } else if (r->method & NGX_HTTP_POST) {
+ r->request_body_no_buffering = 1;
+
+ rc = ngx_http_read_client_request_body(r, ngx_http_abc_body_handler);
+
+ if (rc != NGX_OK && rc != NGX_AGAIN) {
+ printf("%s(),%d, rc: %ld\n", __func__, __LINE__, rc);
+ return rc;
+ }
+ } else
+ return NGX_HTTP_NOT_ALLOWED;
ctx = ngx_http_get_module_ctx(r, ngx_http_abc_module);
if (!ctx) {
ctx->status.count = 0;
ctx->status.start = NULL;
ctx->status.end = NULL;
+
+ ctx->chunk_CRLF = 0;
+ ctx->chunk_size = 0;
+ ctx->chunk_pos = 0;
+ ctx->chunked = 0;
}
if (ngx_http_upstream_create(r) != NGX_OK)
u->resolved->port = 80;
- u->create_request = abc_upstream_create_request;
- u->process_header = abc_upstream_process_status;
- u->finalize_request = abc_upstream_finalize_request;
+ u->create_request = abc_upstream_create_request;
+ u->process_header = abc_upstream_process_status;
+ u->finalize_request = abc_upstream_finalize_request;
+
+ u->input_filter_init = abc_input_filter_init;
+ u->input_filter = abc_input_filter;
+ u->input_filter_ctx = r;
r->main->count++;
ngx_http_upstream_init(r);
- printf("%s(),%d, subrequest_in_memory: %d\n", __func__, __LINE__, r->subrequest_in_memory);
+ printf("%s(), %d, done\n", __func__, __LINE__);
return NGX_DONE;
}
CFILES += abc_layout_form.c
CFILES += abc_layout_label.c
CFILES += abc_layout_input.c
+CFILES += abc_layout_td.c
CFILES += abc_render.c
CFILES += abc_render_html.c
CFILES += abc_render_title.c
+CFILES += abc_render_meta.c
CFILES += abc_render_head.c
CFILES += abc_render_body.c
CFILES += abc_render_div.c
+
CFILES += abc_render_h1.c
CFILES += abc_render_a.c
CFILES += abc_render_a_href.c
CFILES += abc_render_label.c
CFILES += abc_render_input.c
+CFILES += abc_render_table.c
+CFILES += abc_render_tr.c
+CFILES += abc_render_td.c
+
CFILES += ../html/abc_html.c
CFILES += ../html/abc_html_util.c
CFILES += ../html/abc_obj.c
int abc_layout_label(abc_layout_t* layout, abc_obj_t* obj, int width, int height);
int abc_layout_input(abc_layout_t* layout, abc_obj_t* obj, int width, int height);
+int abc_layout_td (abc_layout_t* layout, abc_obj_t* obj, int width, int height);
+
+int abc_layout_empty(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
+{
+ return 0;
+}
+
static abc_layout_pt abc_layouts[ABC_HTML_NB] =
{
[ABC_HTML] = abc_layout_html,
[ABC_HTML_BODY] = abc_layout_body,
[ABC_HTML_DIV] = abc_layout_div,
+ [ABC_HTML_META] = abc_layout_empty,
+
[ABC_HTML_H1] = abc_layout_h1,
[ABC_HTML_H2] = abc_layout_h1,
[ABC_HTML_H3] = abc_layout_h1,
[ABC_HTML_FORM] = abc_layout_form,
[ABC_HTML_LABEL] = abc_layout_label,
[ABC_HTML_INPUT] = abc_layout_input,
+
+ [ABC_HTML_TABLE] = abc_layout_empty,
+ [ABC_HTML_TR] = abc_layout_empty,
+ [ABC_HTML_TD] = abc_layout_td,
};
int abc_layout_obj(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
break;
case ABC_HTML_BR:
+ case ABC_HTML_TR:
x = root->x + 4;
y += h;
h = 0;
obj->w = (obj->w + 3) & ~0x3;
obj->h = (obj->h + 3) & ~0x3;
- scf_logi("%s, w: %d, h: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg\n",
+ scf_logd("%s, w: %d, h: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg\n",
obj->text->data, obj->w, obj->h,
extents.x_bearing, extents.y_bearing, extents.width, extents.height,
extents.x_advance, extents.y_advance);
--- /dev/null
+#include"abc.h"
+
+int abc_layout_td(abc_layout_t* layout, abc_obj_t* obj, int width, int height)
+{
+ abc_obj_t* attr;
+ cairo_text_extents_t extents;
+ cairo_surface_t* surface;
+ cairo_t* cr;
+
+ if (!obj->text)
+ return 0;
+
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+ cr = cairo_create(surface);
+
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
+ if (attr)
+ cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
+ if (attr)
+ cairo_set_font_size(cr, atoi(attr->value->data));
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_text_extents(cr, obj->text->data, &extents);
+
+// obj->x = 4;
+// obj->y = 4;
+ obj->w = extents.width + extents.x_bearing;
+ obj->h = extents.height + extents.height / 2;
+
+ obj->w = (obj->w + 3) & ~0x3;
+ obj->h = (obj->h + 3) & ~0x3;
+
+ scf_logd("%s, w: %d, h: %d, x_bearing: %lg, y_bearing: %lg, width: %lg, height: %lg, x_advance: %lg, y_advance: %lg\n",
+ obj->text->data, obj->w, obj->h,
+ extents.x_bearing, extents.y_bearing, extents.width, extents.height,
+ extents.x_advance, extents.y_advance);
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+ return 0;
+}
extern abc_render_t abc_render_head;
extern abc_render_t abc_render_body;
+extern abc_render_t abc_render_meta;
extern abc_render_t abc_render_div;
extern abc_render_t abc_render_h1;
extern abc_render_t abc_render_label;
extern abc_render_t abc_render_input;
+extern abc_render_t abc_render_table;
+extern abc_render_t abc_render_tr;
+extern abc_render_t abc_render_td;
+
+
static abc_render_t* abc_renders[ABC_HTML_NB] =
{
[ABC_HTML] = &abc_render_html,
[ABC_HTML_HEAD] = &abc_render_head,
[ABC_HTML_BODY] = &abc_render_body,
[ABC_HTML_DIV] = &abc_render_div,
+ [ABC_HTML_META] = &abc_render_meta,
[ABC_HTML_H1] = &abc_render_h1,
[ABC_HTML_H2] = &abc_render_h1,
[ABC_HTML_FORM] = &abc_render_form,
[ABC_HTML_LABEL] = &abc_render_label,
[ABC_HTML_INPUT] = &abc_render_input,
+
+ [ABC_HTML_TABLE] = &abc_render_table,
+ [ABC_HTML_TR] = &abc_render_tr,
+ [ABC_HTML_TD] = &abc_render_td,
};
int abc_renders_fini()
float mvp[16];
__compute_mvp(mvp, 0, 0, 0);
- scf_logi("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
+ scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
GLfloat vert_update[] =
{
--- /dev/null
+#include"abc.h"
+
+static int _render_fini_meta(abc_render_t* render)
+{
+ return 0;
+}
+
+static int _render_draw_meta(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+ return 0;
+}
+
+abc_render_t abc_render_meta =
+{
+ .type = ABC_HTML_META,
+
+ .draw = _render_draw_meta,
+ .fini = _render_fini_meta,
+};
--- /dev/null
+#include"abc.h"
+
+static const char* vert_shader =
+ "#version 330 core\n"
+ "layout(location = 0) in vec4 position; \n"
+ "layout(location = 1) in vec2 a_texCoord; \n"
+ "out vec2 v_texCoord; \n"
+ "unitable mat4 mvp; \n"
+ "void main() { \n"
+ "gl_Position = mvp * position; \n"
+ "v_texCoord = a_texCoord; \n"
+ "} \n";
+
+static const char* frag_shader =
+ "#version 330 core\n"
+ "in vec2 v_texCoord; \n"
+ "out vec4 outputColor; \n"
+ "unitable sampler2D tex_rgba; \n"
+ "void main() { \n"
+ " vec2 xy = v_texCoord; \n"
+ " vec4 v = texture2D(tex_rgba, xy).rgba; \n"
+ " outputColor = vec4(v.b, v.g, v.r, 1.0); \n"
+ "} \n";
+
+
+static GLuint program = 0;
+
+static GLuint vao = 0;
+static GLuint buffers[2] = {0};
+static GLuint texture_rgba = 0;
+
+static GLuint uniform_mvp;
+static GLuint uniform_rgba;
+
+
+static int _render_fini_table(abc_render_t* render)
+{
+ return 0;
+}
+
+static int _render_draw_table(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+ if (!obj->text)
+ return 0;
+
+ if (0 == program)
+ __init_program(&program, vert_shader, frag_shader);
+
+ if (0 == vao)
+ __init_buffers(&vao, buffers);
+
+ if (0 == texture_rgba)
+ __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL);
+
+ abc_obj_t* attr;
+ cairo_text_extents_t extents;
+ cairo_surface_t* surface;
+ cairo_t* cr;
+
+ uint8_t* bgra = calloc(1, obj->w * obj->h * 4);
+ if (!bgra)
+ return -ENOMEM;
+
+ surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, obj->w, obj->h, obj->w * 4);
+ cr = cairo_create(surface);
+
+ cairo_set_line_width(cr, 1);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_rectangle(cr, 0, 0, obj->w, obj->h);
+ cairo_fill(cr);
+ cairo_stroke(cr);
+
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
+ if (attr)
+ cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
+ if (attr)
+ cairo_set_font_size(cr, atoi(attr->value->data));
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_text_extents(cr, obj->text->data, &extents);
+
+ cairo_move_to (cr, extents.x_bearing, -extents.y_bearing);
+ cairo_show_text(cr, obj->text->data);
+
+// cairo_surface_write_to_png(surface, "tmp.png");
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+ surface = NULL;
+ cr = NULL;
+
+ float mvp[16];
+ __compute_mvp(mvp, 0, 0, 0);
+
+ scf_logi("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
+
+ GLfloat vert_update[] =
+ {
+ 2.0 * obj->x / (float)width - 1.0,
+ -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+ 2.0 * (obj->x + obj->w) / (float)width - 1.0,
+ -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+ 2.0 * obj->x / (float)width - 1.0,
+ -2.0 * obj->y / (float)height + 1.0,
+
+ 2.0 * (obj->x + obj->w) / (float)width - 1.0,
+ -2.0 * obj->y / (float)height + 1.0,
+ };
+
+ glUseProgram(program);
+ uniform_rgba = glGetUniformLocation(program, "tex_rgba");
+ uniform_mvp = glGetUniformLocation(program, "mvp");
+
+ glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
+
+ // board
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture (GL_TEXTURE_2D, texture_rgba);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, obj->w, obj->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);
+ glUniform1i(uniform_rgba, 0);
+
+ // draw
+ glBindBuffer (GL_ARRAY_BUFFER, buffers[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
+
+ glBindVertexArray(vao);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ free(bgra);
+ return 0;
+}
+
+abc_render_t abc_render_table =
+{
+ .type = ABC_HTML_TABLE,
+
+ .draw = _render_draw_table,
+ .fini = _render_fini_table,
+};
--- /dev/null
+#include"abc.h"
+
+static const char* vert_shader =
+ "#version 330 core\n"
+ "layout(location = 0) in vec4 position; \n"
+ "layout(location = 1) in vec2 a_texCoord; \n"
+ "out vec2 v_texCoord; \n"
+ "uniform mat4 mvp; \n"
+ "void main() { \n"
+ "gl_Position = mvp * position; \n"
+ "v_texCoord = a_texCoord; \n"
+ "} \n";
+
+static const char* frag_shader =
+ "#version 330 core\n"
+ "in vec2 v_texCoord; \n"
+ "out vec4 outputColor; \n"
+ "uniform sampler2D tex_rgba; \n"
+ "void main() { \n"
+ " vec2 xy = v_texCoord; \n"
+ " vec4 v = texture2D(tex_rgba, xy).rgba; \n"
+ " outputColor = vec4(v.b, v.g, v.r, 1.0); \n"
+ "} \n";
+
+
+static GLuint program = 0;
+
+static GLuint vao = 0;
+static GLuint buffers[2] = {0};
+static GLuint texture_rgba = 0;
+
+static GLuint uniform_mvp;
+static GLuint uniform_rgba;
+
+
+static int _render_fini_td(abc_render_t* render)
+{
+ return 0;
+}
+
+static int _render_draw_td(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+ if (!obj->text)
+ return 0;
+
+ if (0 == program)
+ __init_program(&program, vert_shader, frag_shader);
+
+ if (0 == vao)
+ __init_buffers(&vao, buffers);
+
+ if (0 == texture_rgba)
+ __init_texture(&texture_rgba, GL_RGBA, obj->w, obj->h, NULL);
+
+ abc_obj_t* attr;
+ cairo_text_extents_t extents;
+ cairo_surface_t* surface;
+ cairo_t* cr;
+
+ uint8_t* bgra = calloc(1, obj->w * obj->h * 4);
+ if (!bgra)
+ return -ENOMEM;
+
+ surface = cairo_image_surface_create_for_data(bgra, CAIRO_FORMAT_ARGB32, obj->w, obj->h, obj->w * 4);
+ cr = cairo_create(surface);
+
+ cairo_set_line_width(cr, 1);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_rectangle(cr, 0, 0, obj->w, obj->h);
+ cairo_fill(cr);
+ cairo_stroke(cr);
+
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT);
+ if (attr)
+ cairo_select_font_face(cr, attr->value->data, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+
+ attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_FONT_SIZE);
+ if (attr)
+ cairo_set_font_size(cr, atoi(attr->value->data));
+
+ cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
+ cairo_text_extents(cr, obj->text->data, &extents);
+
+ cairo_move_to (cr, extents.x_bearing, -extents.y_bearing);
+ cairo_show_text(cr, obj->text->data);
+
+// cairo_surface_write_to_png(surface, "tmp.png");
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+ surface = NULL;
+ cr = NULL;
+
+ float mvp[16];
+ __compute_mvp(mvp, 0, 0, 0);
+
+ scf_logd("%s, x: %d, y: %d, w: %d, h: %d\n", obj->text->data, obj->x, obj->y, obj->w, obj->h);
+
+ GLfloat vert_update[] =
+ {
+ 2.0 * obj->x / (float)width - 1.0,
+ -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+ 2.0 * (obj->x + obj->w) / (float)width - 1.0,
+ -2.0 * (obj->y + obj->h) / (float)height + 1.0,
+
+ 2.0 * obj->x / (float)width - 1.0,
+ -2.0 * obj->y / (float)height + 1.0,
+
+ 2.0 * (obj->x + obj->w) / (float)width - 1.0,
+ -2.0 * obj->y / (float)height + 1.0,
+ };
+
+ glUseProgram(program);
+ uniform_rgba = glGetUniformLocation(program, "tex_rgba");
+ uniform_mvp = glGetUniformLocation(program, "mvp");
+
+ glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
+
+ // board
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture (GL_TEXTURE_2D, texture_rgba);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, obj->w, obj->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);
+ glUniform1i(uniform_rgba, 0);
+
+ // draw
+ glBindBuffer (GL_ARRAY_BUFFER, buffers[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
+
+ glBindVertexArray(vao);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ free(bgra);
+ return 0;
+}
+
+abc_render_t abc_render_td =
+{
+ .type = ABC_HTML_TD,
+
+ .draw = _render_draw_td,
+ .fini = _render_fini_td,
+};
--- /dev/null
+#include"abc.h"
+
+static int _render_fini_tr(abc_render_t* render)
+{
+ return 0;
+}
+
+static int _render_draw_tr(abc_render_t* render, abc_obj_t* obj, int width, int height)
+{
+ return 0;
+}
+
+abc_render_t abc_render_tr =
+{
+ .type = ABC_HTML_TR,
+
+ .draw = _render_draw_tr,
+ .fini = _render_fini_tr,
+};
GdkWindow* window;
GdkCursor* cursor;
+ if (!ctx->current->download)
+ return 0;
+
+ if (!ctx->current->root)
+ return 0;
+
abc_obj_t* prev = ctx->current->current;
abc_obj_t* obj = abc_obj_find(ctx->current->root, x, y);
abc_obj_t* attr;
}
if (obj) {
- scf_logd("obj: %s, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n",
- obj->key->data, obj->x, obj->y, obj->w, obj->h, x, y);
+ scf_logd("obj: %s, type: %d, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n",
+ obj->keys[0], obj->type, obj->x, obj->y, obj->w, obj->h, x, y);
switch (obj->type) {
static int __do_button_release(abc_ctx_t* ctx, int x, int y)
{
- abc_obj_t* attr;
- abc_obj_t* obj = abc_obj_find(ctx->current->root, x, y);
+ abc_html_t* html;
+ abc_obj_t* attr;
+ abc_obj_t* obj = abc_obj_find(ctx->current->root, x, y);
if (!obj)
return -ENOMEM;
attr = abc_obj_find_attr(obj, ABC_HTML_ATTR_TYPE);
if (!strcmp(attr->value->data, "submit")) {
- abc_obj_print(ctx->current->root);
+ html = NULL;
+
+ int ret = abc_html_post(&html, ctx->current, obj);
+ if (ret < 0)
+ return ret;
+
+ scf_list_add_tail(&ctx->html_list, &html->list);
+
+ ctx->current = html;
return 0;
}
abc_obj_t* obj;
if (ctx->current) {
- obj = ctx->current->current;
+ if (!ctx->current->download)
+ return TRUE;
+
+ if (!ctx->current->root) {
+ int ret = abc_html_parse(ctx->current);
+ if (ret < 0) {
+ abc_obj_free(ctx->current->root);
+ ctx->current->root = NULL;
+ return TRUE;
+ }
+
+ ctx->current->root->gtk_builder = ctx->builder;
+ ctx->current->current = ctx->current->root;
+ gtk_widget_set_sensitive(GTK_WIDGET(ctx->back), TRUE);
+ gtk_gl_area_queue_render(ctx->gl_area);
+ }
+
+ obj = ctx->current->current;
if (obj) {
obj->jiffies++;
gtk_gl_area_queue_render(ctx->gl_area);