diff -pur dillo-0.2.4/src/dw_page.c dillo-0.2.4.map/src/dw_page.c --- dillo-0.2.4/src/dw_page.c Sun Aug 27 22:51:41 2000 +++ dillo-0.2.4.map/src/dw_page.c Sun Sep 3 21:47:20 2000 @@ -596,11 +596,17 @@ static gint Dw_page_find_link(DwPage *pa { gint line_index; gint word_index; - gint x_cursor; + gint x_cursor, last_x_cursor; gint x1, y1; /* coordinates relative to page */ + gint x0, y0; /* coordinates relative to word */ DwPageLine *line; + DwPageWord *word; DwContainer *container; + DwPageShape *shape; + int dx,dy; + int num_shape; + guint map; container = a_Dw_find_container(&page->dw); if (container == NULL) @@ -610,15 +616,60 @@ static gint Dw_page_find_link(DwPage *pa y1 = y - (container->y_offset + page->dw.allocation.y0); line_index = Dw_page_find_line_index(page, y1); + x0 = x1; + y0 = y1 - page->lines[line_index].y_top; + page->x_click = -1; + if (line_index >= page->num_lines) return -1; line = &page->lines[line_index]; x_cursor = Dw_page_line_x_offset(page, line); for (word_index = 0; word_index < line->num_words; word_index++) { word = &line->words[word_index]; - if (x_cursor <= x1 && x_cursor + word->x_size + word->x_space > x1) - return page->attrs[word->attr].link; + last_x_cursor = x_cursor; x_cursor += word->x_size + word->x_space; + if (last_x_cursor <= x1 && x_cursor > x1) { + // page->x_click = word->attr; + // page->y_click = page->attrs[word->attr].flags; + + if(page->attrs[word->attr].link >= 0) { + if(page->attrs[word->attr].flags & DW_PAGE_HAS_MAP) { + page->x_click = x0; + page->y_click = y0; + } + else + page->x_click = -1; + return page->attrs[word->attr].link; + } + else if (page->attrs[word->attr].flags & DW_PAGE_HAS_MAP) { + //page->x_click = x0; + //page->y_click = y0; + map = page->attrs[word->attr].map; + for ( num_shape=0 ; num_shapenum_shapes ; num_shape++) { + shape = &(page->shapes[num_shape]); + if(shape->map == map) { + if(shape->type == DW_PAGE_SHAPE_CIRCLE) { + dx = shape->data.circle.x - x0; + dy = shape->data.circle.y - y0; + if(shape->data.circle.r2>=(dx*dx+dy*dy)) + return shape->link; + } + else if(shape->type == DW_PAGE_SHAPE_RECT) { + if(x0>shape->data.rect.left + && x0data.rect.right + && y0>shape->data.rect.top + && y0data.rect.bottom + ) + return shape->link; + } + else if(shape->type == DW_PAGE_SHAPE_POLY) { + if(gdk_region_point_in (shape->data.poly, x0, y0)) + return shape->link; + } + } + } + } + } } return -1; } @@ -636,6 +687,7 @@ static void Dw_page_handle_event(Dw *dw, guint c; GdkCursor *cursor; + char full_url[1024]; switch (event->type) { case GDK_BUTTON_PRESS: @@ -701,8 +753,21 @@ static void Dw_page_handle_event(Dw *dw, g_print("dw_page_handle_event: link %s\n", page->links[page->link_pressed].url); #endif - if (page->link != NULL) - (*page->link) (page->link_data, page->links[link_pressed].url); + if (page->link != NULL) { + /* + * todo: How do we pass these datas to the server ? + * Url.c functions can't deal with that yet + */ + if(page->x_click>0) { + sprintf(full_url,"%s?%d,%d", + page->links[link_pressed].url, + page->x_click,page->y_click); + (*page->link) (page->link_data, full_url); + } + else + (*page->link) (page->link_data, page->links[link_pressed].url); + } + page->x_click = -1; } } break; @@ -710,16 +775,28 @@ static void Dw_page_handle_event(Dw *dw, case GDK_MOTION_NOTIFY: motion = (GdkEventMotion *) event; hover_link = Dw_page_find_link(page, motion->x, motion->y); - if (page->status != NULL && page->hover_link != hover_link) { - if (hover_link >= 0) { + if (page->status != NULL) { + if(page->x_click>=0) { c = GDK_HAND2; - (*page->status) (page->status_data, page->links[hover_link].url); - } else { - c = GDK_LEFT_PTR; - (*page->status) (page->status_data, ""); - } - cursor = gdk_cursor_new(c); + sprintf(page->ismap_coords,"?%d,%d",page->x_click,page->y_click); + (*page->status) (page->status_data, page->ismap_coords); + } else if(page->hover_link != hover_link) { + if (hover_link >= 0) { + c = GDK_HAND2; + if (page->links[hover_link].alt) + (*page->status) (page->status_data, page->links[hover_link].alt); + else + (*page->status) (page->status_data, page->links[hover_link].url); + } + else { + c = GDK_LEFT_PTR; + (*page->status) (page->status_data, ""); + } + } else + break; + cursor = gdk_cursor_new(c); + /* -RL :: I don't like this form so much :( */ gdk_window_set_cursor((((BrowserWindow *) (page->status_data))->docwin)->window, @@ -790,6 +867,7 @@ static void Dw_page_destroy(Dw *dw) gint link_index; page = (DwPage *) dw; + /* Destroy links to us! */ if (page->Parent) { *(page->Parent) = NULL; @@ -821,12 +899,16 @@ static void Dw_page_destroy(Dw *dw) } #endif + g_free(page->shapes); + g_hash_table_destroy (page->anchors_table); g_free(page->fonts); g_free(page->colors); g_free(page->attrs); - for (link_index = 0; link_index < page->num_links; link_index++) + for (link_index = 0; link_index < page->num_links; link_index++) { g_free(page->links[link_index].url); + g_free(page->links[link_index].alt); + } g_free(page->links); if(page->gc != NULL) gdk_gc_unref(page->gc); @@ -939,6 +1021,15 @@ Dw *a_Dw_page_new(Dw **Parent) Dw_page->bgnd_color = prefs.bg_color; Dw_page->anchors_table = g_hash_table_new(g_str_hash, g_str_equal); + + /* We use the hash as a key, so we'll only need a direct hash table */ + /* Hopefully g_str_hash() has no collision */ + //Dw_page->current_map = g_str_hash("#null"); + Dw_page->x_click = -1; + Dw_page->current_map = 0; + Dw_page->num_shapes = 0; + Dw_page->num_shapes_max = 8; /* not a critical value */ + Dw_page->shapes = g_new(DwPageShape, Dw_page->num_shapes_max); return (Dw *) Dw_page; } @@ -1000,11 +1091,12 @@ gint a_Dw_page_find_color(DwPage *page, void a_Dw_page_init_attr(DwPage *page, DwPageAttr *attr) { attr->link = -1; + attr->map = 0; attr->color = a_Dw_page_find_color(page, 0); attr->left_indent_first = 0; attr->left_indent_rest = 0; attr->right_indent = 0; - attr->align = DW_PAGE_ALIGN_LEFT; + attr->flags = DW_PAGE_ALIGN_LEFT; } /* @@ -1038,13 +1131,14 @@ gint a_Dw_page_find_font(DwPage *page, c /* * Create a new link, return the index. */ -gint a_Dw_page_new_link(DwPage *page, const char *url) +gint a_Dw_page_new_link(DwPage *page, const char *url, const char *alt) { gint nl; nl = page->num_links; a_List_add(page->links, nl, sizeof(*page->links), page->num_links_max); page->links[nl].url = g_strdup(url); + page->links[nl].alt = g_strdup(alt); return page->num_links++; } diff -pur dillo-0.2.4/src/dw_page.h dillo-0.2.4.map/src/dw_page.h --- dillo-0.2.4/src/dw_page.h Mon Aug 21 06:27:44 2000 +++ dillo-0.2.4.map/src/dw_page.h Sun Sep 3 12:56:28 2000 @@ -21,6 +21,7 @@ typedef struct _DwPageLink DwPageLink typedef struct _DwPageAttr DwPageAttr; typedef struct _DwPageLine DwPageLine; typedef struct _DwPageWord DwPageWord; +typedef struct _DwPageShape DwPageShape; struct _DwPageFont { char *name; @@ -38,27 +39,71 @@ struct _DwPageFont { struct _DwPageLink { char *url; + char *alt; }; +#define DW_PAGE_SHAPE_ERROR 0 +#define DW_PAGE_SHAPE_DEFAULT 1 +#define DW_PAGE_SHAPE_CIRCLE 2 +#define DW_PAGE_SHAPE_RECT 3 +#define DW_PAGE_SHAPE_POLY 4 + +struct _DwPageShape { + guint map; + gint type; + gint link; + + union { + GdkRegion *poly; + struct { + int x; + int y; + int r2; + } circle; + struct { + int top; + int bottom; + int left; + int right; + } rect; + } data; +}; + +/* + * Link finding rules: + * ------------------- + * if (DwPageAttr->link) + * if (DwPageAttr HAS_MAP) + * // add server-side map informations to url + * else + * // regular link + * else if (DwPageAttr HAS_MAP) + * // client-side image map with (shapes) + */ struct _DwPageAttr { gint font; gint link; + guint map; gint32 color; gint left_indent_first; gint left_indent_rest; gint right_indent; - gint align; + gint flags; /* -EG :: was align */ }; -#define DW_PAGE_ALIGN_LEFT 0 -#define DW_PAGE_ALIGN_CENTER 1 -#define DW_PAGE_ALIGN_RIGHT 2 +/* these defines are DwPageAttr->flags + * ALIGN_LEFT == ALIGN_RIGTH ==0 -> CENTER + * ALIGN_LEFT == ALIGN_RIGTH ==1 -> JUSTIFIED */ +#define DW_PAGE_ALIGN_LEFT 1 +#define DW_PAGE_ALIGN_RIGHT 2 +#define DW_PAGE_HAS_MAP 4 struct _DwPageLine { gint num_words; gint num_words_max; /* number allocated */ + gint y_top; gint x_size, y_ascent, y_descent, y_space; gboolean hard; /* false = soft break, true = hard break */ @@ -100,6 +145,16 @@ struct _DwPage { * Value: int (pixel offset [1 based]) */ GHashTable *anchors_table; + /* Page's maps + * Key: guint = g_str_hash(char* map) + * Value: num_shapes+1 */ + DwPageShape *shapes; + gint num_shapes; + gint num_shapes_max; /* number allocated */ + guint current_map; + gint x_click, y_click; + char ismap_coords[10]; + gint width; /* the width (not including pad) at which line wrap was calculated. If this changes, then the whole thing should get re-wrapped. */ @@ -168,7 +223,7 @@ void a_Dw_page_update_end (DwPage *page) void a_Dw_page_init_attr (DwPage *page, DwPageAttr *attr); gint a_Dw_page_find_font (DwPage *page, const DwPageFont *font); -gint a_Dw_page_new_link (DwPage *page, const char *url); +gint a_Dw_page_new_link(DwPage *page, const char *url, const char *alt); gint a_Dw_page_find_color (DwPage *page, gint32 color); gint a_Dw_page_add_attr (DwPage *page, const DwPageAttr *attr); void a_Dw_page_add_text (DwPage *page, char *text, gint attr); diff -pur dillo-0.2.4/src/html.c dillo-0.2.4.map/src/html.c --- dillo-0.2.4/src/html.c Mon Aug 21 06:29:23 2000 +++ dillo-0.2.4.map/src/html.c Sun Sep 3 21:52:15 2000 @@ -783,7 +783,11 @@ static void Html_tag_open_img(DilloHtml gint width, height; char *alt_ptr; Dw *dw; + DwPage *page = (DwPage *)html->dw; + DwPageAttr attr; + char tmp[1024]; + char *ptmp = tmp; if ( !Html_get_attr(tag, tagsize, "src", src, sizeof(src)) ) return; @@ -791,6 +795,7 @@ static void Html_tag_open_img(DilloHtml if ( !url ) return; + attr = page->attrs[html->stack[html->stack_top].attr]; width = 0; if (Html_get_attr(tag, tagsize, "width", num, sizeof(num))) width = atoi(num); @@ -800,6 +805,23 @@ static void Html_tag_open_img(DilloHtml alt_ptr = NULL; if (Html_get_attr(tag, tagsize, "alt", alt, sizeof(alt))) alt_ptr = alt; + if (Html_get_attr(tag, tagsize, "ismap", tmp, sizeof(tmp))) { + /* BUG: if several ISMAP images follow each other without + * being separated with a word, only the first one is ISMAPed + */ + attr.flags |= DW_PAGE_HAS_MAP; + g_print(" Html_tag_open_img: server-side map (ISMAP)\n"); + } + if (Html_get_attr(tag, tagsize, "usemap", tmp, sizeof(tmp))) { + /* todo: usemap can be any URI. + * For now we only understand "#map" */ + while(*(ptmp++)!='#'); + attr.link = -1; + attr.map = g_str_hash(ptmp); + attr.flags |= DW_PAGE_HAS_MAP; + attr.color = a_Dw_page_find_color(page, page->link_color); + g_print(" Html_tag_open_img: using map \"%s\" (%d)\n",ptmp,attr.map); + } imgsink = a_Image_new(0, 0, alt_ptr, page->bgnd_color); dw = (Dw *) imgsink->dw; @@ -811,9 +833,180 @@ static void Html_tag_open_img(DilloHtml /* Dereference the link block */ Html_lb_free(html->linkblock); + html->stack[html->stack_top].attr = a_Dw_page_add_attr(page, &attr); a_Dw_page_add_widget((DwPage *) html->dw, dw, html->stack[html->stack_top].attr); g_free(url); + + /* BUG: What an ugly workaround for having the following words + * get the previous attr !!! Somebody please fix that -EG */ + attr = page->attrs[html->stack[html->stack_top-1].attr]; + html->stack[html->stack_top].attr = a_Dw_page_add_attr(page, &attr); +} + +/* + * ? + */ +static void Html_tag_open_map(DilloHtml *html, char *tag, gint tagsize) +{ + DwPage *page = (DwPage *) html->dw; + char name[1024]; + + Html_push_tag(html, tag, tagsize); + + if (!page->current_map) { /* no already open_map */ + if ( Html_get_attr(tag, tagsize, "name", name, sizeof(name)) ) { + page->current_map = g_str_hash(name); + // g_print(" Html_tag_open_map: \"%s\" (%d)\n",name,page->current_map); + } + } +} + +/* + * ? + */ +static void Html_tag_close_map(DilloHtml *html, char *tag, gint tagsize) +{ + DwPage *page = (DwPage *) html->dw; + + page->current_map = 0; + Html_pop_tag(html, tag, tagsize); +} + +/* + * Read coords in a string and fill a GdkPoint array + */ +static int Html_read_coords(char *str, GdkPoint *array) +{ + int i=0; + int toggle = 0; + int pending = 1; + + while(*str) + { + if (pending) { + if(toggle) { + array[i++].y = atoi(str); + array[i].x = 0; + toggle = 0; + } + else + { + array[i].x = atoi(str); + array[i].y = -1; + toggle = 1; + } + pending = 0; + } + else if(*str==',') + pending = 1; + + str++; + } + + return i; +} + +/* + * ? + */ +static void Html_tag_open_area(DilloHtml *html, char *tag, gint tagsize) +{ + DwPage *page = (DwPage *) html->dw; + DwPageShape poly; + + GdkPoint point[1024]; + + char tmp[1024]; + gint type = DW_PAGE_SHAPE_RECT; + int nbpoints; + gchar *url; + + //g_print(" Html_tag_open_area: in map %d, ",page->current_map); + poly.map = page->current_map; + + if ( Html_get_attr(tag, tagsize, "shape", tmp, sizeof(tmp)) ) { + if(strcmp(tmp,"rect")==0) { + type = DW_PAGE_SHAPE_RECT; + //g_print(" rect "); + } + else if(strcmp(tmp,"circle")==0) { + type = DW_PAGE_SHAPE_CIRCLE; + //g_print(" circle "); + } + else if(strcmp(tmp,"poly")==0) { + type = DW_PAGE_SHAPE_POLY; + //g_print(" poly "); + } + else { + type = DW_PAGE_SHAPE_RECT; + //g_print(" default "); + } + } + /* todo: add support for coords in % */ + if ( Html_get_attr(tag, tagsize, "coords", tmp, sizeof(tmp)) ) { + /* Is this a valid poly ? + * rect = x0,y0,x1,y1 => 2 + * circle = x,y,r => 2 + * poly = x0,y0,x1,y1,x2,y2 minimum => 3 */ + nbpoints = Html_read_coords(tmp, point); + switch(type) { + case DW_PAGE_SHAPE_RECT: + //g_print("RECT(%d) ",nbpoints); + if(nbpoints>=2) { + poly.type = type; + poly.data.rect.left = point[0].x; + poly.data.rect.top = point[0].y; + poly.data.rect.right = point[1].x; + poly.data.rect.bottom = point[1].y; + } + else + type = DW_PAGE_SHAPE_ERROR; + break; + case DW_PAGE_SHAPE_CIRCLE: + //g_print("CIRCLE(%d) ",nbpoints); + if(nbpoints>=1) { + poly.type = type; + poly.data.circle.x = point[0].x; + poly.data.circle.y = point[0].y; + poly.data.circle.r2 = point[1].x*point[1].x; + } + else + type = DW_PAGE_SHAPE_ERROR; + break; + case DW_PAGE_SHAPE_POLY: + if(nbpoints>=3) { + poly.type = type; + //g_print("POLY(%d) ",nbpoints); + poly.data.poly = gdk_region_polygon (point, nbpoints, GDK_WINDING_RULE); + } + else + type = DW_PAGE_SHAPE_ERROR; + break; + } + } + + if (type != DW_PAGE_SHAPE_ERROR) { + if ( Html_get_attr(tag, tagsize, "nohref", tmp, sizeof(tmp)) ) { + poly.link = -1; + //g_print("nohref"); + } + if (Html_get_attr(tag, tagsize, "href", tmp, sizeof(tmp)) ) { + url = a_Url_resolve_relative(html->linkblock->base_url, tmp); + if ( !url ) + return; + if(Html_get_attr(tag, tagsize, "alt", tmp, sizeof(tmp))) + poly.link = a_Dw_page_new_link(page, url, tmp); + else + poly.link = a_Dw_page_new_link(page, url, NULL); + g_free(url); + } + a_List_add(page->shapes, page->num_shapes, + sizeof(*page->shapes), page->num_shapes_max); + page->shapes[page->num_shapes] = poly; + page->num_shapes++; + } + //g_print("\n"); } /* @@ -827,20 +1020,24 @@ static void Html_tag_open_a(DilloHtml *h char href[1024]; char name[512]; gchar *url; - guint idx; Html_push_tag(html, tag, tagsize); page = (DwPage *) html->dw; + /* todo: add support for MAP with A HREF */ + Html_tag_open_area(html, tag, tagsize); + /* can have both a "href" attribute and a "name" attribute */ if ( Html_get_attr(tag, tagsize, "href", href, sizeof(href)) ) { url = a_Url_resolve_relative(html->linkblock->base_url, href); if ( !url ) return; - idx = html->stack[html->stack_top].attr; - attr = page->attrs[idx]; - attr.link = a_Dw_page_new_link(page, url); + attr = page->attrs[html->stack[html->stack_top].attr]; + if(Html_get_attr(tag, tagsize, "alt", name, sizeof(name)) ) + attr.link = a_Dw_page_new_link(page, url, name); + else + attr.link = a_Dw_page_new_link(page, url, NULL); attr.color = a_Dw_page_find_color(page, page->link_color); html->stack[html->stack_top].attr = a_Dw_page_add_attr(page, &attr); g_free(url); @@ -1867,13 +2064,13 @@ typedef struct { TagFunct open, close; } TagInfo; -#define NTAGS 36 +#define NTAGS 38 static TagInfo Tags[NTAGS] = { {"a", Html_tag_open_a, Html_tag_close_default}, /* 0 */ /* abbr */ /* acronym */ {"address", Html_tag_open_i, Html_tag_close_par}, - /* area */ + {"area", Html_tag_open_area, Html_tag_close_nop}, /* new */ {"b", Html_tag_open_b, Html_tag_close_default}, /* base */ /* big */ @@ -1918,7 +2115,7 @@ static TagInfo Tags[NTAGS] = { /* legend */ {"li", Html_tag_open_li, Html_tag_close_default}, /* link */ - /* map */ + {"map", Html_tag_open_map, Html_tag_close_map}, /* new */ {"meta", Html_tag_open_meta, Html_tag_close_nop}, /* noframes */ /* noscript */