diff --git a/atari/browser.c b/atari/browser.c index fd858c045..e107b88cd 100755 --- a/atari/browser.c +++ b/atari/browser.c @@ -87,7 +87,7 @@ struct s_browser * browser_create( struct gui_window * gw, bw->scale = clone->scale; else bw->scale = 1; - + bnew->redraw.areas_used = 0; bnew->compwin = mt_WindCreate( &app, VSLIDE|HSLIDE, 1, 1, app.w, app.h); bnew->compwin->w_u = 1; bnew->compwin->h_u = 1; @@ -181,21 +181,10 @@ bool browser_attach_frame( struct gui_window * container, struct gui_window * fr container->browser->compwin->w_max = 0; container->browser->comp->flex = 0; container->browser->comp->size = 300; - //container->browser->comp->bounds.max_height = 0; - //container->browser->comp->bounds.min_height = 0; - //WindClose( container->browser->compwin ); - container->browser->comp->type = lt; mt_CompAttach( &app, container->browser->comp, frame->browser->comp ); - //win_comp_attach(&app, container->browser->compwin, frame->browser->comp); browser_update_rects( container ); - frame->browser->attached = true; - //container->browser->attached = true; - /*browser_update_rects( frame ); - LGRECT brect; - browser_get_rect( frame, BR_CONTENT, &brect ); - */ - + frame->browser->attached = true; } /* find the root of an frame ( or just return gw if is already the root) */ @@ -806,20 +795,17 @@ bool browser_redraw_required( struct gui_window * gw) } } } - ret = ( (b->redraw.required && frames == 0) || - b->scroll.required || - b->caret.redraw ); + ret = ( ((b->redraw.areas_used > 0) && frames == 0) + || b->scroll.required + || b->caret.redraw ); return( ret ); } /* schedule a redraw of content */ /* coords are relative to the framebuffer */ -/* the box is modified to fit the current viewport if it doesn't fit in */ void browser_schedule_redraw_rect(struct gui_window * gw, short x, short y, short w, short h) { - int diff; - if( x < 0 ){ w += x; x = 0; @@ -832,17 +818,32 @@ void browser_schedule_redraw_rect(struct gui_window * gw, short x, short y, shor browser_schedule_redraw( gw, x, y, x+w, y+h ); } -/* schedule a redraw of content */ -/* coords are relative to the framebuffer */ +static inline bool bbox_intersect(BBOX * box1, BBOX * box2) +{ + if (box2->x1 < box1->x0) + return false; + + if (box2->y1 < box1->y0) + return false; + + if (box2->x0 > box1->x1) + return false; + + if (box2->y0 > box1->y1) + return false; + + return true; +} + +/* + schedule a redraw of content, coords are relative to the framebuffer +*/ void browser_schedule_redraw(struct gui_window * gw, short x0, short y0, short x1, short y1) { assert( gw != NULL ); CMP_BROWSER b = gw->browser; + int i; LGRECT work; - /* TODO: add rectangle to list, instead of summarizing the rect.? */ - /* otherwise it can result in large areas, altough it isnt needed. ( like 1 px in the upper left, - and 1px in bottom right corner ) - */ if( y1 < 0 || x1 < 0 ) return; @@ -853,53 +854,65 @@ void browser_schedule_redraw(struct gui_window * gw, short x0, short y0, short x if( y0 > work.g_h ) return; - /* special handling of initial call: */ - if( b->redraw.required == false ) { - b->redraw.required = true; - b->redraw.area.x0 = x0; - b->redraw.area.y0 = y0; - b->redraw.area.x1 = x1; - b->redraw.area.y1 = y1; - } else { - b->redraw.area.x0 = MIN(b->redraw.area.x0, x0); - b->redraw.area.y0 = MIN(b->redraw.area.y0, y0); - b->redraw.area.x1 = MAX(b->redraw.area.x1, x1); - b->redraw.area.y1 = MAX(b->redraw.area.y1, y1); + for( i=0; iredraw.areas_used; i++) { + if( b->redraw.areas[i].x0 <= x0 + && b->redraw.areas[i].x1 >= x1 + && b->redraw.areas[i].y0 <= y0 + && b->redraw.areas[i].y1 >= y1 ){ + /* the area is already queued for redraw */ + return; + } else { + BBOX area; + area.x0 = x0; + area.y0 = y0; + area.x1 = x1; + area.y1 = y1; + if( bbox_intersect(&b->redraw.areas[i], &area ) ){ + b->redraw.areas[i].x0 = MIN(b->redraw.areas[i].x0, x0); + b->redraw.areas[i].y0 = MIN(b->redraw.areas[i].y0, y0); + b->redraw.areas[i].x1 = MAX(b->redraw.areas[i].x1, x1); + b->redraw.areas[i].y1 = MAX(b->redraw.areas[i].y1, y1); + return; + } + } } + + if( b->redraw.areas_used < MAX_REDRW_SLOTS ) { + b->redraw.areas[b->redraw.areas_used].x0 = x0; + b->redraw.areas[b->redraw.areas_used].x1 = x1; + b->redraw.areas[b->redraw.areas_used].y0 = y0; + b->redraw.areas[b->redraw.areas_used].y1 = y1; + b->redraw.areas_used++; + } else { + /* + we are out of available slots, merge box with last slot + this is dumb... but also a very rare case. + */ + b->redraw.areas[MAX_REDRW_SLOTS-1].x0 = MIN(b->redraw.areas[i].x0, x0); + b->redraw.areas[MAX_REDRW_SLOTS-1].y0 = MIN(b->redraw.areas[i].y0, y0); + b->redraw.areas[MAX_REDRW_SLOTS-1].x1 = MAX(b->redraw.areas[i].x1, x1); + b->redraw.areas[MAX_REDRW_SLOTS-1].y1 = MAX(b->redraw.areas[i].y1, y1); + } +done: + return; } static void browser_redraw_content( struct gui_window * gw, int xoff, int yoff ) { LGRECT work; CMP_BROWSER b = gw->browser; - GRECT area; struct rect clip; LOG(("%s : %d,%d - %d,%d\n", b->bw->name, b->redraw.area.x0, b->redraw.area.y0, b->redraw.area.x1, b->redraw.area.y1 )); - area.g_x = b->redraw.area.x0; - area.g_y = b->redraw.area.y0; - area.g_w = b->redraw.area.x1 - b->redraw.area.x0; - area.g_h = b->redraw.area.y1 - b->redraw.area.y0; current_redraw_browser = b->bw; - clip.x0 = b->redraw.area.x0; - clip.y0 = b->redraw.area.y0; - clip.x1 = b->redraw.area.x1; - clip.y1 = b->redraw.area.y1; - browser_window_redraw( b->bw, -b->scroll.current.x, - -b->scroll.current.y, &clip ); + -b->scroll.current.y, &b->redraw.area ); current_redraw_browser = NULL; - - /* reset redraw area */ - b->redraw.area.x0 = INT_MAX; - b->redraw.area.y0 = INT_MAX; - b->redraw.area.x1 = INT_MIN; - b->redraw.area.y1 = INT_MIN; } @@ -961,41 +974,55 @@ void browser_redraw( struct gui_window * gw ) b->scroll.required = false; } - if (b->redraw.required == true && b->bw->current_content != NULL ) { + if ((b->redraw.areas_used > 0) && b->bw->current_content != NULL ) { if( (plotter->flags & PLOT_FLAG_OFFSCREEN) == 0 ) { + int i; GRECT area; + GRECT fbwork; BBOX cliporg; todo[0] = bwrect.g_x; todo[1] = bwrect.g_y; todo[2] = todo[0] + bwrect.g_w-1; todo[3] = todo[1] + bwrect.g_h-1; vs_clip(plotter->vdi_handle, 1, (short*)&todo[0]); - - area.g_x = b->redraw.area.x0; - area.g_y = b->redraw.area.y0; - area.g_w = b->redraw.area.x1 - b->redraw.area.x0; - area.g_h = b->redraw.area.y1 - b->redraw.area.y0; if( wind_get(gw->root->handle->handle, WF_FIRSTXYWH, &todo[0], &todo[1], &todo[2], &todo[3] )!=0 ) { while (todo[2] && todo[3]) { /* convert screen to framebuffer coords: */ - todo[0] -= bwrect.g_x; - todo[1] -= bwrect.g_y; - if( todo[0] < 0 ){ - todo[2] = todo[2] + todo[0]; - todo[0] = 0; + fbwork.g_x = todo[0] - bwrect.g_x; + fbwork.g_y = todo[1] - bwrect.g_y; + if( fbwork.g_x < 0 ){ + fbwork.g_w = todo[2] + todo[0]; + fbwork.g_x = 0; + } else { + fbwork.g_w = todo[2]; } - if( todo[1] < 0 ){ - todo[3] = todo[3] + todo[1]; - todo[1] = 0; + if( fbwork.g_y < 0 ){ + fbwork.g_h = todo[3] + todo[1]; + fbwork.g_y = 0; + } else { + fbwork.g_h = todo[3]; } - - if (rc_intersect((GRECT *)&area,(GRECT *)&todo)) { - b->redraw.area.x0 = todo[0]; - b->redraw.area.y0 = todo[1]; - b->redraw.area.x1 = b->redraw.area.x0 + todo[2]; - b->redraw.area.y1 = b->redraw.area.y0 + todo[3]; - browser_redraw_content( gw, 0, 0 ); + /* walk the redraw requests: */ + for( i=0; iredraw.areas_used; i++ ){ + area.g_x = b->redraw.areas[i].x0; + area.g_y = b->redraw.areas[i].y0; + area.g_w = b->redraw.areas[i].x1 - b->redraw.areas[i].x0; + area.g_h = b->redraw.areas[i].y1 - b->redraw.areas[i].y0; + if (rc_intersect((GRECT *)&fbwork,(GRECT *)&area)) { + + b->redraw.area.x0 = area.g_x; //todo[0]; + b->redraw.area.y0 = area.g_y; //todo[1]; + b->redraw.area.x1 = area.g_x + area.g_w; //todo[0] + todo[2]; + b->redraw.area.y1 = area.g_y + area.g_h; //todo[1] + todo[3]; + browser_redraw_content( gw, 0, 0 ); + } else { + /* + the area should be kept scheduled for later redraw, but because this + is onscreen plotter, it doesn't make much sense anyway... + */ + } + } if (wind_get(gw->root->handle->handle, WF_NEXTXYWH, &todo[0], &todo[1], &todo[2], &todo[3])==0) { @@ -1007,7 +1034,7 @@ void browser_redraw( struct gui_window * gw ) } else { /* its save to do a complete redraw :) */ } - b->redraw.required = false; + b->redraw.areas_used = 0; } if( b->caret.redraw == true && b->bw->current_content != NULL ) { GRECT area; diff --git a/atari/browser.h b/atari/browser.h index 44d9ac8e1..c5923a125 100755 --- a/atari/browser.h +++ b/atari/browser.h @@ -24,7 +24,19 @@ which cosnist mainly of an WinDom COMPONENT. */ -#define BROWSER_SCROLL_SVAL 64 /* The small scroll inc. value */ +/* + BROWSER_SCROLL_SVAL + The small scroll inc. value (used by scroll-wheel, arrow click): +*/ +#define BROWSER_SCROLL_SVAL 64 + +/* + MAX_REDRW_SLOTS + This is the number of redraw requests that an browser window can queue. + If a redraw is scheduled and all slots are used, the rectangle will + be merged to one of the existing slots. + */ +#define MAX_REDRW_SLOTS 32 enum browser_type { @@ -42,6 +54,56 @@ enum browser_rect BR_VSLIDER = 4 }; + +/* + This struct contains info of current browser viewport scroll + and the scroll which is requested. If a scroll is requested, + the field required is set to true. +*/ +struct s_scroll_info +{ + POINT requested; + POINT current; + bool required; +}; + +/* + This struct holds information of the cursor within the browser + viewport. +*/ +struct s_caret +{ + GRECT requested; + GRECT current; + bool redraw; +}; + +/* + This struct holds scheduled redraw requests. +*/ +struct s_browser_redrw_info +{ + BBOX areas[MAX_REDRW_SLOTS]; + short areas_used; + BBOX area; /* used for clipping of content redraw */ +}; + +/* + This is the actual browser widget, containings GUI elements and + the current state of the browser widget. +*/ +struct s_browser +{ + int type; + COMPONENT * comp; + WINDOW * compwin; + struct browser_window * bw; + struct s_scroll_info scroll; + struct s_browser_redrw_info redraw; + struct s_caret caret; + bool attached; +}; + struct s_browser * browser_create( struct gui_window * gw, struct browser_window * clone, struct browser_window *bw, enum browser_type, int lt, int w, int flex ); bool browser_destroy( struct s_browser * b ); void browser_get_rect( struct gui_window * gw, enum browser_rect type, LGRECT * out); @@ -53,6 +115,18 @@ bool browser_attach_frame( struct gui_window * container, struct gui_window * fr struct gui_window * browser_find_root( struct gui_window * gw ); static void browser_process_scroll( struct gui_window * gw, LGRECT bwrect ); bool browser_redraw_required( struct gui_window * gw); + +/* + This queues an redraw to one of the slots. + The following strategy is used: + 1. It checks if the rectangle to be scheduled is within one of the + already queued bboxes. If yes, it will return. + 2. It checks for an intersection, and it will merge the rectangle to + already queued rectangle where it fits best. + 3. it tries to put the rectangle into one available slot. + 4. if no slot is available, it will search for the nearest rectangle + and summarize it within that slot. +*/ void browser_redraw_caret( struct gui_window * gw, GRECT * area ); static void browser_redraw_content( struct gui_window * gw, int xoff, int yoff ); diff --git a/atari/gui.h b/atari/gui.h index 24a71a1cb..df9d782ee 100755 --- a/atari/gui.h +++ b/atari/gui.h @@ -68,28 +68,6 @@ struct s_gem_cursors { MFORM_EX arrow; } gem_cursors; -/* maybe its better to have an linked - list of redraw areas, so that there - is no such an overhead when 2 (or more) - SMALL rectangles far away from each other - need an redraw! - Currently these rects get summarized into - one big redraw area! -*/ -struct s_browser_redrw_info -{ - BBOX area; /* this is an box which describes the area to redraw */ - /* from netsurfs point of view */ - bool required; -}; - -struct s_scroll_info -{ - POINT requested; - POINT current; - bool required; -}; - enum focus_element_type { WIDGET_NONE=0, URL_WIDGET, @@ -113,101 +91,28 @@ struct s_gui_input_state { } prev_inp_state; */ -#define TB_BUTTON_WIDTH 32 -#define TB_BUTTON_HEIGHT 21 /* includes 1px 3d effect */ -#define TOOLBAR_HEIGHT 25 -#define URLBOX_HEIGHT 21 -#define STATUSBAR_HEIGHT 16 -#define STATUSBAR_MAX_SLEN 255 -#define MOVER_WH 16 -#define THROBBER_WIDTH 32 - - /* defines for data attached to components: */ #define CDT_OBJECT 0x004f424aUL #define CDT_OWNER 0x03UL #define CDT_ICON 0x04UL #define CDT_ICON_TYPE 0x05UL -/* - URL Widget Block size: size of memory block to allocated - when input takes more memory than currently allocated: -*/ -#define URL_WIDGET_BSIZE 64 -#define URL_WIDGET_MAX_MEM 60000 -struct s_url_widget -{ - short selection_len; /* len & direction of selection */ - short caret_pos; /* cursor pos */ - short char_size; /* size of one character (width & hight) */ - short scrollx; /* current scroll position */ - bool redraw; /* widget is only redrawn when this flag is set */ - char * text; /* dynamicall allocated URL string*/ - unsigned short allocated; - unsigned short used; /* memory used by URL (strlen + 1) */ - COMPONENT * comp; -}; - -struct s_throbber_widget -{ - COMPONENT * comp; - short index; - short max_index; - bool running; -}; struct gui_window; - -struct s_tb_button -{ - short rsc_id; - void (*cb_click)(struct gui_window * gw); - COMPONENT * comp; -}; - -struct s_toolbar -{ - COMPONENT * comp; - struct gui_window * owner; - struct s_url_widget url; - struct s_throbber_widget throbber; - GRECT btdim; /* size & location of buttons */ - struct s_tb_button * buttons; - int btcnt; - /* buttons are defined in toolbar.c */ -}; - -struct s_statusbar -{ - COMPONENT * comp; - char text[STATUSBAR_MAX_SLEN+1]; - size_t textlen; - bool attached; -}; - -struct s_caret -{ - GRECT requested; - GRECT current; - bool redraw; -}; - -struct s_browser -{ - int type; - COMPONENT * comp; - WINDOW * compwin; - struct browser_window * bw; - struct s_scroll_info scroll; - struct s_browser_redrw_info redraw; - struct s_caret caret; - bool attached; -}; +struct s_browser; +struct s_statusbar; +struct s_toolbar; typedef struct s_toolbar * CMP_TOOLBAR; typedef struct s_statusbar * CMP_STATUSBAR; typedef struct s_browser * CMP_BROWSER; +/* + This is the "main" window. It can consist of several components + and also holds information shared by several frames within + the window. Each frame, no matter how deep nested, + knows about it's root (GEM window). +*/ struct s_gui_win_root { WINDOW * handle; @@ -222,6 +127,13 @@ struct s_gui_win_root GRECT loc; /* current size of window on screen */ }; +/* + This is the part of the gui which is known by netsurf core. + You must implement it. Altough, you are free how to do it. + Each of the browser "viewports" managed by netsurf are bound + to this structure. gui_window does not mean that it is an + comple window - also frames own an gui_window. +*/ struct gui_window { struct s_gui_win_root * root; CMP_BROWSER browser; @@ -233,5 +145,4 @@ extern struct gui_window *window_list; #define MOUSE_IS_DRAGGING() (mouse_hold_start[0] || mouse_hold_start[1]) - #endif diff --git a/atari/misc.c b/atari/misc.c index fcefee4e5..35f05d760 100755 --- a/atari/misc.c +++ b/atari/misc.c @@ -33,6 +33,7 @@ #include "content/fetch.h" #include "atari/gui.h" #include "atari/toolbar.h" +#include "atari/browser.h" #include "atari/misc.h" extern void * h_gem_rsrc; diff --git a/atari/osspec.c b/atari/osspec.c index a67e6f164..bbceec144 100644 --- a/atari/osspec.c +++ b/atari/osspec.c @@ -116,8 +116,6 @@ char * gemdos_realpath(const char * path, char * rpath) char * work_ptr; size_t l; - printf("gdos rpath in: %s\n", path); - if( rpath == NULL ){ return( NULL ); } @@ -125,6 +123,7 @@ char * gemdos_realpath(const char * path, char * rpath) return( realpath(path, rpath) ); } + LOG(("gdos rpath in: %s\n", path)); memset( rpath, 0, PATH_MAX ); /* first, absolutize relative path: */ @@ -186,7 +185,7 @@ char * gemdos_realpath(const char * path, char * rpath) strcpy( rpath, work_ptr ); } l = strlen( rpath ); - printf("gdos rpath out: %s\n", rpath); + LOG(("gdos rpath out: %s\n", rpath)); return( rpath ); } diff --git a/atari/search.c b/atari/search.c index 37013e92c..668d7c76d 100644 --- a/atari/search.c +++ b/atari/search.c @@ -14,6 +14,7 @@ #include "utils/messages.h" #include "atari/gui.h" #include "atari/misc.h" +#include "atari/browser.h" #include "atari/search.h" #include "atari/res/netsurf.rsh" diff --git a/atari/statusbar.c b/atari/statusbar.c index 85c483b71..7a7582532 100755 --- a/atari/statusbar.c +++ b/atari/statusbar.c @@ -58,7 +58,6 @@ void __CDECL evnt_sb_redraw( COMPONENT *c, long buff[8] ) if( sb == NULL ) return; - assert( sb->attached != false ); if( sb->attached == false ) return; diff --git a/atari/statusbar.h b/atari/statusbar.h index ef6f1f040..6daf62951 100755 --- a/atari/statusbar.h +++ b/atari/statusbar.h @@ -19,6 +19,19 @@ #ifndef NS_ATARI_STATUSBAR #define NS_ATARI_STATUSBAR +#define STATUSBAR_HEIGHT 16 +#define STATUSBAR_MAX_SLEN 255 +#define MOVER_WH 16 + +struct s_statusbar +{ + COMPONENT * comp; + char text[STATUSBAR_MAX_SLEN+1]; + size_t textlen; + bool attached; +}; + + CMP_STATUSBAR sb_create( struct gui_window * gw ); void sb_destroy( CMP_STATUSBAR s ); void sb_set_text( CMP_STATUSBAR sb , char * text ); diff --git a/atari/toolbar.c b/atari/toolbar.c index da8e72176..360d2e66c 100755 --- a/atari/toolbar.c +++ b/atari/toolbar.c @@ -40,6 +40,7 @@ #include "atari/gui.h" #include "atari/toolbar.h" #include "atari/browser_win.h" +#include "atari/browser.h" #include "atari/clipboard.h" #include "atari/misc.h" #include "atari/global_evnt.h" diff --git a/atari/toolbar.h b/atari/toolbar.h index ecf6ebe7b..851609bc4 100755 --- a/atari/toolbar.h +++ b/atari/toolbar.h @@ -19,10 +19,60 @@ #ifndef NS_ATARI_TOOLBAR_H #define NS_ATARI_TOOLBAR_H +#define TB_BUTTON_WIDTH 32 +#define TB_BUTTON_HEIGHT 21 /* includes 1px 3d effect */ +#define TOOLBAR_HEIGHT 25 +#define THROBBER_WIDTH 32 #define THROBBER_MIN_INDEX 1 #define THROBBER_MAX_INDEX 12 #define THROBBER_INACTIVE_INDEX 13 +#define URLBOX_HEIGHT 21 +/* + URL Widget Block size: size of memory block to allocated + when input takes more memory than currently allocated: +*/ +#define URL_WIDGET_BSIZE 64 +#define URL_WIDGET_MAX_MEM 60000 +struct s_tb_button +{ + short rsc_id; + void (*cb_click)(struct gui_window * gw); + COMPONENT * comp; +}; + + +struct s_url_widget +{ + short selection_len; /* len & direction of selection */ + short caret_pos; /* cursor pos */ + short char_size; /* size of one character (width & hight) */ + short scrollx; /* current scroll position */ + bool redraw; /* widget is only redrawn when this flag is set */ + char * text; /* dynamicall allocated URL string */ + unsigned short allocated; + unsigned short used; /* memory used by URL (strlen + 1) */ + COMPONENT * comp; +}; + +struct s_throbber_widget +{ + COMPONENT * comp; + short index; + short max_index; + bool running; +}; + +struct s_toolbar +{ + COMPONENT * comp; + struct gui_window * owner; + struct s_url_widget url; + struct s_throbber_widget throbber; + GRECT btdim; /* size & location of buttons */ + struct s_tb_button * buttons; + int btcnt; +}; CMP_TOOLBAR tb_create( struct gui_window * gw ); void tb_destroy( CMP_TOOLBAR tb );