listview *listview_create ( const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse ) { listview *lv = g_malloc0 ( sizeof ( listview ) ); gchar *box = g_strjoin ( ".", name, "box", NULL ); widget_init ( WIDGET ( lv ), box ); g_free ( box ); lv->listview_name = g_strdup ( name ); lv->widget.free = listview_free; lv->widget.resize = listview_resize; lv->widget.draw = listview_draw; lv->widget.clicked = listview_clicked; lv->widget.motion_notify = listview_motion_notify; lv->widget.get_desired_height = listview_get_desired_height; lv->widget.enabled = TRUE; lv->eh = eh; char *n = g_strjoin ( ".", lv->listview_name, "scrollbar", NULL ); lv->scrollbar = scrollbar_create ( n ); // Default position on right. lv->scrollbar->widget.index = rofi_theme_get_integer_exact ( WIDGET ( lv->scrollbar ), "index", 1 ); g_free ( n ); widget_set_clicked_handler ( WIDGET ( lv->scrollbar ), listview_scrollbar_clicked, lv ); lv->scrollbar->widget.parent = WIDGET ( lv ); // Calculate height of an element. // char *tb_name = g_strjoin ( ".", lv->listview_name, "element", NULL ); textbox *tb = textbox_create ( tb_name, 0, NORMAL, "" ); lv->element_height = textbox_get_estimated_height ( tb, lv->eh ); g_free ( tb_name ); widget_free ( WIDGET ( tb ) ); lv->callback = cb; lv->udata = udata; // Some settings. lv->spacing = rofi_theme_get_distance ( WIDGET ( lv ), "spacing", DEFAULT_SPACING ); lv->menu_columns = rofi_theme_get_integer ( WIDGET ( lv ), "columns", config.menu_columns ); lv->fixed_num_lines = rofi_theme_get_boolean ( WIDGET ( lv ), "fixed-height", config.fixed_num_lines ); lv->dynamic = rofi_theme_get_boolean ( WIDGET ( lv ), "dynamic", TRUE ); lv->reverse = rofi_theme_get_boolean ( WIDGET ( lv ), "reverse", reverse ); listview_set_show_scrollbar ( lv, rofi_theme_get_boolean ( WIDGET ( lv ), "scrollbar", !config.hide_scrollbar ) ); lv->cycle = rofi_theme_get_boolean ( WIDGET ( lv ), "cycle", config.cycle ); return lv; }
int main ( G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv ) { scrollbar * sb = scrollbar_create ( NULL, "scrollbar" ); widget_resize ( WIDGET (sb), 10, 100); scrollbar_set_handle ( NULL, 10213); scrollbar_set_max_value ( NULL, 10 ); scrollbar_set_handle_length ( NULL , 1000); scrollbar_set_max_value ( sb, 10000); TASSERTE ( sb->length, 10000 ); scrollbar_set_handle_length ( sb, 10); TASSERTE ( sb->pos_length, 10 ); scrollbar_set_handle ( sb , 5000 ); TASSERTE ( sb->pos, 5000 ); scrollbar_set_handle ( sb , 15000 ); TASSERTE ( sb->pos, 10000 ); scrollbar_set_handle ( sb , UINT32_MAX ); TASSERTE ( sb->pos, 10000 ); scrollbar_set_handle_length ( sb, 15000); TASSERTE ( sb->pos_length, 10000 ); scrollbar_set_handle_length ( sb, 0); TASSERTE ( sb->pos_length, 1 ); guint cl = scrollbar_scroll_get_line ( sb, 10 ); TASSERTE ( cl, 1010); cl = scrollbar_scroll_get_line ( sb, 20 ); TASSERTE ( cl, 2020); cl = scrollbar_scroll_get_line ( sb, 0 ); TASSERTE ( cl, 0); cl = scrollbar_scroll_get_line ( sb, 99 ); TASSERTE ( cl, 9999); scrollbar_set_handle_length ( sb, 1000); cl = scrollbar_scroll_get_line ( sb, 10 ); TASSERTE ( cl, 555); cl = scrollbar_scroll_get_line ( sb, 20 ); TASSERTE ( cl, 1666); cl = scrollbar_scroll_get_line ( sb, 0 ); TASSERTE ( cl, 0); cl = scrollbar_scroll_get_line ( sb, 99 ); TASSERTE ( cl, 9999); widget_free( WIDGET (sb ) ); }
void list_create(list_t *m,int x,int y,int w,int h,char *(*refresh)(list_t*,int)) { memset(m,0,sizeof(list_t)); m->info.type = G_LIST; m->info.x = x; m->info.y = y; m->info.w = w; m->info.h = h; m->info.draw = (drawfunc_t)list_draw; m->info.event = (eventfunc_t)list_event; m->refresh = refresh; m->selected = -1; strcpy(m->path,config.path_rom); scrollbar_create(&m->scrollbar,x + w - 8,y,h,0,click_scrollbar); m->scrollbar.user = m; }
/** * Callback for (i)frame scrollbars. */ void browser_window_scroll_callback(void *client_data, struct scrollbar_msg_data *scrollbar_data) { struct browser_window *bw = client_data; switch(scrollbar_data->msg) { case SCROLLBAR_MSG_MOVED: if (bw->browser_window_type == BROWSER_WINDOW_IFRAME) { html_redraw_a_box(bw->parent->current_content, bw->box); } else { struct rect rect; rect.x0 = scrollbar_get_offset(bw->scroll_x); rect.y0 = scrollbar_get_offset(bw->scroll_y); rect.x1 = rect.x0 + bw->width; rect.y1 = rect.y0 + bw->height; browser_window_update_box(bw, &rect); } break; case SCROLLBAR_MSG_SCROLL_START: { struct rect rect = { .x0 = scrollbar_data->x0, .y0 = scrollbar_data->y0, .x1 = scrollbar_data->x1, .y1 = scrollbar_data->y1 }; if (scrollbar_is_horizontal(scrollbar_data->scrollbar)) browser_window_set_drag_type(bw, DRAGGING_SCR_X, &rect); else browser_window_set_drag_type(bw, DRAGGING_SCR_Y, &rect); } break; case SCROLLBAR_MSG_SCROLL_FINISHED: browser_window_set_drag_type(bw, DRAGGING_NONE, NULL); browser_window_set_pointer(bw, BROWSER_POINTER_DEFAULT); break; } } /* exported interface, documented in browser.h */ void browser_window_handle_scrollbars(struct browser_window *bw) { hlcache_handle *h = bw->current_content; bool scroll_x; bool scroll_y; int c_width = 0; int c_height = 0; assert(!bw->window); /* Core-handled windows only */ if (h != NULL) { c_width = content_get_width(h); c_height = content_get_height(h); } if (bw->scrolling == SCROLLING_YES) { scroll_x = true; scroll_y = true; } else if (bw->scrolling == SCROLLING_AUTO && bw->current_content) { int bw_width = bw->width; int bw_height = bw->height; /* subtract existing scrollbar width */ bw_width -= bw->scroll_y ? SCROLLBAR_WIDTH : 0; bw_height -= bw->scroll_x ? SCROLLBAR_WIDTH : 0; scroll_y = (c_height > bw_height) ? true : false; scroll_x = (c_width > bw_width) ? true : false; } else { /* No scrollbars */ scroll_x = false; scroll_y = false; } if (!scroll_x && bw->scroll_x != NULL) { scrollbar_destroy(bw->scroll_x); bw->scroll_x = NULL; } if (!scroll_y && bw->scroll_y != NULL) { scrollbar_destroy(bw->scroll_y); bw->scroll_y = NULL; } if (scroll_y) { int length = bw->height; int visible = bw->height - (scroll_x ? SCROLLBAR_WIDTH : 0); if (bw->scroll_y == NULL) { /* create vertical scrollbar */ if (!scrollbar_create(false, length, c_height, visible, bw, browser_window_scroll_callback, &(bw->scroll_y))) return; } else { /* update vertical scrollbar */ scrollbar_set_extents(bw->scroll_y, length, visible, c_height); } } if (scroll_x) { int length = bw->width - (scroll_y ? SCROLLBAR_WIDTH : 0); int visible = length; if (bw->scroll_x == NULL) { /* create horizontal scrollbar */ if (!scrollbar_create(true, length, c_width, visible, bw, browser_window_scroll_callback, &(bw->scroll_x))) return; } else { /* update horizontal scrollbar */ scrollbar_set_extents(bw->scroll_x, length, visible, c_width); } } if (scroll_x && scroll_y) scrollbar_make_pair(bw->scroll_x, bw->scroll_y); }
/** * Enable scrollbar. * @param list * List to enable scrollbar on. */ void list_scrollbar_enable(list_struct *list) { list->scrollbar_enabled = 1; scrollbar_create(&list->scrollbar, 9, LIST_ROWS_HEIGHT(list) + 1, &list->row_offset, &list->rows, list->max_rows); }
/** @copydoc widgetdata::draw_func */ static void widget_draw(widgetdata *widget) { SDL_Rect box; char buf[HUGE_BUF]; size_t i; /* The list doesn't exist yet, create it. */ if (!list_mplayer) { char version[MAX_BUF]; /* Create the list and set up settings. */ list_mplayer = list_create(12, 1, 8); list_mplayer->handle_enter_func = list_handle_enter; list_mplayer->text_color_hook = list_text_color_hook; list_mplayer->surface = widget->surface; list_scrollbar_enable(list_mplayer); list_set_column(list_mplayer, 0, 130, 7, NULL, -1); list_set_font(list_mplayer, FONT_ARIAL10); /* Add default media directory songs. */ get_data_dir_file(buf, sizeof(buf), DIRECTORY_MEDIA); mplayer_list_init(list_mplayer, buf, 0); /* Now add custom ones, but ignore duplicates. */ snprintf(buf, sizeof(buf), "%s/.atrinik/%s/"DIRECTORY_MEDIA, get_config_dir(), package_get_version_partial(version, sizeof(version))); mplayer_list_init(list_mplayer, buf, 1); /* If we added any, sort the list alphabetically and add an entry * to disable background music. */ if (list_mplayer->rows) { FILE *fp; /* Allocate the blacklist. + 1 is for the last entry added * further down. It is not actually used by the blacklist as * it's not possible to toggle it on/off using the button, but * it simplifies other logic checks. */ shuffle_blacklist = ecalloc(1, sizeof(*shuffle_blacklist) * (list_mplayer->rows + 1)); /* Sort the list. */ list_sort(list_mplayer, LIST_SORT_ALPHA); /* Read the blacklist file contents. */ fp = path_fopen(FILE_MPLAYER_BLACKLIST, "r"); if (fp) { size_t row; while (fgets(buf, sizeof(buf) - 1, fp)) { for (row = 0; row < list_mplayer->rows; row++) { if (!strncmp(buf, list_mplayer->text[row][0], strlen(buf) - 1)) { shuffle_blacklist[row] = 1; break; } } } fclose(fp); } list_add(list_mplayer, list_mplayer->rows, 0, "Disable music"); } scrollbar_create(&scrollbar_progress, 130, 11, &scrollbar_progress_info.scroll_offset, &scrollbar_progress_info.num_lines, 1); scrollbar_progress.redraw = &scrollbar_progress_info.redraw; } if (widget->redraw) { const char *bg_music; box.h = 0; box.w = widget->w; text_show(widget->surface, FONT_SERIF12, "Music Player", 0, 3, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); list_set_parent(list_mplayer, widget->x, widget->y); list_show(list_mplayer, 10, 2); box.w /= 2; text_show(widget->surface, FONT_SANS10, "Currently playing:", widget->w / 2, 22, COLOR_WHITE, TEXT_ALIGN_CENTER, &box); bg_music = sound_get_bg_music_basename(); box.h = 0; box.w = widget->w / 2; /* Store the background music file name in temporary buffer and * make sure it won't overflow by truncating it if necessary. */ if (bg_music) { strncpy(buf, bg_music, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; text_truncate_overflow(FONT_SANS11, buf, 150); } /* Show the music that is being played. */ text_show(widget->surface, FONT_SANS11, bg_music ? buf : "No music", widget->w / 2 - 5, 34, COLOR_HGOLD, TEXT_ALIGN_CENTER, &box); scrollbar_progress.px = widget->x; scrollbar_progress.py = widget->y; scrollbar_show(&scrollbar_progress, widget->surface, 170, 50); box.h = 120; box.w -= 6 * 2; text_show(widget->surface, FONT_ARIAL10, "You can use the music player to play your favorite tunes from the game, or play them all one-by-one in random order (shuffle).\n\nNote that if you use the music player, in-game areas won't change your music until you click [b]Stop[/b].", widget->w / 2 + 6, 62, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP, &box); for (i = 0; i < BUTTON_NUM; i++) { buttons[i].surface = widget->surface; button_set_parent(&buttons[i], widget->x, widget->y); } buttons[BUTTON_PLAY].x = 10; buttons[BUTTON_PLAY].y = widget->h - TEXTURE_CLIENT("button")->h - 4; button_show(&buttons[BUTTON_PLAY], sound_map_background(-1) ? "Stop" : "Play"); buttons[BUTTON_SHUFFLE].x = 10 + TEXTURE_CLIENT("button")->w + 5; buttons[BUTTON_SHUFFLE].y = widget->h - TEXTURE_CLIENT("button")->h - 4; buttons[BUTTON_SHUFFLE].pressed_forced = shuffle; button_show(&buttons[BUTTON_SHUFFLE], "Shuffle"); buttons[BUTTON_BLACKLIST].x = 10 + TEXTURE_CLIENT("button")->w * 2 + 5 * 2; buttons[BUTTON_BLACKLIST].y = widget->h - TEXTURE_CLIENT("button_round")->h - 5; buttons[BUTTON_BLACKLIST].disabled = list_mplayer->row_selected == list_mplayer->rows; button_show(&buttons[BUTTON_BLACKLIST], mplayer_blacklisted(list_mplayer) ? "+" : "-"); /* Show close button. */ buttons[BUTTON_CLOSE].x = widget->w - TEXTURE_CLIENT("button_round")->w - 4; buttons[BUTTON_CLOSE].y = 4; button_show(&buttons[BUTTON_CLOSE], "X"); /* Show help button. */ buttons[BUTTON_HELP].x = widget->w - TEXTURE_CLIENT("button_round")->w * 2 - 4; buttons[BUTTON_HELP].y = 4; button_show(&buttons[BUTTON_HELP], "?"); } }
/** * Load the book interface. * @param data * Book's content. * @param len * Length of 'data'. */ void book_load(const char *data, int len) { SDL_Rect box; int pos; /* Nothing to do. */ if (!data || !len) { return; } /* Free old book data and reset the values. */ if (book_content != NULL) { efree(book_content); } book_lines = 0; book_scroll_lines = 0; book_scroll = 0; /* Store the data. */ book_content = estrdup(data); book_name_change("Book", 4); /* Strip trailing newlines. */ for (pos = len - 1; pos >= 0; pos--) { if (book_content[pos] != '\n') { break; } book_content[pos] = '\0'; } /* No data... */ if (book_content[0] == '\0') { return; } /* Calculate the line numbers. */ box.w = BOOK_TEXT_WIDTH; box.h = BOOK_TEXT_HEIGHT; text_show(NULL, FONT_ARIAL11, book_content, BOOK_TEXT_STARTX, BOOK_TEXT_STARTY, COLOR_WHITE, TEXT_WORD_WRAP | TEXT_MARKUP | TEXT_LINES_CALC, &box); book_lines = box.h; book_scroll_lines = box.y; /* Create the book popup if it doesn't exist yet. */ if (!popup_get_head() || popup_get_head()->texture != texture_get(TEXTURE_TYPE_CLIENT, "book")) { popup_struct *popup; popup = popup_create(texture_get(TEXTURE_TYPE_CLIENT, "book")); popup->draw_func = popup_draw_func; popup->draw_post_func = popup_draw_post_func; popup->event_func = popup_event_func; popup->destroy_callback_func = popup_destroy_callback; popup->clipboard_copy_func = popup_clipboard_copy_func; popup->disable_texture_drawing = 1; popup->button_left.x = 25; popup->button_left.y = 25; if (book_help_history_enabled) { popup->button_left.event_func = popup_button_event_func; popup_button_set_text(&popup->button_left, "<"); } popup->button_right.x = 649; popup->button_right.y = 25; } scrollbar_create(&scrollbar, BOOK_SCROLLBAR_WIDTH, BOOK_SCROLLBAR_HEIGHT, &book_scroll, &book_lines, book_scroll_lines); scrollbar.redraw = &popup_get_head()->redraw; popup_get_head()->redraw = 1; }
/** * Callback for (i)frame scrollbars. */ void browser_window_scroll_callback(void *client_data, struct scrollbar_msg_data *scrollbar_data) { struct browser_window *bw = client_data; switch(scrollbar_data->msg) { case SCROLLBAR_MSG_MOVED: if (bw->browser_window_type == BROWSER_WINDOW_IFRAME) { html_redraw_a_box(bw->parent->current_content, bw->box); } else { struct rect rect; rect.x0 = scrollbar_get_offset(bw->scroll_x); rect.y0 = scrollbar_get_offset(bw->scroll_y); rect.x1 = rect.x0 + bw->width; rect.y1 = rect.y0 + bw->height; browser_window_update_box(bw, &rect); } break; case SCROLLBAR_MSG_SCROLL_START: { struct rect rect = { .x0 = scrollbar_data->x0, .y0 = scrollbar_data->y0, .x1 = scrollbar_data->x1, .y1 = scrollbar_data->y1 }; if (scrollbar_is_horizontal(scrollbar_data->scrollbar)) browser_window_set_drag_type(bw, DRAGGING_SCR_X, &rect); else browser_window_set_drag_type(bw, DRAGGING_SCR_Y, &rect); } break; case SCROLLBAR_MSG_SCROLL_FINISHED: browser_window_set_drag_type(bw, DRAGGING_NONE, NULL); browser_window_set_pointer(bw, BROWSER_POINTER_DEFAULT); break; } } /* exported interface, documented in browser.h */ void browser_window_handle_scrollbars(struct browser_window *bw) { struct hlcache_handle *h = bw->current_content; bool scroll_x; bool scroll_y; int c_width = 0; int c_height = 0; assert(!bw->window); /* Core-handled windows only */ if (h != NULL) { c_width = content_get_width(h); c_height = content_get_height(h); } if (bw->scrolling == BW_SCROLLING_YES) { scroll_x = true; scroll_y = true; } else if (bw->scrolling == BW_SCROLLING_AUTO && bw->current_content) { int bw_width = bw->width; int bw_height = bw->height; /* subtract existing scrollbar width */ bw_width -= bw->scroll_y ? SCROLLBAR_WIDTH : 0; bw_height -= bw->scroll_x ? SCROLLBAR_WIDTH : 0; scroll_y = (c_height > bw_height) ? true : false; scroll_x = (c_width > bw_width) ? true : false; } else { /* No scrollbars */ scroll_x = false; scroll_y = false; } if (!scroll_x && bw->scroll_x != NULL) { scrollbar_destroy(bw->scroll_x); bw->scroll_x = NULL; } if (!scroll_y && bw->scroll_y != NULL) { scrollbar_destroy(bw->scroll_y); bw->scroll_y = NULL; } if (scroll_y) { int length = bw->height; int visible = bw->height - (scroll_x ? SCROLLBAR_WIDTH : 0); if (bw->scroll_y == NULL) { /* create vertical scrollbar */ if (scrollbar_create(false, length, c_height, visible, bw, browser_window_scroll_callback, &(bw->scroll_y)) != NSERROR_OK) { return; } } else { /* update vertical scrollbar */ scrollbar_set_extents(bw->scroll_y, length, visible, c_height); } } if (scroll_x) { int length = bw->width - (scroll_y ? SCROLLBAR_WIDTH : 0); int visible = length; if (bw->scroll_x == NULL) { /* create horizontal scrollbar */ if (scrollbar_create(true, length, c_width, visible, bw, browser_window_scroll_callback, &(bw->scroll_x)) != NSERROR_OK) { return; } } else { /* update horizontal scrollbar */ scrollbar_set_extents(bw->scroll_x, length, visible, c_width); } } if (scroll_x && scroll_y) scrollbar_make_pair(bw->scroll_x, bw->scroll_y); } /* exported function documented in desktop/frames.h */ nserror browser_window_create_iframes(struct browser_window *bw, struct content_html_iframe *iframe) { struct browser_window *window; struct content_html_iframe *cur; struct rect rect; int iframes = 0; int index; nserror ret = NSERROR_OK; if (iframe == NULL) { return NSERROR_BAD_PARAMETER; } /* Count iframe list and allocate enough space within the * browser window. */ for (cur = iframe; cur; cur = cur->next) { iframes++; } bw->iframes = calloc(iframes, sizeof(*bw)); if (!bw->iframes) { return NSERROR_NOMEM; } bw->iframe_count = iframes; index = 0; for (cur = iframe; cur; cur = cur->next) { window = &(bw->iframes[index++]); /* Initialise common parts */ browser_window_initialise_common(BW_CREATE_NONE, window, NULL); /* window characteristics */ window->browser_window_type = BROWSER_WINDOW_IFRAME; window->scrolling = cur->scrolling; window->border = cur->border; window->border_colour = cur->border_colour; window->no_resize = true; window->margin_width = cur->margin_width; window->margin_height = cur->margin_height; window->scale = bw->scale; if (cur->name != NULL) { window->name = strdup(cur->name); if (window->name == NULL) { free(bw->iframes) ; bw->iframes = 0; bw->iframe_count = 0; return NSERROR_NOMEM; } } /* linking */ window->box = cur->box; window->parent = bw; window->box->iframe = window; /* iframe dimensions */ box_bounds(window->box, &rect); browser_window_set_position(window, rect.x0, rect.y0); browser_window_set_dimensions(window, rect.x1 - rect.x0, rect.y1 - rect.y0); } /* calculate dimensions */ browser_window_update_extent(bw); browser_window_recalculate_iframes(bw); index = 0; for (cur = iframe; cur; cur = cur->next) { window = &(bw->iframes[index++]); if (cur->url) { /* fetch iframe's content */ ret = browser_window_navigate(window, cur->url, hlcache_handle_get_url(bw->current_content), BW_NAVIGATE_UNVERIFIABLE, NULL, NULL, bw->current_content); } } return ret; } /** * Recalculate iframe positions following a resize. * * \param bw The browser window to reposition iframes for */ void browser_window_recalculate_iframes(struct browser_window *bw) { struct browser_window *window; int index; for (index = 0; index < bw->iframe_count; index++) { window = &(bw->iframes[index]); if (window != NULL) { browser_window_handle_scrollbars(window); } } } /* exported interface documented in desktop/frames.h */ nserror browser_window_create_frameset(struct browser_window *bw, struct content_html_frames *frameset) { int row, col, index; struct content_html_frames *frame; struct browser_window *window; hlcache_handle *parent; assert(bw && frameset); /* 1. 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 NSERROR_NOMEM; } bw->cols = frameset->cols; bw->rows = frameset->rows; for (row = 0; row < bw->rows; row++) { for (col = 0; col < bw->cols; col++) { index = (row * bw->cols) + col; frame = &frameset->children[index]; window = &bw->children[index]; /* Initialise common parts */ browser_window_initialise_common(BW_CREATE_NONE, window, NULL); /* window characteristics */ if (frame->children) window->browser_window_type = BROWSER_WINDOW_FRAMESET; else window->browser_window_type = BROWSER_WINDOW_FRAME; window->scrolling = frame->scrolling; window->border = frame->border; window->border_colour = frame->border_colour; window->no_resize = frame->no_resize; window->frame_width = frame->width; window->frame_height = frame->height; window->margin_width = frame->margin_width; window->margin_height = frame->margin_height; if (frame->name) { window->name = strdup(frame->name); if (!window->name) { free(bw->children); bw->children = NULL; return NSERROR_NOMEM; } } window->scale = bw->scale; /* linking */ window->parent = bw; if (window->name) LOG("Created frame '%s'", window->name); else LOG("Created frame (unnamed)"); } } /* 2. Calculate dimensions */ browser_window_update_extent(bw); browser_window_recalculate_frameset(bw); /* 3. Recurse for grandchildren */ for (row = 0; row < bw->rows; row++) { for (col = 0; col < bw->cols; col++) { index = (row * bw->cols) + col; frame = &frameset->children[index]; window = &bw->children[index]; if (frame->children) browser_window_create_frameset(window, frame); } } /* Use the URL of the first ancestor window containing html content * as the referer */ for (window = bw; window->parent; window = window->parent) { if (window->current_content && content_get_type(window->current_content) == CONTENT_HTML) break; } parent = window->current_content; /* 4. Launch content */ for (row = 0; row < bw->rows; row++) { for (col = 0; col < bw->cols; col++) { index = (row * bw->cols) + col; frame = &frameset->children[index]; window = &bw->children[index]; if (frame->url) { browser_window_navigate(window, frame->url, hlcache_handle_get_url(parent), BW_NAVIGATE_HISTORY | BW_NAVIGATE_UNVERIFIABLE, NULL, NULL, parent); } } } return NSERROR_OK; }