diff options
-rw-r--r-- | Docs/source-object-backing-store | 28 | ||||
-rw-r--r-- | amiga/gui.c | 91 | ||||
-rw-r--r-- | amiga/menu.c | 83 | ||||
-rwxr-xr-x | amiga/misc.c | 6 | ||||
-rwxr-xr-x | amiga/schedule.c | 171 | ||||
-rw-r--r-- | amiga/theme.c | 103 | ||||
-rw-r--r-- | amiga/theme.h | 4 | ||||
-rwxr-xr-x | atari/misc.c | 11 | ||||
-rwxr-xr-x | atari/schedule.h | 15 | ||||
-rw-r--r-- | beos/gui.cpp | 30 | ||||
-rw-r--r-- | content/fetch.c | 47 | ||||
-rw-r--r-- | content/fs_backing_store.c | 125 | ||||
-rw-r--r-- | framebuffer/fbtk.h | 5 | ||||
-rw-r--r-- | riscos/history.c | 5 | ||||
-rw-r--r-- | riscos/window.c | 36 | ||||
-rw-r--r-- | riscos/window.h | 6 | ||||
-rw-r--r-- | utils/file.h | 2 | ||||
-rw-r--r-- | windows/findfile.c | 2 |
18 files changed, 461 insertions, 309 deletions
diff --git a/Docs/source-object-backing-store b/Docs/source-object-backing-store index e55a99db3..5d4d3049d 100644 --- a/Docs/source-object-backing-store +++ b/Docs/source-object-backing-store @@ -34,8 +34,8 @@ As the backing store only holds cache data one should not expect a great deal of effort to be expended converting formats (i.e. the cache may simply be discarded). -Layout version 1 ----------------- +Layout version 1.1 +------------------ An object has an identifier value generated from the url (NetSurf backing stores uses the url as the unique key). The value used is @@ -54,7 +54,7 @@ overhead of reconstructing it at initialisation and to keep the data used to improve the eviction decisions. Each object is stored and retrived directly into the filesystem using -a filename generated from a base64url encoding of an address +a filename generated from a RFC4648 base32 encoding of an address value. The objects address is derived from the identifier by cropping it to a shorter length. @@ -71,17 +71,27 @@ E.g. Linux based systems can easily cope with several megabytes of mmaped index but RISC OS might want to limit this to a few megabytes of heap at most. -The files are stored on disc using their base64url address value. +The files are stored on disc using their base32 address value. By creating a directory for each character of the encoded filename (except the last which is of course the leafname) we create a -directory structure where no directory has more than 64 entries. +directory structure where no directory has more than 32 entries. -E.g. A 19bit address of 0x1 would be base64url encoded into AAAB +E.g. A 19bit address of 0x1 would be base32 encoded into AAAB resulting in the data being stored in a file path of -"/store/prefix/data/B/A/A/BAAAAA". +"/store/prefix/d/B/A/A/BAAAAA". An address of 0x00040001 encodes to BAAB and a file path of -"/store/prefix/meta/B/A/A/BAABAA" +"/store/prefix/m/B/A/A/BAABAAA" + +Version 1.0 +----------- + +The version 1 layout was identical to the 1.1 except base64url +encoding was used, this proved problematic as some systems filesystems +were case insensitive so upper and lower case letetrs collided. + +There is no upgrade provision from the previous version simply delete +the cache directory. Control files ~~~~~~~~~~~~~ @@ -99,7 +109,7 @@ filesystem. Each control file table entry is 28 bytes and consists of - - signed 64 but value for last use time + - signed 64 bit value for last use time - 32bit full url hash allowing for index reconstruction and addiitonal collision detection. Also the possibility of increasing diff --git a/amiga/gui.c b/amiga/gui.c index bc01ff99e..9bf049a15 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -18,6 +18,7 @@ /* NetSurf core includes */ #include "content/backing_store.h" +#include "content/fetchers.h" #include "content/fetchers/resource.h" #include "content/urldb.h" #include "css/utils.h" @@ -171,9 +172,6 @@ ULONG screen_signal = -1; struct MsgPort *applibport = NULL; ULONG applibsig = 0; -BOOL refresh_search_ico = FALSE; -BOOL refresh_favicon = FALSE; -BOOL refresh_throbber = FALSE; struct Hook newprefs_hook; STRPTR temp_homepage_url = NULL; @@ -1419,6 +1417,12 @@ static void gui_window_set_icon(struct gui_window *g, hlcache_handle *icon) g->favicon = icon; } +static void ami_gui_refresh_favicon(void *p) +{ + struct gui_window_2 *gwin = (struct gui_window_2 *)p; + gui_window_set_icon(gwin->bw->window, gwin->bw->window->favicon); +} + void ami_handle_msg(void) { ULONG class,result,storage = 0,x,y,xs,ys,width=800,height=600; @@ -2116,7 +2120,7 @@ void ami_handle_msg(void) case AMINS_WINDOW: ami_set_border_gadget_balance(gwin); - ami_update_throbber(gwin,true); + ami_throbber_redraw_schedule(0, gwin->bw->window); if(gwin->tabs) { @@ -2131,7 +2135,7 @@ void ami_handle_msg(void) } while(tab=ntab); } - refresh_favicon = TRUE; + ami_schedule(0, ami_gui_refresh_favicon, gwin); browser_window_schedule_reformat(gwin->bw); ami_schedule_redraw(gwin, true); break; @@ -2201,31 +2205,8 @@ void ami_handle_msg(void) // ReplyMsg((struct Message *)message); } - if(node->Type == AMINS_WINDOW) - { - if(gwin->bw->window->throbbing) - ami_update_throbber(gwin,false); - } } while(node = nnode); - if(refresh_search_ico) - { - search_web_select_provider(-1); - refresh_search_ico = FALSE; - } - - if(refresh_favicon) - { - gui_window_set_icon(gwin->bw->window, gwin->bw->window->favicon); - refresh_favicon = FALSE; - } - - if(refresh_throbber) - { - ami_update_throbber(gwin, true); - refresh_throbber = FALSE; - } - if(ami_menu_window_close) { if(ami_menu_window_close == (void *)AMI_MENU_WINDOW_CLOSE_ALL) @@ -2456,15 +2437,39 @@ void ami_get_msg(void) ULONG appsig = 1L << appport->mp_SigBit; ULONG schedulesig = 1L << msgport->mp_SigBit; ULONG ctrlcsig = SIGBREAKF_CTRL_C; - ULONG signal; + uint32 signal = 0; + fd_set read_fd_set, write_fd_set, except_fd_set; + int max_fd = -1; struct TimerRequest *timermsg = NULL; struct MsgPort *printmsgport = ami_print_get_msgport(); ULONG printsig = 0; ULONG helpsignal = ami_help_signal(); if(printmsgport) printsig = 1L << printmsgport->mp_SigBit; - ULONG signalmask = winsignal | appsig | schedulesig | rxsig | printsig | applibsig | ctrlcsig | helpsignal; - - signal = Wait(signalmask); + uint32 signalmask = winsignal | appsig | schedulesig | rxsig | + printsig | applibsig | helpsignal; + + if ((fetcher_fdset(&read_fd_set, &write_fd_set, &except_fd_set, &max_fd) == NSERROR_OK) && + (max_fd != -1)) { + /* max_fd is the highest fd in use, but waitselect() needs to know how many + * are in use, so we add 1. */ + if (waitselect(max_fd + 1, &read_fd_set, &write_fd_set, &except_fd_set, + NULL, (unsigned int *)&signalmask) != -1) { + signal = signalmask; + } else { + LOG(("waitselect() returned error")); + /* \todo Fix Ctrl-C handling. + * WaitSelect() from bsdsocket.library returns -1 if the task was + * signalled with a Ctrl-C. waitselect() from newlib.library does not. + * Adding the Ctrl-C signal to our user signal mask causes a Ctrl-C to + * occur sporadically. Otherwise we never get a -1 except on error. + * NetSurf still terminates at the Wait() when network activity is over. + */ + } + } else { + /* If fetcher_fdset fails or no network activity, do it the old fashioned way. */ + signalmask |= ctrlcsig; + signal = Wait(signalmask); + } if(signal & winsignal) ami_handle_msg(); @@ -2547,8 +2552,8 @@ void ami_switch_tab(struct gui_window_2 *gwin,bool redraw) GetAttr(CLICKTAB_CurrentNode, (Object *)gwin->objects[GID_TABS], (ULONG *)&tabnode); GetClickTabNodeAttrs(tabnode, - TNA_UserData, &gwin->bw, - TAG_DONE); + TNA_UserData, &gwin->bw, + TAG_DONE); curbw = gwin->bw; GetAttr(SPACE_AreaBox, (Object *)gwin->objects[GID_BROWSER], (ULONG *)&bbox); @@ -2572,7 +2577,6 @@ void ami_switch_tab(struct gui_window_2 *gwin,bool redraw) p96RectFill(gwin->win->RPort, bbox->Left, bbox->Top, bbox->Width+bbox->Left, bbox->Height+bbox->Top, 0xffffffff); - browser_window_update(gwin->bw, false); gui_window_set_scroll(gwin->bw->window, @@ -2580,8 +2584,8 @@ void ami_switch_tab(struct gui_window_2 *gwin,bool redraw) gwin->redraw_scroll = false; browser_window_refresh_url_bar(gwin->bw); - ami_gui_update_hotlist_button(gwin); + ami_throbber_redraw_schedule(0, gwin->bw->window); } } @@ -3128,6 +3132,11 @@ void ami_gui_tabs_toggle_all(void) } while(node = nnode); } +void ami_gui_search_ico_refresh(void *p) +{ + search_web_select_provider(-1); +} + nserror ami_gui_new_blank_tab(struct gui_window_2 *gwin) { nsurl *url; @@ -3250,6 +3259,7 @@ gui_window_create(struct browser_window *bw, if(nsoption_bool(new_tab_is_active)) ami_switch_tab(g->shared,false); ami_update_buttons(g->shared); + ami_schedule(0, ami_gui_refresh_favicon, g->shared); return g; } @@ -3772,7 +3782,7 @@ gui_window_create(struct browser_window *bw, if(locked_screen) UnlockPubScreen(NULL,scrn); - refresh_search_ico = TRUE; + ami_schedule(0, ami_gui_search_ico_refresh, NULL); ScreenToFront(scrn); @@ -4676,7 +4686,7 @@ static void gui_window_set_url(struct gui_window *g, const char *url) static uint32 ami_set_favicon_render_hook(struct Hook *hook, APTR space, struct gpRender *msg) { - refresh_favicon = TRUE; + ami_schedule(0, ami_gui_refresh_favicon, hook->h_Data); return 0; } @@ -4736,7 +4746,8 @@ static nserror gui_search_web_provider_update(const char *provider_name, static uint32 ami_set_throbber_render_hook(struct Hook *hook, APTR space, struct gpRender *msg) { - refresh_throbber = TRUE; + struct gui_window_2 *gwin = hook->h_Data; + ami_throbber_redraw_schedule(0, gwin->bw->window); return 0; } @@ -5129,6 +5140,8 @@ int main(int argc, char** argv) .llcache = filesystem_llcache_table, }; + signal(SIGINT, SIG_IGN); + ret = netsurf_register(&amiga_table); if (ret != NSERROR_OK) { die("NetSurf operation table failed registration"); diff --git a/amiga/menu.c b/amiga/menu.c index 784fec163..c1e863a65 100644 --- a/amiga/menu.c +++ b/amiga/menu.c @@ -35,8 +35,6 @@ #include <images/label.h> #include <proto/bitmap.h> #include <images/bitmap.h> -#include <proto/glyph.h> -#include <images/glyph.h> #include <reaction/reaction_macros.h> @@ -358,13 +356,34 @@ void ami_menu_free_glyphs(void) menu_glyphs_loaded = false; } +static int ami_menu_calc_item_width(struct gui_window_2 *gwin, int j, struct RastPort *rp) +{ + int space_width = TextLength(rp, " ", 1); + int item_size; + + item_size = TextLength(rp, gwin->menulab[j], strlen(gwin->menulab[j])); + item_size += space_width; + + if(gwin->menukey[j]) { + item_size += TextLength(rp, &gwin->menukey[j], 1); + item_size += menu_glyph_width[NSA_GLYPH_AMIGAKEY]; + /**TODO: take account of the size of other imagery too + */ + } + + return item_size; +} + + static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) { int i, j; - int txtlen = 0; + int txtlen = 0, subtxtlen = 0; + int left_posn; struct RastPort *rp = &scrn->RastPort; struct DrawInfo *dri = GetScreenDrawInfo(scrn); - + int space_width = TextLength(rp, " ", 1); + if(menu_glyphs_loaded == false) ami_menu_load_glyphs(dri); @@ -373,18 +392,10 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) if(gwin->menutype[i] == NM_TITLE) { j = i + 1; txtlen = 0; - int item_size = 0; do { if(gwin->menulab[j] != NM_BARLABEL) { if(gwin->menutype[j] == NM_ITEM) { - item_size = TextLength(rp, gwin->menulab[j], strlen(gwin->menulab[j])); - if(gwin->menukey[j]) { - item_size += TextLength(rp, &gwin->menukey[j], 1); - item_size += menu_glyph_width[NSA_GLYPH_AMIGAKEY]; - /**TODO: take account of the size of other imagery too - */ - } - + int item_size = ami_menu_calc_item_width(gwin, j, rp); if(item_size > txtlen) { txtlen = item_size; } @@ -399,6 +410,7 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) using label.image if there's a bitmap associated with the item. */ if((gwin->menuicon[i] != NULL) && (gwin->menulab[i] != NM_BARLABEL)) { int icon_width = 0; + Object *blank_space = NULL; Object *submenuarrow = NULL; Object *icon = BitMapObject, BITMAP_Screen, scrn, @@ -413,25 +425,60 @@ static struct gui_window_2 *ami_menu_layout(struct gui_window_2 *gwin) TAG_DONE); GetAttr(IA_Width, icon, (ULONG *)&icon_width); - + + if(gwin->menutype[i] == NM_SUB) { + left_posn = subtxtlen; + } else { + left_posn = txtlen; + } + + left_posn = left_posn - + TextLength(rp, gwin->menulab[i], strlen(gwin->menulab[i])) - + icon_width - space_width; + if((gwin->menutype[i] == NM_ITEM) && (gwin->menutype[i+1] == NM_SUB)) { + left_posn -= menu_glyph_width[NSA_GLYPH_SUBMENU]; + submenuarrow = NewObject(NULL, "sysiclass", - SYSIA_Which, MENUSUB, - SYSIA_DrawInfo, dri, - IA_Left, txtlen - TextLength(rp, gwin->menulab[i], strlen(gwin->menulab[i])) - - menu_glyph_width[NSA_GLYPH_SUBMENU] - icon_width, + SYSIA_Which, MENUSUB, + SYSIA_DrawInfo, dri, + IA_Left, left_posn, TAG_DONE); + + j = i + 1; + subtxtlen = 0; + do { + if(gwin->menulab[j] != NM_BARLABEL) { + if(gwin->menutype[j] == NM_SUB) { + int item_size = ami_menu_calc_item_width(gwin, j, rp); + if(item_size > subtxtlen) { + subtxtlen = item_size; + } + } + } + j++; + } while((gwin->menutype[j] == NM_SUB)); } /**TODO: Checkmark/MX images and keyboard shortcuts */ + + if(gwin->menutype[i] == NM_SUB) { + blank_space = NewObject(NULL, "fillrectclass", + IA_Height, 0, + IA_Width, left_posn + icon_width, + TAG_DONE); + } gwin->menuobj[i] = LabelObject, LABEL_DrawInfo, dri, LABEL_DisposeImage, TRUE, LABEL_Image, icon, + LABEL_Text, " ", LABEL_Text, gwin->menulab[i], LABEL_DisposeImage, TRUE, + LABEL_Image, blank_space, + LABEL_DisposeImage, TRUE, LABEL_Image, submenuarrow, LabelEnd; diff --git a/amiga/misc.c b/amiga/misc.c index 67240006d..7d126c906 100755 --- a/amiga/misc.c +++ b/amiga/misc.c @@ -112,7 +112,7 @@ void die(const char *error) /** * Create a path from a nsurl using amiga file handling. * - * @parm[in] url The url to encode. + * @param[in] url The url to encode. * @param[out] path_out A string containing the result path which should * be freed by the caller. * @return NSERROR_OK and the path is written to \a path or error code @@ -254,8 +254,8 @@ char *translate_escape_chars(const char *s) * @param[in,out] size The size of the space available if \a str not * NULL on input and if not NULL set to the total * output length on output. - * @param[in] nemb The number of elements. - * @param[in] ... The elements of the path as string pointers. + * @param[in] nelm The number of elements. + * @param[in] ap The elements of the path as string pointers. * @return NSERROR_OK and the complete path is written to str * or error code on faliure. */ diff --git a/amiga/schedule.c b/amiga/schedule.c index 9aa74881f..6222917cf 100755 --- a/amiga/schedule.c +++ b/amiga/schedule.c @@ -39,7 +39,15 @@ struct nscallback PblHeap *schedule_list; -static void ami_remove_timer_event(struct nscallback *nscb) +/** + * Remove timer event + * + * \param nscb callback + * + * The timer event for the callback is aborted + */ + +static void ami_schedule_remove_timer_event(struct nscallback *nscb) { if(!nscb) return; @@ -54,48 +62,112 @@ static void ami_remove_timer_event(struct nscallback *nscb) } /** - * Unschedule a callback. + * Add timer event + * + * \param nscb callback + * \param t time in ms + * + * NetSurf will be signalled in t ms for this event. + */ + +static nserror ami_schedule_add_timer_event(struct nscallback *nscb, int t) +{ + struct TimeVal tv; + ULONG time_us = t * 1000; /* t converted to µs */ + + nscb->tv.Seconds = time_us / 1000000; + nscb->tv.Microseconds = time_us % 1000000; + + GetSysTime(&tv); + AddTime(&nscb->tv,&tv); // now contains time when event occurs + + if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL)) { + *nscb->treq = *tioreq; + nscb->treq->Request.io_Command=TR_ADDREQUEST; + nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs + nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro + SendIO((struct IORequest *)nscb->treq); + } else { + return NSERROR_NOMEM; + } + + return NSERROR_OK; +} + +/** + * Locate a scheduled callback * * \param callback callback function * \param p user parameter, passed to callback function + * \param remove remove callback from the heap * - * All scheduled callbacks matching both callback and p are removed. + * A scheduled callback matching both callback and p is returned, or NULL if none present. */ -static nserror schedule_remove(void (*callback)(void *p), void *p) +static struct nscallback *ami_schedule_locate(void (*callback)(void *p), void *p, bool remove) { PblIterator *iterator; struct nscallback *nscb; - bool restoreheap = false; - - /* check there is something on the list to remove */ - if (schedule_list == NULL) - { - return NSERROR_OK; - } + bool found_cb = false; - if(pblHeapIsEmpty(schedule_list)) - { - return NSERROR_OK; - } + /* check there is something on the list */ + if (schedule_list == NULL) return NULL; + if(pblHeapIsEmpty(schedule_list)) return NULL; iterator = pblHeapIterator(schedule_list); - while ((nscb = pblIteratorNext(iterator)) != -1) - { - if((nscb->callback == callback) && (nscb->p == p)) - { - ami_remove_timer_event(nscb); - pblIteratorRemove(iterator); - FreeVec(nscb); - restoreheap = true; + while ((nscb = pblIteratorNext(iterator)) != -1) { + if ((nscb->callback == callback) && (nscb->p == p)) { + if (remove == true) pblIteratorRemove(iterator); + found_cb = true; + break; } }; pblIteratorFree(iterator); - if(restoreheap) - { + if (found_cb == true) return nscb; + else return NULL; +} + +/** + * Reschedule a callback. + * + * \param nscb callback + * \param t time in ms + * + * The nscallback will be rescheduled for t ms. + */ + +static nserror ami_schedule_reschedule(struct nscallback *nscb, int t) +{ + ami_schedule_remove_timer_event(nscb); + if (ami_schedule_add_timer_event(nscb, t) != NSERROR_OK) + return NSERROR_NOMEM; + + pblHeapConstruct(schedule_list); + return NSERROR_OK; +} + +/** + * Unschedule a callback. + * + * \param callback callback function + * \param p user parameter, passed to callback function + * + * All scheduled callbacks matching both callback and p are removed. + */ + +static nserror schedule_remove(void (*callback)(void *p), void *p) +{ + PblIterator *iterator; + struct nscallback *nscb; + + nscb = ami_schedule_locate(callback, p, true); + + if(nscb != NULL) { + ami_schedule_remove_timer_event(nscb); + FreeVec(nscb); pblHeapConstruct(schedule_list); } @@ -113,7 +185,7 @@ static void schedule_remove_all(void) while ((nscb = pblIteratorNext(iterator)) != -1) { - ami_remove_timer_event(nscb); + ami_schedule_remove_timer_event(nscb); pblIteratorRemove(iterator); FreeVec(nscb); }; @@ -155,7 +227,7 @@ void schedule_run(BOOL poll) callback = nscb->callback; p = nscb->p; - ami_remove_timer_event(nscb); + ami_schedule_remove_timer_event(nscb); pblHeapRemoveFirst(schedule_list); FreeVec(nscb); callback(p); @@ -200,11 +272,7 @@ void ami_schedule_open_timer(void) /* exported function documented in amiga/schedule.h */ void ami_schedule_close_timer(void) { - if(ITimer) - { - DropInterface((struct Interface *)ITimer); - } - + if(ITimer) DropInterface((struct Interface *)ITimer); CloseDevice((struct IORequest *) tioreq); FreeSysObject(ASOT_IOREQUEST,tioreq); FreeSysObject(ASOT_PORT,msgport); @@ -214,41 +282,19 @@ void ami_schedule_close_timer(void) nserror ami_schedule(int t, void (*callback)(void *p), void *p) { struct nscallback *nscb; - struct TimeVal tv; - ULONG time_us = 0; - - if(schedule_list == NULL) - { - return NSERROR_INIT_FAILED; - } - if(t < 0) - { - return schedule_remove(callback, p); + if(schedule_list == NULL) return NSERROR_INIT_FAILED; + if (t < 0) return schedule_remove(callback, p); + + if (nscb = ami_schedule_locate(callback, p, false)) { + return ami_schedule_reschedule(nscb, t); } nscb = AllocVecTagList(sizeof(struct nscallback), NULL); - if(!nscb) - { - return NSERROR_NOMEM; - } - - time_us = t * 1000; /* t converted to µs */ - - nscb->tv.Seconds = time_us / 1000000; - nscb->tv.Microseconds = time_us % 1000000; + if(!nscb) return NSERROR_NOMEM; - GetSysTime(&tv); - AddTime(&nscb->tv,&tv); // now contains time when event occurs - - if(nscb->treq = AllocVecTagList(sizeof(struct TimeRequest), NULL)) - { - *nscb->treq = *tioreq; - nscb->treq->Request.io_Command=TR_ADDREQUEST; - nscb->treq->Time.Seconds=nscb->tv.Seconds; // secs - nscb->treq->Time.Microseconds=nscb->tv.Microseconds; // micro - SendIO((struct IORequest *)nscb->treq); - } + if (ami_schedule_add_timer_event(nscb, t) != NSERROR_OK) + return NSERROR_NOMEM; nscb->callback = callback; nscb->p = p; @@ -257,3 +303,4 @@ nserror ami_schedule(int t, void (*callback)(void *p), void *p) return NSERROR_OK; } + diff --git a/amiga/theme.c b/amiga/theme.c index 29c72574b..cc8b55d7f 100644 --- a/amiga/theme.c +++ b/amiga/theme.c @@ -36,11 +36,12 @@ #include "amiga/bitmap.h" #include "amiga/drag.h" -#include "desktop/browser_private.h" -#include "utils/nsoption.h" +#include "amiga/schedule.h" #include "amiga/theme.h" +#include "desktop/browser_private.h" #include "desktop/searchweb.h" #include "utils/messages.h" +#include "utils/nsoption.h" #include "utils/utils.h" struct BitMap *throbber = NULL; @@ -157,7 +158,7 @@ void ami_theme_throbber_setup(void) ami_get_theme_filename(throbberfile,"theme_throbber",false); throbber_frames=atoi(messages_get("theme_throbber_frames")); throbber_update_interval = atoi(messages_get("theme_throbber_delay")); - if(throbber_update_interval == 0) throbber_update_interval = 100; + if(throbber_update_interval == 0) throbber_update_interval = 250; bm = ami_bitmap_from_datatype(throbberfile); throbber = ami_bitmap_get_native(bm, bm->width, bm->height, NULL); @@ -423,16 +424,8 @@ void gui_window_start_throbber(struct gui_window *g) } g->throbbing = true; - - if((cur_tab == g->tab) || (g->shared->tabs <= 1)) - { - GetAttr(SPACE_AreaBox, g->shared->objects[GID_THROBBER], - (ULONG *)&bbox); - - if(g->shared->throbber_frame == 0) g->shared->throbber_frame=1; - - BltBitMapRastPort(throbber,throbber_width,0,g->shared->win->RPort,bbox->Left,bbox->Top,throbber_width,throbber_height,0x0C0); - } + if(g->shared->throbber_frame == 0) g->shared->throbber_frame = 1; + ami_throbber_redraw_schedule(throbber_update_interval, g); } void gui_window_stop_throbber(struct gui_window *g) @@ -452,8 +445,6 @@ void gui_window_stop_throbber(struct gui_window *g) g->shared->win, NULL); } - g->throbbing = false; - if((cur_tab == g->tab) || (g->shared->tabs <= 1)) { GetAttr(SPACE_AreaBox, g->shared->objects[GID_THROBBER], @@ -462,60 +453,58 @@ void gui_window_stop_throbber(struct gui_window *g) BltBitMapRastPort(throbber, 0, 0, g->shared->win->RPort, bbox->Left, bbox->Top, throbber_width, throbber_height, 0x0C0); } -// g->shared->throbber_frame = 0; + + g->throbbing = false; + ami_throbber_redraw_schedule(-1, g); } -void ami_update_throbber(struct gui_window_2 *g, bool redraw) +static void ami_throbber_update(void *p) { + struct gui_window *g = (struct gui_window *)p; struct IBox *bbox; - int frame; + int frame = 0; + ULONG cur_tab = 0; if(!g) return; - if(!g->objects[GID_THROBBER]) return; + if(!g->shared->objects[GID_THROBBER]) return; - if(g->bw->window->throbbing == false) - { - frame = 0; - g->throbber_frame = 1; + if(g->throbbing == true) { + frame = g->shared->throbber_frame; + g->shared->throbber_frame++; + if(g->shared->throbber_frame > (throbber_frames-1)) + g->shared->throbber_frame=1; } - else - { - frame = g->throbber_frame; - if(!redraw) - { - if(g->throbber_update_count < throbber_update_interval) - { - g->throbber_update_count++; - return; - } - - g->throbber_update_count = 0; + if(g->tab_node && (g->shared->tabs > 1)) + { + GetAttr(CLICKTAB_Current, g->shared->objects[GID_TABS], + (ULONG *)&cur_tab); + } - g->throbber_frame++; - if(g->throbber_frame > (throbber_frames-1)) - g->throbber_frame=1; + if((cur_tab == g->tab) || (g->shared->tabs <= 1)) + { + GetAttr(SPACE_AreaBox, g->shared->objects[GID_THROBBER], + (ULONG *)&bbox); - } + BltBitMapTags(BLITA_SrcX, throbber_width * frame, + BLITA_SrcY, 0, + BLITA_DestX, bbox->Left, + BLITA_DestY, bbox->Top, + BLITA_Width, throbber_width, + BLITA_Height, throbber_height, + BLITA_Source, throbber, + BLITA_Dest, g->shared->win->RPort, + BLITA_SrcType, BLITT_BITMAP, + BLITA_DestType, BLITT_RASTPORT, + // BLITA_UseSrcAlpha, TRUE, + TAG_DONE); } - GetAttr(SPACE_AreaBox,(Object *)g->objects[GID_THROBBER],(ULONG *)&bbox); + if(frame > 0) ami_throbber_redraw_schedule(throbber_update_interval, g); +} -/* - EraseRect(g->win->RPort,bbox->Left,bbox->Top, - bbox->Left+throbber_width,bbox->Top+throbber_height); -*/ - - BltBitMapTags(BLITA_SrcX, throbber_width * frame, - BLITA_SrcY,0, - BLITA_DestX,bbox->Left, - BLITA_DestY,bbox->Top, - BLITA_Width,throbber_width, - BLITA_Height,throbber_height, - BLITA_Source,throbber, - BLITA_Dest,g->win->RPort, - BLITA_SrcType,BLITT_BITMAP, - BLITA_DestType,BLITT_RASTPORT, -// BLITA_UseSrcAlpha,TRUE, - TAG_DONE); +void ami_throbber_redraw_schedule(int t, struct gui_window *g) +{ + ami_schedule(t, ami_throbber_update, g); } + diff --git a/amiga/theme.h b/amiga/theme.h index e81db33dd..c1aca15d7 100644 --- a/amiga/theme.h +++ b/amiga/theme.h @@ -44,6 +44,8 @@ void ami_update_pointer(struct Window *win, gui_pointer_shape shape); void gui_window_start_throbber(struct gui_window *g); void gui_window_stop_throbber(struct gui_window *g); -void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape); +void ami_throbber_redraw_schedule(int t, struct gui_window *g); +void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape); #endif + diff --git a/atari/misc.c b/atari/misc.c index e689b8249..bd3158406 100755 --- a/atari/misc.c +++ b/atari/misc.c @@ -203,12 +203,15 @@ static nserror load_icon_callback(hlcache_handle *handle, /** * utility function. Copied from NetSurf tree API. * - * \param name the name of the loaded icon, if it's not a full path the icon is - * looked for in the directory specified by icons_dir + * \param name the name of the loaded icon, if it's not a full path + * the icon is looked for in the directory specified by + * icons_dir. + * \param cb callback function to deal with hlcache callback. + * \param pw Context pointer to be passed to callback. * \return the icon in form of a content or NULL on failure */ -hlcache_handle *load_icon(const char *name, hlcache_handle_callback cb, - void * pw ) +hlcache_handle * +load_icon(const char *name, hlcache_handle_callback cb, void *pw) { hlcache_handle *c; nserror err; diff --git a/atari/schedule.h b/atari/schedule.h index 47d8c2ddf..05eebb2d7 100755 --- a/atari/schedule.h +++ b/atari/schedule.h @@ -22,20 +22,23 @@ /** * Process events up to current time. + * + * \return The number of miliseconds until the next scheduled event. */ int schedule_run(void); /** * Schedule a callback. * - * \param tival interval before the callback should be made in ms - * \param callback callback function - * \param p user parameter, passed to callback function + * \param ival interval before the callback should be made in miliseconds. + * \param callback callback function. + * \param p user parameter, passed to callback function. + * \return NSERROR_OK on success or appropriate error code. * - * The callback function will be called as soon as possible after t ms have - * passed. + * The callback function will be called as soon as possible after \a ival + * ms have passed. */ -nserror atari_schedule(int cs_ival, void (*callback)(void *p), void *p); +nserror atari_schedule(int ival, void (*callback)(void *p), void *p); /** * LOG all current scheduled events. diff --git a/beos/gui.cpp b/beos/gui.cpp index 84f397b0b..cb7effead 100644 --- a/beos/gui.cpp +++ b/beos/gui.cpp @@ -299,22 +299,28 @@ static char *find_resource(char *buf, const char *filename, const char *def) BPathFinder f((void*)find_resource); BPath p; - f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res/", p); - strcpy(t, p.Path()); - - strcat(t, filename); - realpath(t, buf); - if (access(buf, R_OK) == 0) - return buf; + if (f.FindPath(B_FIND_PATH_APPS_DIRECTORY, "netsurf/res", p) == B_OK) { + strcpy(t, p.Path()); + strcat(t, filename); + realpath(t, buf); + if (access(buf, R_OK) == 0) + return buf; + } if (def[0] == '%') { snprintf(t, PATH_MAX, "%s%s", path.Path(), def + 1); - realpath(t, buf); + if (realpath(t, buf) == NULL) { + strcpy(buf, t); + } } else if (def[0] == '~') { snprintf(t, PATH_MAX, "%s%s", getenv("HOME"), def + 1); - realpath(t, buf); + if (realpath(t, buf) == NULL) { + strcpy(buf, t); + } } else { - realpath(def, buf); + if (realpath(def, buf) == NULL) { + strcpy(buf, def); + } } return buf; @@ -724,8 +730,8 @@ static void gui_poll(bool active) // our own event pipe FD_SET(sEventPipe[0], &read_fd_set); - /** @todo Check if this max_fd should have + 1 */ - max_fd = MAX(max_fd, sEventPipe[0] + 1); + // max of all the fds in the set, plus one for select() + max_fd = MAX(max_fd, sEventPipe[0]) + 1; // compute schedule timeout if (earliest_callback_timeout != B_INFINITE_TIMEOUT) { diff --git a/content/fetch.c b/content/fetch.c index 3d1183aa0..2160204ef 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -61,17 +61,27 @@ /* Define this to turn on verbose fetch logging */ #undef DEBUG_FETCH_VERBOSE -#define DEBUG_FETCH_VERBOSE - -/** The maximum number of fetchers that can be added */ -#define MAX_FETCHERS 8 +/** Verbose fetcher logging */ #ifdef DEBUG_FETCH_VERBOSE #define FETCH_LOG(x) LOG(x) #else #define FETCH_LOG(x) #endif +/** The maximum number of fetchers that can be added */ +#define MAX_FETCHERS 8 + +/** The time in ms between polling the fetchers. + * + * \todo The schedule timeout should be profiled to see if there is a + * better value or even if it needs to be dynamic. + */ +#define SCHEDULE_TIME 10 + +/** The fdset timeout in ms */ +#define FDSET_TIMEOUT 1000 + /** * Information about a fetcher for a given scheme. */ @@ -265,7 +275,7 @@ static void fetcher_poll(void *unused) } /* schedule active fetchers to run again in 10ms */ - guit->browser->schedule(10, fetcher_poll, NULL); + guit->browser->schedule(SCHEDULE_TIME, fetcher_poll, NULL); } } @@ -290,9 +300,28 @@ void fetcher_quit(void) { int fetcherd; /* fetcher index */ for (fetcherd = 0; fetcherd < MAX_FETCHERS; fetcherd++) { - if (fetchers[fetcherd].refcount > 0) { - /* assert if the fetcher is active at quit */ - assert(fetchers[fetcherd].refcount == 1); + if (fetchers[fetcherd].refcount > 1) { + /* fetcher still has reference at quit. This + * should not happen as the fetch should have + * been aborted in llcache shutdown. + * + * This appears to be normal behaviour if a + * curl operation is still in progress at exit + * as the abort waits for curl to complete. + * + * We could make the user wait for curl to + * complete but we are exiting anyway so thats + * unhelpful. Instead we just log it and force + * the reference count to allow the fetcher to + * be stopped. + */ + LOG(("Fetcher for scheme %s still has %d active users at quit.", + lwc_string_data(fetchers[fetcherd].scheme), + fetchers[fetcherd].refcount)); + + fetchers[fetcherd].refcount = 1; + } + if (fetchers[fetcherd].refcount == 1) { fetch_unref_fetcher(fetcherd); } @@ -376,7 +405,7 @@ nserror fetcher_fdset(fd_set *read_fd_set, * select on. All the other fetchers continue to need * polling frequently. */ - guit->browser->schedule(1000, fetcher_poll, NULL); + guit->browser->schedule(FDSET_TIMEOUT, fetcher_poll, NULL); } *maxfd_out = maxfd; diff --git a/content/fs_backing_store.c b/content/fs_backing_store.c index d29fcaac7..fde17ed62 100644 --- a/content/fs_backing_store.c +++ b/content/fs_backing_store.c @@ -54,7 +54,7 @@ #define DEFAULT_ENTRY_SIZE 16 /** Backing store file format version */ -#define CONTROL_VERSION 100 +#define CONTROL_VERSION 110 /** Get address from ident */ #define BS_ADDRESS(ident, state) ((ident) & ((1 << state->ident_bits) - 1)) @@ -215,6 +215,26 @@ remove_store_entry(struct store_state *state, /** * Generate a filename for an object. * + * this generates the filename for an object on disc. It is necessary + * for this to generate a filename which conforms to the limitations + * of all the filesystems the cache can be placed upon. + * + * From http://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits + * the relevant subset is: + * - path elements no longer than 8 characters + * - acceptable characters are A-Z, 0-9 + * - short total path lengths (255 or less) + * + * The short total path lengths mean the encoding must represent as + * much data as possible in the least number of characters. + * + * To achieve all these goals we use RFC4648 base32 encoding which packs + * 5bits into each character of the filename. + * + * @note Version 1.00 of the cache implementation used base64 to + * encode this, however that did not meet the requirement for only + * using uppercase characters. + * * @param state The store state to use. * @param ident The identifier to use. * @return The filename string or NULL on allocation error. @@ -225,96 +245,79 @@ store_fname(struct store_state *state, enum backing_store_flags flags) { char *fname = NULL; - uint8_t b64u_i[7]; /* base64 ident */ - uint8_t b64u_d[6][2]; /* base64 ident as separate components */ + uint8_t b32u_i[8]; /* base32 encoded ident */ + uint8_t b32u_d[6][2]; /* base64 ident as separate components */ const char *dat; - /** Base64url encoding table */ + /* RFC4648 base32 encoding table */ static const uint8_t encoding_table[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '-', '_' + 'Y', 'Z', '2', '3', '4', '5', '6', '7' }; - /* base64 encode ident */ - b64u_i[0] = b64u_d[0][0] = encoding_table[(ident ) & 0x3f]; - b64u_i[1] = b64u_d[1][0] = encoding_table[(ident >> 6) & 0x3f]; - b64u_i[2] = b64u_d[2][0] = encoding_table[(ident >> 12) & 0x3f]; - b64u_i[3] = b64u_d[3][0] = encoding_table[(ident >> 18) & 0x3f]; - b64u_i[4] = b64u_d[4][0] = encoding_table[(ident >> 24) & 0x3f]; - b64u_i[5] = b64u_d[5][0] = encoding_table[(ident >> 30) & 0x3f]; + /* base32 encode ident */ + b32u_i[0] = b32u_d[0][0] = encoding_table[(ident ) & 0x1f]; + b32u_i[1] = b32u_d[1][0] = encoding_table[(ident >> 5) & 0x1f]; + b32u_i[2] = b32u_d[2][0] = encoding_table[(ident >> 10) & 0x1f]; + b32u_i[3] = b32u_d[3][0] = encoding_table[(ident >> 15) & 0x1f]; + b32u_i[4] = b32u_d[4][0] = encoding_table[(ident >> 20) & 0x1f]; + b32u_i[5] = b32u_d[5][0] = encoding_table[(ident >> 25) & 0x1f]; + b32u_i[6] = encoding_table[(ident >> 30) & 0x1f]; /* null terminate strings */ - b64u_i[6] = b64u_d[0][1] = b64u_d[1][1] = b64u_d[2][1] = - b64u_d[3][1] = b64u_d[4][1] = b64u_d[5][1] = 0; + b32u_i[7] = b32u_d[0][1] = b32u_d[1][1] = b32u_d[2][1] = + b32u_d[3][1] = b32u_d[4][1] = b32u_d[5][1] = 0; if ((flags & BACKING_STORE_META) != 0) { - dat = "meta"; + dat = "m"; /* metadata */ } else { - dat = "data"; + dat = "d"; /* data */ } - /* number of chars with usefully encoded data in b64 */ - switch(((state->ident_bits + 5) / 6)) { + /* number of chars with usefully encoded data in base 32 */ + switch(((state->ident_bits + 4) / 5)) { case 1: - netsurf_mkpath(&fname, NULL, 3, - state->path, - dat, - b64u_i); + netsurf_mkpath(&fname, NULL, 3, state->path, dat, + b32u_i); break; case 2: - netsurf_mkpath(&fname, NULL, 4, - state->path, - dat, - b64u_d[0], - b64u_i); + netsurf_mkpath(&fname, NULL, 4, state->path, dat, + b32u_d[0], + b32u_i); break; case 3: - netsurf_mkpath(&fname, NULL, 5, - state->path, - dat, - b64u_d[0], - b64u_d[1], - b64u_i); + netsurf_mkpath(&fname, NULL, 5, state->path, dat, + b32u_d[0], b32u_d[1], + b32u_i); break; case 4: - netsurf_mkpath(&fname, NULL, 6, - state->path, - dat, - b64u_d[0], - b64u_d[1], - b64u_d[2], - b64u_i); + netsurf_mkpath(&fname, NULL, 6, state->path, dat, + b32u_d[0], b32u_d[1], b32u_d[2], + b32u_i); break; case 5: - netsurf_mkpath(&fname, NULL, 7, - state->path, - dat, - b64u_d[0], - b64u_d[1], - b64u_d[2], - b64u_d[3], - b64u_i); + netsurf_mkpath(&fname, NULL, 7, state->path, dat, + b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3], + b32u_i); break; case 6: - netsurf_mkpath(&fname, NULL, 8, - state->path, - dat, - b64u_d[0], - b64u_d[1], - b64u_d[2], - b64u_d[3], - b64u_d[4], - b64u_i); + netsurf_mkpath(&fname, NULL, 8, state->path, dat, + b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3], + b32u_d[4], + b32u_i); + break; + + case 7: + netsurf_mkpath(&fname, NULL, 9, state->path, dat, + b32u_d[0], b32u_d[1], b32u_d[2], b32u_d[3], + b32u_d[4], b32u_d[5], + b32u_i); break; default: diff --git a/framebuffer/fbtk.h b/framebuffer/fbtk.h index 220700fef..325db0e9b 100644 --- a/framebuffer/fbtk.h +++ b/framebuffer/fbtk.h @@ -312,7 +312,8 @@ int fbtk_destroy_widget(fbtk_widget_t *widget); /********************************* Widgets *********************************/ -/** Create a window widget. +/** + * Create a window widget. * * @param parent The parent window or the root widget for a top level window. * @param x The x location relative to the parent window. @@ -323,7 +324,7 @@ int fbtk_destroy_widget(fbtk_widget_t *widget); * window. * @param height The height of the window limited in a similar way to the * /a width. - * @param c The background colour. + * @param bg The background colour. * @return new window widget handle or NULL on error. */ fbtk_widget_t *fbtk_create_window(fbtk_widget_t *parent, int x, int y, int width, int height, colour bg); diff --git a/riscos/history.c b/riscos/history.c index 8c096b88c..3b8b63ae1 100644 --- a/riscos/history.c +++ b/riscos/history.c @@ -74,9 +74,8 @@ void ro_gui_history_init(void) /** * Open history window. * - * \param bw browser window to open history for - * \param history history to open - * \param at_pointer open the window at the pointer + * \param g The riscos window to open history for. + * \param at_pointer open the window at the pointer. */ void ro_gui_history_open(struct gui_window *g, bool at_pointer) diff --git a/riscos/window.c b/riscos/window.c index 3bb359d31..2ad432b2e 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -1071,13 +1071,7 @@ void gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape) } -/** - * Set the contents of a window's address bar. - * - * \param g gui_window to update - * \param url new url for address bar - */ - +/* exported function documented in riscos/window.h */ void gui_window_set_url(struct gui_window *g, const char *url) { if (!g->toolbar) @@ -3804,13 +3798,13 @@ bool ro_gui_window_check_menu(wimp_menu *menu) * Return boolean flags to show what RISC OS types we can sensibly convert * the given object into. * - * \TODO -- This should probably be somewhere else but in window.c, and - * should probably even be done in content_(). + * \todo This should probably be somewhere else but in window.c, and + * should probably even be done in content_(). * - * \param *h The object to test. - * \param *export_draw true on exit if a drawfile would be possible. - * \param *export_sprite true on exit if a sprite would be possible. - * \return true if valid data is returned; else false. + * \param h The object to test. + * \param export_draw true on exit if a drawfile would be possible. + * \param export_sprite true on exit if a sprite would be possible. + * \return true if valid data is returned; else false. */ bool ro_gui_window_content_export_types(hlcache_handle *h, @@ -3849,10 +3843,10 @@ bool ro_gui_window_content_export_types(hlcache_handle *h, /** * Return true if a browser window can navigate upwards. * - * \TODO -- This should probably be somewhere else but in window.c. + * \todo This should probably be somewhere else but in window.c. * - * \param *bw the browser window to test. - * \return true if navigation up is possible; else false. + * \param bw the browser window to test. + * \return true if navigation up is possible otherwise false. */ bool ro_gui_window_up_available(struct browser_window *bw) @@ -3980,8 +3974,8 @@ void ro_gui_window_prepare_objectinfo(hlcache_handle *object, const char *href) /** * Launch a new url in the given window. * - * \param g gui_window to update - * \param url url to be launched + * \param g gui_window to update + * \param url1 url to be launched */ void ro_gui_window_launch_url(struct gui_window *g, const char *url1) @@ -4846,8 +4840,8 @@ void ro_gui_window_process_form_select_menu(struct gui_window *g, /** * Convert a RISC OS window handle to a gui_window. * - * \param w RISC OS window handle - * \return pointer to a structure if found, 0 otherwise + * \param window RISC OS window handle. + * \return A pointer to a riscos gui window if found or NULL. */ struct gui_window *ro_gui_window_lookup(wimp_w window) @@ -4856,7 +4850,7 @@ struct gui_window *ro_gui_window_lookup(wimp_w window) for (g = window_list; g; g = g->next) if (g->window == window) return g; - return 0; + return NULL; } diff --git a/riscos/window.h b/riscos/window.h index a55ce1b9f..c4daf8bb8 100644 --- a/riscos/window.h +++ b/riscos/window.h @@ -33,6 +33,12 @@ void ro_gui_window_initialise(void); bool ro_gui_window_check_menu(wimp_menu *menu); +/** + * Set the contents of a window's address bar. + * + * \param g gui_window to update + * \param url new url for address bar + */ void gui_window_set_url(struct gui_window *g, const char *url); #endif diff --git a/utils/file.h b/utils/file.h index 7baf2f019..dbbab300e 100644 --- a/utils/file.h +++ b/utils/file.h @@ -86,7 +86,7 @@ struct gui_file_table { /** * Create a path from a nsurl. * - * @parm[in] url The url to encode. + * @param[in] url The url to encode. * @param[out] path A string containing the result path which * must be freed by the caller. * @return NSERROR_OK and the path is written to \a path diff --git a/windows/findfile.c b/windows/findfile.c index 51ce74829..aed43b0bf 100644 --- a/windows/findfile.c +++ b/windows/findfile.c @@ -93,7 +93,7 @@ static char *realpath(const char *path, char *resolved_path) * * Search order is: ~/.netsurf/, $NETSURFRES/ (where NETSURFRES is an * environment variable), then the path specified in - NETSURF_WINDOWS_RESPATH in the Makefile then .\res\ [windows paths] + * NETSURF_WINDOWS_RESPATH in the Makefile then .\res\ [windows paths] */ char *nsws_find_resource(char *buf, const char *filename, const char *def) |