From 221e5aa2a3725decb62997fbf643efcecd336c9e Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Wed, 6 Sep 2006 00:15:10 +0000 Subject: Add frame target support to imagemaps. svn path=/trunk/netsurf/; revision=2920 --- desktop/browser.c | 112 +++++++++++++++++++++++------------------------ render/imagemap.c | 129 +++++++++++++++++++++++++++++++++++++++--------------- render/imagemap.h | 6 ++- 3 files changed, 154 insertions(+), 93 deletions(-) diff --git a/desktop/browser.c b/desktop/browser.c index 12bec0f68..8ab99338e 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -78,7 +78,7 @@ static void download_window_callback(fetch_msg msg, void *p, const void *data, static void browser_window_destroy_children(struct browser_window *bw); static void browser_window_destroy_internal(struct browser_window *bw); static struct browser_window *browser_window_find_target(struct browser_window *bw, const char *target); -static void browser_window_find_target_internal(struct browser_window *bw, const char *target, +static void browser_window_find_target_internal(struct browser_window *bw, const char *target, int depth, struct browser_window *page, int *rdepth, struct browser_window **bw_target); static void browser_window_mouse_action_html(struct browser_window *bw, browser_mouse_state mouse, int x, int y); @@ -145,7 +145,7 @@ struct browser_window *browser_window_create(const char *url, struct browser_win bw->scrolling = SCROLLING_YES; bw->border = true; bw->no_resize = true; - + /* gui window */ if ((bw->window = gui_create_browser_window(bw, clone)) == NULL) { browser_window_destroy(bw); @@ -168,10 +168,10 @@ struct browser_window *browser_window_owner(struct browser_window *bw) { /* an iframe's parent is just the parent window */ if (bw->browser_window_type == BROWSER_WINDOW_IFRAME) return bw->parent; - + /* the parent of a frameset is either a NORMAL window or an IFRAME */ while (bw->parent) { - switch (bw->browser_window_type) { + switch (bw->browser_window_type) { case BROWSER_WINDOW_NORMAL: case BROWSER_WINDOW_IFRAME: return bw; @@ -198,7 +198,7 @@ void browser_window_create_iframes(struct browser_window *bw, struct content_html_iframe *cur; int iframes = 0; int index; - + for (cur = iframe; cur; cur = cur->next) iframes++; bw->iframes = calloc(iframes, sizeof(*bw)); @@ -214,7 +214,7 @@ void browser_window_create_iframes(struct browser_window *bw, window->history = history_create(); window->sel = selection_create(window); window->refresh_interval = -1; - + /* window characteristics */ window->drag_type = DRAGGING_NONE; window->browser_window_type = BROWSER_WINDOW_IFRAME; @@ -226,11 +226,11 @@ void browser_window_create_iframes(struct browser_window *bw, window->margin_height = cur->margin_height; if (cur->name) window->name = strdup(cur->name); - + /* linking */ window->box = cur->box; window->parent = bw; - + /* gui window */ window->window = gui_create_browser_window(window, bw); } @@ -253,7 +253,7 @@ void browser_window_create_iframes(struct browser_window *bw, * * \param bw The browser window to reposition iframes for */ - + void browser_window_recalculate_iframes(struct browser_window *bw) { struct browser_window *window; struct rect rect; @@ -261,7 +261,7 @@ void browser_window_recalculate_iframes(struct browser_window *bw) { int index; assert(bw); - + /* update window dimensions */ gui_window_get_dimensions(bw->window, &bw_width, &bw_height); if (!bw->parent) { @@ -270,13 +270,13 @@ void browser_window_recalculate_iframes(struct browser_window *bw) { bw->x1 = bw_width; bw->y1 = bw_height; } - + for (index = 0; index < bw->iframe_count; index++) { window = &(bw->iframes[index]); box_bounds(window->box, &rect); gui_window_position_frame(window->window, rect.x0, rect.y0, - rect.x1, rect.y1); - } + rect.x1, rect.y1); + } } @@ -300,7 +300,7 @@ void browser_window_create_frameset(struct browser_window *bw, /* create children */ assert(bw->children == NULL); assert(frameset->cols + frameset->rows != 0); - + bw->children = calloc((frameset->cols * frameset->rows), sizeof(*bw)); if (!bw->children) return; @@ -311,7 +311,7 @@ void browser_window_create_frameset(struct browser_window *bw, index = (row * bw->cols) + col; frame = &frameset->children[index]; window = &bw->children[index]; - + /* content */ window->history = history_create(); window->sel = selection_create(window); @@ -336,18 +336,18 @@ void browser_window_create_frameset(struct browser_window *bw, /* linking */ window->parent = bw; - + /* gui window */ window->window = gui_create_browser_window(window, bw); if (frame->children) browser_window_create_frameset(window, frame); } } - + /* calculate dimensions */ gui_window_update_extent(bw->window); browser_window_recalculate_frameset(bw); - + /* launch content */ for (row = 0; row < bw->rows; row++) { for (col = 0; col < bw->cols; col++) { @@ -367,7 +367,7 @@ void browser_window_create_frameset(struct browser_window *bw, * * \param bw The browser window to reposition framesets for */ - + void browser_window_recalculate_frameset(struct browser_window *bw) { int widths[bw->cols][bw->rows]; int heights[bw->cols][bw->rows]; @@ -380,7 +380,7 @@ void browser_window_recalculate_frameset(struct browser_window *bw) { int x, y; assert(bw); - + /* window dimensions */ if (!bw->parent) { gui_window_get_dimensions(bw->window, &bw_width, &bw_height); @@ -423,7 +423,7 @@ void browser_window_recalculate_frameset(struct browser_window *bw) { } avail_width -= widths[col][row]; } - + /* try to distribute remainder to relative values in preference */ if ((relative > 0) && (avail_width > 0)) { for (col = 0; col < bw->cols; col++) { @@ -443,7 +443,7 @@ void browser_window_recalculate_frameset(struct browser_window *bw) { for (col = 0; col < bw->cols; col++) { index = (row * bw->cols) + col; window = &bw->children[index]; - + if (col == bw->cols - 1) { widths[col][row] = bw_width; } else { @@ -508,7 +508,7 @@ void browser_window_recalculate_frameset(struct browser_window *bw) { for (row = 0; row < bw->rows; row++) { index = (row * bw->cols) + col; window = &bw->children[index]; - + if (row == bw->rows - 1) { heights[col][row] = bw_height; } else { @@ -533,7 +533,7 @@ void browser_window_recalculate_frameset(struct browser_window *bw) { y+= heights[col][row2]; gui_window_position_frame(window->window, x, y, x + widths[col][row] - 1, - y + heights[col][row] - 1); + y + heights[col][row] - 1); x += widths[col][row]; if (window->children) browser_window_recalculate_frameset(window); @@ -547,13 +547,13 @@ void browser_window_recalculate_frameset(struct browser_window *bw) { * * \param bw The browser window to resize */ - + void browser_window_resize_frame(struct browser_window *bw, int x, int y) { struct browser_window *parent; struct browser_window *sibling; int col = -1, row = -1, i; bool change = false; - + parent = bw->parent; assert(parent); @@ -565,7 +565,7 @@ void browser_window_resize_frame(struct browser_window *bw, int x, int y) { } } assert((col >= 0) && (row >= 0)); - + sibling = NULL; if (bw->drag_resize_left) sibling = &parent->children[row * parent->cols + (col - 1)]; @@ -573,7 +573,7 @@ void browser_window_resize_frame(struct browser_window *bw, int x, int y) { sibling = &parent->children[row * parent->cols + (col + 1)]; if (sibling) change |= browser_window_resolve_frame_dimension(bw, sibling, x, y, true, false); - + sibling = NULL; if (bw->drag_resize_up) sibling = &parent->children[(row - 1) * parent->cols + col]; @@ -596,7 +596,7 @@ bool browser_window_resolve_frame_dimension(struct browser_window *bw, struct br int frame_size; assert(!(width && height)); - + /* extend/shrink the box to the pointer */ if (width) { if (bw->drag_resize_left) @@ -620,7 +620,7 @@ bool browser_window_resolve_frame_dimension(struct browser_window *bw, struct br frame_size = bw->parent->y1 - bw->parent->y0; } sibling_dimension = bw_pixels + sibling_pixels - bw_dimension; - + /* check for no change or no frame size*/ if ((bw_dimension == bw_pixels) || (frame_size == 0)) return false; @@ -678,11 +678,11 @@ bool browser_window_resolve_frame_dimension(struct browser_window *bw, struct br bw_d->value = (bw_d->value * sibling_pixels) / sibling_dimension; else bw_d->value = (bw_d->value * bw_dimension) / bw_pixels; - + /* todo: the availble resize may have changed, update the drag box */ return true; } - + /* finally we have a pixel/percentage mix. unlike relative values, percentages * can easily be backwards-calculated as they can simply be scaled like pixel * values @@ -755,7 +755,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url, LOG(("bw %p, url %s", bw, url)); assert(bw); assert(url); - + /* don't allow massively nested framesets */ for (cur = bw; cur->parent; cur = cur->parent) depth++; @@ -1137,10 +1137,10 @@ void browser_window_start_throbber(struct browser_window *bw) void browser_window_stop_throbber(struct browser_window *bw) { bw->throbbing = false; - + while (bw->parent) bw = bw->parent; - + if (!browser_window_check_throbber(bw)) gui_window_stop_throbber(bw->window); } @@ -1148,10 +1148,10 @@ void browser_window_stop_throbber(struct browser_window *bw) bool browser_window_check_throbber(struct browser_window *bw) { int children, index; - + if (bw->throbbing) return true; - + if (bw->children) { children = bw->rows * bw->cols; for (index = 0; index < children; index++) { @@ -1216,7 +1216,7 @@ void browser_window_update(struct browser_window *bw, void browser_window_stop(struct browser_window *bw) { int children, index; - + if (bw->loading_content) { content_remove_user(bw->loading_content, browser_window_callback, (intptr_t) bw, 0); @@ -1231,7 +1231,7 @@ void browser_window_stop(struct browser_window *bw) } schedule_remove(browser_window_refresh, bw); - + if (bw->children) { children = bw->rows * bw->cols; for (index = 0; index < children; index++) @@ -1400,14 +1400,14 @@ void browser_window_destroy_internal(struct browser_window *bw) * \param bw the browser_window to search all relatives of * \param target the target to locate */ - + struct browser_window *browser_window_find_target(struct browser_window *bw, const char *target) { struct browser_window *bw_target; struct browser_window *top; struct content *c; int rdepth; - + /* use the base target if we don't have one */ c = bw->current_content; if (!target && c && c->data.html.base_target) @@ -1438,13 +1438,13 @@ struct browser_window *browser_window_find_target(struct browser_window *bw, con return bw; return bw_target; } - + /* find frame according to B.8, ie using the following priorities: * * 1) current frame * 2) closest to front */ - + rdepth = -1; bw_target = bw; for (top = bw; top->parent; top = top->parent); @@ -1452,11 +1452,11 @@ struct browser_window *browser_window_find_target(struct browser_window *bw, con return bw_target; } -void browser_window_find_target_internal(struct browser_window *bw, const char *target, +void browser_window_find_target_internal(struct browser_window *bw, const char *target, int depth, struct browser_window *page, int *rdepth, struct browser_window **bw_target) { int i; - + if ((bw->name) && (!strcasecmp(bw->name, target))) { if ((bw == page) || (depth > *rdepth)) { *rdepth = depth; @@ -1466,7 +1466,7 @@ void browser_window_find_target_internal(struct browser_window *bw, const char * if ((!bw->children) && (!bw->iframes)) return; - + depth++; for (i = 0; i < (bw->cols * bw->rows); i++) { if ((bw->children[i].name) && (!strcasecmp(bw->children[i].name, target))) { @@ -1591,7 +1591,7 @@ void browser_window_mouse_action_html(struct browser_window *bw, { char *base_url = 0; char *title = 0; - char *url = 0; + const char *url = 0; const char *target = 0; char status_buffer[200]; const char *status = 0; @@ -1643,7 +1643,7 @@ void browser_window_mouse_action_html(struct browser_window *bw, if (box->usemap) url = imagemap_get(content, box->usemap, - box_x, box_y, x, y); + box_x, box_y, x, y, &target); if (box->gadget) { gadget_content = content; @@ -1864,14 +1864,14 @@ void browser_window_mouse_action_html(struct browser_window *bw, } else { bool done = false; - + /* frame resizing */ if (bw->parent) { struct browser_window *parent; for (parent = bw->parent; parent->parent; parent = parent->parent); browser_window_resize_frames(parent, mouse, x + bw->x0, y + bw->y0, &pointer, &status, &done); - } + } /* if clicking in the main page, remove the selection from any text areas */ if (!done) { @@ -1906,7 +1906,7 @@ void browser_window_mouse_action_html(struct browser_window *bw, } } } - + if (!done) { if (title) status = title; @@ -1948,10 +1948,10 @@ bool browser_window_resize_frames(struct browser_window *bw, browser_mouse_state gui_pointer_shape *pointer, const char **status, bool *action) { bool left, right, up, down; int i, resize_margin; - + if ((x < bw->x0) || (x > bw->x1) || (y < bw->y0) || (y > bw->y1)) return false; - + if ((!bw->no_resize) && (bw->parent)) { resize_margin = FRAME_RESIZE; if (resize_margin * 2 > (bw->x1 - bw->x0)) @@ -1963,7 +1963,7 @@ bool browser_window_resize_frames(struct browser_window *bw, browser_mouse_state resize_margin = (bw->y1 - bw->y0) / 2; up = (y < bw->y0 + resize_margin); down = (y > bw->y1 - resize_margin); - + /* check if the edges can actually be moved */ if (left || right || up || down) { int row = -1, col = -1; @@ -1984,7 +1984,7 @@ bool browser_window_resize_frames(struct browser_window *bw, browser_mouse_state } } assert((row >= 0) && (col >= 0)); - + left &= (col > 0); right &= (col < bw->parent->cols - 1) & (!left); up &= (row > 0); @@ -2042,7 +2042,7 @@ bool browser_window_resize_frames(struct browser_window *bw, browser_mouse_state } return false; } - + diff --git a/render/imagemap.c b/render/imagemap.c index 03047179d..c8fbb47c4 100644 --- a/render/imagemap.c +++ b/render/imagemap.c @@ -28,6 +28,7 @@ typedef enum { struct mapentry { imagemap_entry_type type; /**< type of shape */ char *url; /**< absolute url to go to */ + char *target; /**< target frame (if any) */ union { struct { int x; /**< x coordinate of centre */ @@ -71,9 +72,9 @@ static int imagemap_point_in_poly(int num, float *xpt, float *ypt, /** * Add an imagemap to the hashtable, creating it if it doesn't exist * - * @param c The containing content - * @param key The name of the imagemap - * @param list List of map regions + * \param c The containing content + * \param key The name of the imagemap + * \param list List of map regions * \return true on succes, false otherwise */ bool imagemap_add(struct content *c, const char *key, struct mapentry *list) @@ -108,7 +109,7 @@ bool imagemap_add(struct content *c, const char *key, struct mapentry *list) /** * Create hashtable of imagemaps * - * @param c The containing content + * \param c The containing content * \return true on success, false otherwise */ bool imagemap_create(struct content *c) @@ -130,7 +131,7 @@ bool imagemap_create(struct content *c) /** * Destroy hashtable of imagemaps * - * @param c The containing content + * \param c The containing content */ void imagemap_destroy(struct content *c) { @@ -160,7 +161,7 @@ void imagemap_destroy(struct content *c) /** * Dump imagemap data to the log * - * @param c The containing content + * \param c The containing content */ void imagemap_dump(struct content *c) { @@ -219,8 +220,8 @@ void imagemap_dump(struct content *c) /** * Extract all imagemaps from a document tree * - * @param node Root node of tree - * @param c The containing content + * \param node Root node of tree + * \param c The containing content * \return false on memory exhaustion, true otherwise */ bool imagemap_extract(xmlNode *node, struct content *c) @@ -314,7 +315,7 @@ bool imagemap_extract_map(xmlNode *node, struct content *c, */ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) { - char *shape, *coords = 0, *href, *val; + char *shape, *coords = 0, *href, *val, *target = 0; int num; struct mapentry *new_map, *temp; @@ -332,6 +333,9 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) if ((href = (char*)xmlGetProp(n, (const xmlChar*)"href")) == NULL) { return true; } + + target = (char *)xmlGetProp(n, (const xmlChar *)"target"); + /* no shape -> shape is a rectangle */ if ((shape = (char*)xmlGetProp(n, (const xmlChar*)"shape")) == NULL) { shape = (char*)xmlMemStrdup("rect"); @@ -339,6 +343,8 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) if (strcasecmp(shape, "default") != 0) { /* no coords -> ignore */ if ((coords = (char*)xmlGetProp(n, (const xmlChar*)"coords")) == NULL) { + if (target) + xmlFree(target); xmlFree(href); xmlFree(shape); return true; @@ -347,6 +353,12 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) new_map = calloc(1, sizeof(*new_map)); if (!new_map) { + if (target) + xmlFree(target); + xmlFree(href); + xmlFree(shape); + if (coords) + xmlFree(coords); return false; } @@ -367,29 +379,55 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) } else { /* unknown shape -> bail */ free(new_map); + if (target) + xmlFree(target); xmlFree(href); xmlFree(shape); - xmlFree(coords); + if (coords) + xmlFree(coords); return true; } if (!box_extract_link(href, base_url, &new_map->url)) { free(new_map); + if (target) + xmlFree(target); xmlFree(href); xmlFree(shape); - xmlFree(coords); + if (coords) + xmlFree(coords); return false; } if (!new_map->url) { /* non-fatal error -> ignore this entry */ free(new_map); + if (target) + xmlFree(target); xmlFree(href); xmlFree(shape); - xmlFree(coords); + if (coords) + xmlFree(coords); return true; } + if (target) { + new_map->target = strdup(target); + if (!new_map->target) { + free(new_map->url); + free(new_map); + xmlFree(target); + xmlFree(href); + xmlFree(shape); + if (coords) + xmlFree(coords); + return false; + } + + /* no longer needed */ + xmlFree(target); + } + if (new_map->type != IMAGEMAP_DEFAULT) { /* coordinates are a comma-separated list of values */ val = strtok(coords, ","); @@ -439,17 +477,20 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) new_map->bounds.poly.xcoords = calloc(0, sizeof(*new_map->bounds.poly.xcoords)); if (!new_map->bounds.poly.xcoords) { + free(new_map->target); free(new_map->url); free(new_map); xmlFree(href); xmlFree(shape); - xmlFree(coords); + if (coords) + xmlFree(coords); return false; } new_map->bounds.poly.ycoords = calloc(0, sizeof(*new_map->bounds.poly.ycoords)); if (!new_map->bounds.poly.ycoords) { free(new_map->bounds.poly.xcoords); + free(new_map->target); free(new_map->url); free(new_map); xmlFree(href); @@ -471,6 +512,7 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) if (!xcoords) { free(new_map->bounds.poly.ycoords); free(new_map->bounds.poly.xcoords); + free(new_map->target); free(new_map->url); free(new_map); xmlFree(href); @@ -483,6 +525,7 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) if (!ycoords) { free(new_map->bounds.poly.ycoords); free(new_map->bounds.poly.xcoords); + free(new_map->target); free(new_map->url); free(new_map); xmlFree(href); @@ -522,7 +565,8 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) xmlFree(href); xmlFree(shape); - xmlFree(coords); + if (coords) + xmlFree(coords); return true; } @@ -530,7 +574,7 @@ bool imagemap_addtolist(xmlNode *n, char *base_url, struct mapentry **entry) /** * Free list of imagemap entries * - * @param list Pointer to head of list + * \param list Pointer to head of list */ void imagemap_freelist(struct mapentry *list) { @@ -543,6 +587,8 @@ void imagemap_freelist(struct mapentry *list) while (entry != 0) { prev = entry; free(entry->url); + if (entry->target) + free(entry->target); if (entry->type == IMAGEMAP_POLY) { free(entry->bounds.poly.xcoords); free(entry->bounds.poly.ycoords); @@ -555,17 +601,19 @@ void imagemap_freelist(struct mapentry *list) /** * Retrieve url associated with imagemap entry * - * @param c The containing content - * @param key The map name to search for - * @param x The left edge of the containing box - * @param y The top edge of the containing box - * @param click_x The horizontal location of the click - * @param click_y The vertical location of the click - * @return The url associated with this area, or NULL if not found + * \param c The containing content + * \param key The map name to search for + * \param x The left edge of the containing box + * \param y The top edge of the containing box + * \param click_x The horizontal location of the click + * \param click_y The vertical location of the click + * \param target Pointer to location to receive target pointer (if any) + * \return The url associated with this area, or NULL if not found */ -char *imagemap_get(struct content *c, const char *key, unsigned long x, - unsigned long y, unsigned long click_x, - unsigned long click_y) +const char *imagemap_get(struct content *c, const char *key, + unsigned long x, unsigned long y, + unsigned long click_x, unsigned long click_y, + const char **target) { unsigned int slot = 0; struct imagemap *map; @@ -590,6 +638,8 @@ char *imagemap_get(struct content *c, const char *key, unsigned long x, switch (entry->type) { case IMAGEMAP_DEFAULT: /* just return the URL. no checks required */ + if (target) + *target = entry->target; return entry->url; break; case IMAGEMAP_RECT: @@ -597,6 +647,8 @@ char *imagemap_get(struct content *c, const char *key, unsigned long x, click_x <= x + entry->bounds.rect.x1 && click_y >= y + entry->bounds.rect.y0 && click_y <= y + entry->bounds.rect.y1) { + if (target) + *target = entry->target; return entry->url; } break; @@ -606,6 +658,8 @@ char *imagemap_get(struct content *c, const char *key, unsigned long x, if ((cx * cx + cy * cy) <= (unsigned long)(entry->bounds.circle.r * entry->bounds.circle.r)) { + if (target) + *target = entry->target; return entry->url; } break; @@ -614,20 +668,25 @@ char *imagemap_get(struct content *c, const char *key, unsigned long x, entry->bounds.poly.xcoords, entry->bounds.poly.ycoords, x, y, click_x, click_y)) { + if (target) + *target = entry->target; return entry->url; } break; } } + if (target) + *target = NULL; + return NULL; } /** * Hash function * - * @param key The key to hash - * @return The hashed value + * \param key The key to hash + * \return The hashed value */ unsigned int imagemap_hash(const char *key) { @@ -646,14 +705,14 @@ unsigned int imagemap_hash(const char *key) * Test if a point lies within an arbitrary polygon * Modified from comp.graphics.algorithms FAQ 2.03 * - * @param num Number of vertices - * @param xpt Array of x coordinates - * @param ypt Array of y coordinates - * @param x Left hand edge of containing box - * @param y Top edge of containing box - * @param click_x X coordinate of click - * @param click_y Y coordinate of click - * @return 1 if point is in polygon, 0 if outside. 0 or 1 if on boundary + * \param num Number of vertices + * \param xpt Array of x coordinates + * \param ypt Array of y coordinates + * \param x Left hand edge of containing box + * \param y Top edge of containing box + * \param click_x X coordinate of click + * \param click_y Y coordinate of click + * \return 1 if point is in polygon, 0 if outside. 0 or 1 if on boundary */ int imagemap_point_in_poly(int num, float *xpt, float *ypt, unsigned long x, unsigned long y, unsigned long click_x, diff --git a/render/imagemap.h b/render/imagemap.h index 35523c9a5..8af50e79d 100644 --- a/render/imagemap.h +++ b/render/imagemap.h @@ -15,7 +15,9 @@ struct content; void imagemap_destroy(struct content *c); void imagemap_dump(struct content *c); bool imagemap_extract(xmlNode *node, struct content *c); -char *imagemap_get(struct content *c, const char *key, unsigned long x, - unsigned long y, unsigned long click_x, unsigned long click_y); +const char *imagemap_get(struct content *c, const char *key, + unsigned long x, unsigned long y, + unsigned long click_x, unsigned long click_y, + const char **target); #endif -- cgit v1.2.3