%s%s
\n", _(strUriColonSpace), html_uri, html_uri); htmlify_cleanup(uri, html_uri); wk_info_collect(iw, spfbuf); my_spf_cleanup(strbuf, spfbuf); } html_title = ( (cantent != NULL) ? cantent->major_html_title : NULL ); if (html_title == NULL) html_title = document->minor_html_title; if ( (html_title != NULL) && (*html_title != '\0') ) { const char* htitle = htmlify(html_title); my_spf(strbuf, STRBUF_SIZE, &spfbuf, "%s\"%s\"
\n", _("Title: "), htitle); htmlify_cleanup(html_title, htitle); wk_info_collect(iw, spfbuf); my_spf_cleanup(strbuf, spfbuf); } if (resource != NULL) { const size_t size = resource->bytecount; my_spf(strbuf, STRBUF_SIZE, &spfbuf, "%s%d %s
\n", _("Size: "), localized_size(size), bytebytes(size)); wk_info_collect(iw, spfbuf); my_spf_cleanup(strbuf, spfbuf); } if ( (cantent == NULL) || ( (document->bddm != bddmHtml) && (cantent->kind != rckHtml) ) ) goto not_html; /* Currently we must run the whole document once through the renderer to get the handling of "inside tag" correctly in the permanently stored
tree of HTML nodes. Rubbish... IMPROVEME! */
#if 0
{ const tLinenumber l = document->origin_y;
const tActiveElementNumber a = document->aecur;
document_display(document, wrtToEnd);
if (document->origin_y != l) /* ("likely") */
{ document->origin_y = l; document->aecur = a;
document_display(document, wrtRedraw);
}
}
#else
document_display(document, wrtToEnd);
#endif
parser_html_start(cantent); my_memclr_arr(ibuf);
_ae = __ae = INVALID_AE; _hfn = __hfn = INVALID_HTML_FORM_NUMBER;
while ( (node = parser_html_next(falsE)) != NULL )
{ const tHtmlTagKind htk = node->kind;
const tHtmlNodeFlags hnf = node->flags;
const tBoolean has_aebase = cond2boolean(hnf & hnfHasAeBase);
const tActiveElementBase* aeb;
const tAttribute* attr;
const char *str, *hstr;
if (has_aebase) { __ae++; _ae = __ae; }
else _ae = INVALID_AE;
if (hnf & hnfGoodForm) { __hfn++; _hfn = __hfn; }
else _hfn = INVALID_HTML_FORM_NUMBER;
if (htk == htkText) goto do_next;
idx = iiInvalid;
/* CHECKME: avoid duplicates in the lists of links and images? */
switch (htk)
{ case htkA:
if (_ae == INVALID_AE) goto do_next;
aeb = &(cantent->aebase[_ae]);
if ( ( (str = aeb->data) != NULL ) && (*str != '\0') )
{ tUriData* uri_data;
idx = iiLink;
use_linkstr:
uri_data = uri_parse(str, req_ud, NULL, NULL, 2);
/* CHECKME: use the "proper" referrer! */
str = uri_data->uri; hstr = htmlify(str);
my_spf(NULL, 0, &spfbuf, "%s%s%s", strIpre, hstr,
hstr, strIpost);
htmlify_cleanup(str, hstr); uri_put(uri_data);
}
break;
case htkImg:
attr = find_attribute(node, anSrc);
if ( (attr != NULL) && ( (str = attr->value) != NULL ) && (*str!='\0'))
{ idx = iiImage; goto use_linkstr; }
break;
case htkForm:
if (_hfn != INVALID_HTML_FORM_NUMBER)
{ const tHtmlForm* f = &(cantent->form[_hfn]);
const char* au = f->action_uri;
if ( (au != NULL) && (*au != '\0') )
{ const tHtmlFormFlags hff = f->flags;
my_spf(NULL, 0, &spfbuf, "%s\"%s\"%s%s%s", strIpre, au,
( (hff & hffMethodPost) ? " - POST" : strEmpty ),
( (hff & hffEncodingMultipart) ? " - multipart" : strEmpty ),
strIpost);
idx = iiForm;
}
}
break;
case htkFrame:
if (_ae == INVALID_AE) goto do_next;
aeb = &(cantent->aebase[_ae]);
if ( ( (str = aeb->data) != NULL ) && (*str != '\0') )
{ idx = iiFrame; goto use_linkstr; }
break;
}
if (idx >= 0)
{ tIbuf* ib = __memory_allocate(sizeof(tIbuf), mapOther);
ib->next = NULL; ib->str = my_spf_use(spfbuf);
if (ibuf[idx].tail != NULL) ibuf[idx].tail->next = ib;
ibuf[idx].tail = ib;
if (ibuf[idx].head == NULL) ibuf[idx].head = ib;
}
do_next:
if (!(hnf & hnfStoredInTree)) deallocate_html_node(node);
}
parser_html_finish();
for (idx = 0; idx <= iiMax; idx++)
{ tIbuf* ib = ibuf[idx].head;
if (ib == NULL) goto do_next_idx; /* no entries exist for this one */
sprint_safe(strbuf, "%s
\n%s", _(strIheader[idx]), strMasterPre);
wk_info_collect(iw, strbuf);
while (ib != NULL)
{ tIbuf* next = ib->next;
const char* str = ib->str;
wk_info_collect(iw, str);
memory_deallocate(str); memory_deallocate(ib); ib = next;
}
wk_info_collect(iw, strMasterPost);
do_next_idx: {}
}
not_html: {}
wk_info_finalize(iw);
}
#endif /* #if DO_WK_INFO */
/** Browser window document operations interface */
static tBoolean wk_browser_dop_find_coords(const tBrowserDocument* document,
/*@out@*/ short* _x1, /*@out@*/ short* _y1, /*@out@*/ short* _x2,
/*@out@*/ short* _y2)
{ const tWindowView* view = (const tWindowView*) (document->container);
const tWindow* window = view->window;
short minrow, maxrow;
const tBoolean retval = window_contents_minmaxrow(window, &minrow, &maxrow);
if (retval) { *_x1 = 0; *_y1 = minrow; *_x2 = COLS - 1; *_y2 = maxrow; }
return(retval);
}
static void wk_browser_dop_display_meta1(tBrowserDocument* document)
{ wk_browser_redraw_message(document);
}
static void wk_browser_dop_display_meta2(tBrowserDocument* document)
{ short minrow, maxrow;
if (document_minmaxrow(document, &minrow, &maxrow))
wk_browser_redraw_title(document, maxrow + 1);
}
static const tBrowserDocumentOps wk_browser_document_ops =
{ wk_browser_dop_find_coords, wk_browser_dop_display_meta1,
wk_browser_dop_display_meta2
};
/** Browser window view handling */
static void deallocate_windowviewlist(const tWindowView* view)
/* deallocates the given list of views and drops associated request and
resource data */
{ while (view != NULL)
{ const tWindowView* next = view->next;
document_tear(&(view->bd)); memory_deallocate(view); view = next;
}
}
static void cut_windowviewlist(tWindow* window)
/* "cuts" the current view and all its successors out of the and
deallocates them */
{ tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
tWindowView* view = wksd->current_view;
if (view != NULL)
{ if (view->prev != NULL) view->prev->next = NULL;
wksd->current_view = view->prev;
if (wksd->first_view == view) wksd->first_view = NULL;
deallocate_windowviewlist(view);
}
}
static /* __sallocator -- not an "only" reference... */ tWindowView*
__callocator wk_browser_append_view(tWindow* window)
/* prepares a new view in the given browser window and removes any old "tail"
of views in that window */
{ tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
tWindowView *current_view = wksd->current_view,
*new_view = memory_allocate(sizeof(tWindowView), mapWindowView);
new_view->window = window;
if (current_view != NULL) /* wasn't a new (empty) window */
{ const tWindowView* tail = current_view->next;
if (tail != NULL) deallocate_windowviewlist(tail); /* remove old tail */
current_view->next = new_view; new_view->prev = current_view;
}
wksd->current_view = new_view;
if (wksd->first_view == NULL) wksd->first_view = new_view;
return(new_view);
}
static void wk_browser_request_callback(void* _document,
tDhmNotificationFlags flags)
{ tBrowserDocument* document = (tBrowserDocument*) _document;
tResourceRequest* request = document->request;
tResource* resource = request->resource;
tWindowView* view = (tWindowView*) (document->container);
tWindow* window = view->window;
#if CONFIG_DEBUG
sprint_safe(debugstrbuf, "wk_browser_request_callback(): document=%p, request=%p, resource=%p, dhmnf=%d\n", document, request, resource, flags);
debugmsg(debugstrbuf);
#endif
if (resource != NULL) request_copy_error(request, resource);
if (flags & (dhmnfDataChange | dhmnfMetadataChange))
{ tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
#if MIGHT_USE_SCROLL_BARS
document->sbvi = 0;
#endif
if ( (window_is_visible(window)) && (wksd->current_view == view) )
{ if (request->flags & rrfResourceChanged) /* REMOVEME?! */
request->flags &= ~rrfResourceChanged;
else if (document->flags & wvfScreenFull)
document->flags |= wvfDontDrawContents;
document_display(document, wrtRedraw);
}
}
else if (flags & dhmnfAttachery) /* a resource was attached to the request */
{ dhm_notification_setup(resource, wk_browser_request_callback,
document, dhmnfDataChange | dhmnfMetadataChange, dhmnSet);
cantent_attach(document->cantent, resource->cantent);
}
test_redirection(window, document);
}
static void wk_browser_prr(tWindow* window, const char* uri, tPrrFlags prrf,
const tBrowserDocument* referrer)
/* prepares a resource request in a browser window */
{ tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
tWindowView *current_view = wksd->current_view, *new_view;
tPrrData prr_data;
tResourceRequest* request;
tBrowserDocument* document;
const char* anchor;
unsigned char redirections = 0;
prr_setup(&prr_data, uri, prrf | prrfWantUriAnchor);
prr_data.referrer = referrer; prepare_resource_request(&prr_data);
request = prr_data.result; prr_data.result = NULL;
anchor = prr_data.uri_anchor; prr_data.uri_anchor = NULL;
if ( (prrf & prrfIsRedirection) && (referrer != NULL) )
{ const unsigned char count = redirections = referrer->redirections + 1;
if (count > config.redirections)
{ redirection_error: request_set_error(request, reRedirection);
goto redirection_checked;
}
if ( (prrf & prrfIsHttpRedirection) && (referrer != NULL) )
{ const tResource* res = referrer->request->resource;
if ( (res != NULL) && (res->flags & rfPost) )
goto redirection_error; /* RFC2616, 9.3 */
}
}
redirection_checked: {}
new_view = wk_browser_append_view(window);
document = &(new_view->bd);
document_init(document, &wk_browser_document_ops, new_view, request);
document->anchor = anchor; document->redirections = redirections;
document->title = my_strdup(request->uri_data->uri);
if (prrf & prrfPost) document->flags |= wvfPost;
if (prrf & prrfSource)
{ document->bddm = bddmSource;
if (current_view != NULL)
{ const char* html_title = current_view->bd.minor_html_title;
if (html_title != NULL)
document->minor_html_title = my_strdup(html_title);
}
}
else if (prrf & prrfHtml) document->bddm = bddmHtml;
if (prrf & prrfRedrawAll) window_redraw_all();
else if (prrf & prrfRedrawOne) window_redraw(window);
if (request->state != rrsError)
{ tResourceRequestAction action;
if (prrf & prrfEnforcedReload) action = rraEnforcedReload;
else if (prrf & prrfReload) action = rraReload;
else
{ action = rraLoad;
#if CONFIG_MENUS & MENUS_UHIST
if (is_environed)
{ my_strdedup(uri_history[uri_history_index], request->uri_data->uri);
if (uri_history_index < URI_HISTORY_LEN - 1) uri_history_index++;
else uri_history_index = 0;
/* IMPLEMENTME: if the URI already is in the list, just "move it" to
the top of the list! */
}
#endif
}
dhm_notification_setup(request, wk_browser_request_callback, document,
dhmnfDataChange | dhmnfMetadataChange | dhmnfAttachery, dhmnSet);
request_queue(request, action);
}
prr_setdown(&prr_data);
}
#if TGC_IS_GRAPHICS
static one_caller void wk_browser_build_graphics(tWindow* window)
{ tGraphicsWindow* w = (GtkWindow*) gtk_window_new(GTK_WINDOW_TOPLEVEL);
tGraphicsWidget *base=gtk_vbox_new(FALSE,0), *fluff=gtk_vbox_new(FALSE,0),
*buttons = gtk_hbox_new(FALSE, 0), *texts = gtk_vbox_new(FALSE, 0),
*contents = gtk_drawing_area_new(), *url0 = gtk_hbox_new(FALSE, 0),
*url1 = gtk_label_new(_("Location: ")), *url2 = gtk_label_new(strEmpty),
*info0 = gtk_hbox_new(FALSE, 0), *info1 = gtk_label_new(strEmpty),
*info2 = gtk_label_new(strEmpty), *mbar = gtk_menu_bar_new(),
*mFile = create_menu(mbar, _(strFileUc)), *mView = create_menu(mbar,
_("View")), *mBookmark = create_menu(mbar, _("Bookmark")),
*mWindow = create_menu(mbar, _("Window"));
tGraphicsLowlevelWindow *some_parent, *drawable;
GdkWindowAttr* drawattrs = memory_allocate(sizeof(GdkWindowAttr), mapGtk);
GtkStyle* style;
tGraphicsContext* gc;
static tBoolean is_first_call = truE;
static char *strHome, *strStop;
static GdkPixmap* logo_mini_pixmap;
static GdkBitmap* logo_mini_mask;
GtkAccelGroup* accel = gtk_accel_group_new();
if (is_first_call)
{ tGraphicsLowlevelWindow* template_window;
GdkWindowAttr* attr = memory_allocate(sizeof(GdkWindowAttr), mapGtk);
is_first_call = falsE;
strHome = i18n_strdup(_("Home")); strStop = i18n_strdup(_("Stop"));
attr->window_type = GDK_WINDOW_CHILD;
template_window = gdk_window_new(NULL, attr, 0);
logo_mini_pixmap = gdk_pixmap_create_from_xpm_d(template_window,
&logo_mini_mask, NULL, (gchar**) retawq_logo_mini);
}
gtk_window_set_policy(w, TRUE /* CHECKME: documentation contradicts it! */,
TRUE, FALSE);
gtk_window_set_title(GTK_WINDOW(w), strProgramVersion);
gtk_window_add_accel_group(GTK_WINDOW(w), accel);
gtk_drawing_area_size(GTK_DRAWING_AREA(contents), config.width,
config.height);
gtk_widget_set_events(contents, GDK_EXPOSURE_MASK);
/* basic window structure */
gtk_container_add(GTK_CONTAINER(w), base);
pack_box(base, mbar); pack_box(base, fluff); pack_box(base, contents);
pack_box(fluff, buttons); pack_box(fluff, texts);
pack_box(texts, url0); pack_box(texts, info0);
pack_box(url0, url1); pack_box(url0, url2);
pack_box(info0, info1); pack_box(info0, info2);
/* menus */
create_item(mFile, _("New Window"), pccWindowNew, 'n');
create_item(mFile, _(strOpenInNewWindow), pccWindowNewFromDocument, 'N');
create_item(mFile, _("Open Local File..."), pccLocalFileDirOpen, 'O');
create_item(mFile, _("Open URL..."), pccGoUri, 'o');
create_item(mFile, _("Open Relative URL..."), pccGoUriPreset, '\0');
create_item(mFile, _(strSaveAs), pccDocumentSave, 's');
create_item(mFile, _(strUcClose), pccWindowClose, 'c');
create_item(mFile, _(strUcQuit), pccQuit, 'q');
create_item(mView, _(strBack), pccViewBack, '\0');
create_item(mView, _(strForward), pccViewForward, '\0');
create_item(mView, _(strReload), pccDocumentReload, 'R');
if (config.home_uri != NULL) create_item(mView, strHome,pccGoHome, 'h');
if (config.search_engine != NULL)
create_item(mView, _(strSearch), pccGoSearch, 'e');
create_item(mView, strStop, pccStop, '.');
create_item(mView, _("Document Info"), pccUnknown, 'I');
create_item(mView, _(strSourceCode), pccDocumentEnforceSource, '\\');
create_item(mBookmark, _(strAddBookmark), pccUnknown, '\0');
create_item(mWindow, "(Titles of all windows)", pccUnknown, '\0');
/* buttons */
create_button(retval, buttons, _(strBack), pccViewBack);
create_button(retval, buttons, _(strForward), pccViewForward);
create_button(retval, buttons, _(strReload), pccDocumentReload);
if (config.home_uri != NULL)
create_button(retval, buttons, strHome, pccGoHome);
if (config.search_engine != NULL)
create_button(retval, buttons, _(strSearch), pccGoSearch);
create_button(retval, buttons, strStop, pccStop);
/* show all */
show_widget(url0); show_widget(url1); show_widget(url2);
show_widget(info0); show_widget(info1); show_widget(info2);
show_widget(mbar); show_widget(buttons); show_widget(texts);
show_widget(fluff); show_widget(contents); show_widget(base);
show_widget(w);
/* GDK window and gc for contents */
drawattrs->event_mask = gtk_widget_get_events(contents) | GDK_EXPOSURE_MASK
| GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK;
drawattrs->x = contents->allocation.x;
drawattrs->y = contents->allocation.y;
drawattrs->width = contents->allocation.width;
drawattrs->height = contents->allocation.height;
drawattrs->wclass = GDK_INPUT_OUTPUT;
drawattrs->visual = gtk_widget_get_visual(contents);
drawattrs->colormap = gtk_widget_get_colormap(contents);
drawattrs->window_type = GDK_WINDOW_CHILD;
some_parent = gtk_widget_get_parent_window(contents);
drawable = gdk_window_new(some_parent, drawattrs,
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
gdk_window_set_icon(some_parent, NULL, logo_mini_pixmap, logo_mini_mask);
style = gtk_widget_get_style(contents);
gc = gdk_gc_new(drawable);
gdk_window_set_background(drawable, &(style->white));
gdk_gc_set_foreground(gc, &(style->black));
gdk_gc_set_background(gc, &(style->white));
gdk_window_show(drawable);
/* store */
retval->ww = w;
retval->contents = contents; retval->location = url2;
retval->info = info1; retval->message = info2;
retval->drawable = drawable; retval->gc = gc;
/* connect signal handlers */
connect_window(w, strGtkDestroy, window_handle_destroy, retval);
connect_window(w, strGtkDelete, window_handle_delete, retval);
connect_widget(contents, strGtkConfigure, window_handle_configure, retval);
connect_widget(contents, strGtkKey, graphics_propagate_event, NULL);
connect_widget(contents, strGtkButton, graphics_cm, retval);
}
#endif
/** Browser window operations interface */
static void wop_browser_create(tWindow* window)
{ window->wksd = memory_allocate(sizeof(tWkBrowserData), mapWksd);
#if TGC_IS_GRAPHICS
#endif
}
static void wop_browser_remove(tWindow* window)
{ const tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
const tWindowView* view = wksd->first_view;
if (view != NULL) deallocate_windowviewlist(view);
#if TGC_IS_GRAPHICS
#endif
memory_deallocate(wksd);
}
static void wop_browser_redraw(const tWindow* window)
{ const tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
tWindowView* view = wksd->current_view;
tBrowserDocument* document = ( (view != NULL) ? (&(view->bd)) : NULL );
short i, minrow, maxrow;
#if CONFIG_DEBUG
sprint_safe(debugstrbuf, "wop_browser_redraw(): window=%p, view=%p, document=%p\n", window, view, document);
debugmsg(debugstrbuf);
#endif
if (document != NULL) document_display(document, wrtRedraw);
else if (window_contents_minmaxrow(window, &minrow, &maxrow))
{ for (i = minrow; i <= maxrow; i++) { (void) move(i,0); (void) clrtoeol(); }
cu_display_title(window, _(strBracedNewWindow), maxrow + 1);
if (window == current_window_x) show_message(strEmpty, falsE);
}
must_reset_cursor();
}
static tBoolean wop_browser_is_precious(const tWindow* window)
{ const tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
return(cond2boolean(wksd->first_view != NULL));
}
static tBoolean wop_browser_handle_pcc(tWindow* window,tProgramCommandCode pcc)
{ tBoolean retval = truE;
tWkBrowserData* wksd;
tWindowView* view;
switch (pcc)
{case pccViewBack:
wksd = (tWkBrowserData*) (window->wksd); view = wksd->current_view;
if ( (view != NULL) && (view->prev != NULL) )
{ wksd->current_view = view->prev; window_redraw(window); }
break;
case pccViewForward:
wksd = (tWkBrowserData*) (window->wksd); view = wksd->current_view;
if ( (view != NULL) && (view->next != NULL) )
{ wksd->current_view = view->next; window_redraw(window); }
break;
case pccDocumentReload: case pccDocumentReloadEnforced:
{ tBrowserDocument* document;
tBoolean is_post;
wksd = (tWkBrowserData*) (window->wksd); view = wksd->current_view;
if (view == NULL) goto out;
document = &(view->bd); is_post = cond2boolean(document->flags &wvfPost);
lid.prrf = ( (pcc == pccDocumentReloadEnforced) ? prrfEnforcedReload :
prrfReload );
if (is_post) lid.prrf |= prrfPost;
if ( (!is_post) || (config.flags & cfDontConfirmRepost) )
wk_browser_reload(window);
else ask_yesno(_("Really repost form data?"), cgRepost, NULL);
}
break;
case pccDocumentEnforceSource:
{ const tBrowserDocument* document = window_currdoc(window);
if ( (document != NULL) && (document->bddm != bddmSource) )
{ wk_browser_prr(require_browser_window(), document->title,
prrfRedrawOne | prrfSource, NULL);
}
}
break;
case pccDocumentInfo:
#if DO_WK_INFO
wksd = (tWkBrowserData*) (window->wksd); view = wksd->current_view;
if (view != NULL) wk_browser_build_document_info(&(view->bd));
#else
fwdact(_("Finformation window"));
#endif
break;
default: retval = falsE; break; /* not handled here, try generic handler */
}
out:
return(retval);
}
static tBrowserDocument* wop_browser_find_currdoc(const tWindow* window)
{ const tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
tWindowView* view = wksd->current_view;
return( (view != NULL) ? (&(view->bd)) : NULL );
}
static const char* wop_browser_get_info(tWindow* window,
/*@out@*/ tBoolean* _is_error)
{ const tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
const tWindowView* view = wksd->current_view;
const char* retval = ( (view != NULL) ? (view->bd.last_info) : NULL );
*_is_error = ( (retval != NULL) ? cond2boolean(*retval++ & 1) : falsE );
return(retval);
}
static const char* wop_browser_get_menu_entry(tWindow* window)
{ const tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
const tWindowView* view = wksd->current_view;
const tBrowserDocument* document;
const tCantent* cantent;
const char* text;
if (view == NULL) { text = _(strBracedNewWindow); goto out; }
document = &(view->bd); cantent = document->cantent;
if ( (cantent != NULL) && ( (text = cantent->major_html_title) != NULL ) )
goto out;
if ( (text = document->minor_html_title) != NULL ) goto out;
if ( (text = document->title) != NULL ) goto out;
text = unconstify_or_(strUnknown); /* "should not happen" */
out:
return(text);
}
#if CONFIG_MENUS & MENUS_CONTEXT
static void wop_browser_setup_cm(tWindow* window, short* _x, short* _y,
tActiveElementNumber _ae)
{ const tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
const tWindowView* view = wksd->current_view;
if (view != NULL)
{ const tBrowserDocument* document = &(view->bd);
const tResourceRequest* request = document->request;
const char* uri = ( (request != NULL) ? request->uri_data->uri : NULL );
short x, y;
/* ae-specific entries */
if (_ae != INVALID_AE)
{ const tCantent* cantent = document->cantent;
const tActiveElementBase* aeb = cantent->aebase;
tActiveElementKind aek = ( (aeb != NULL) ? aeb[_ae].kind : aekUnknown );
const tActiveElementCoordinates* aec = find_visible_aec(document, _ae);
if ( (aec != NULL) && (document_line2row(document, aec->y, &y)) )
{ x = aec->x1; y++; *_x = x; *_y = y; }
cm_add(strShowElementInfo, cm_handle_command_code, pccElementInfo);
if ( (aeb != NULL) && (aeb[_ae].flags & aefDisabled) )
cm_add(strEnableThisElement, cm_handle_command_code, pccElementEnable);
if (aek == aekLink)
{ cm_add(strOpenLinkInNewWindow, cm_handle_command_code,
pccWindowNewFromElement);
#if CONFIG_EXTRA & EXTRA_DOWNLOAD
cm_add(strSaveLinkAs, cm_handle_command_code, pccDownloadFromElement);
#endif
}
else if (is_form_aek(aek))
{ tHtmlFormNumber hfn = calc_hfn(cantent, _ae);
if (hfn != INVALID_HTML_FORM_NUMBER)
{ cm_add(strSubmitThisForm, cm_handle_command_code, pccFormSubmit);
/* IMPLEMENTME: "Show Form Info" */
}
}
cm_add_separator();
}
/* general entries */
if (view->prev != NULL)
cm_add(strBack, cm_handle_command_code, pccViewBack);
if (view->next != NULL)
cm_add(strForward, cm_handle_command_code, pccViewForward);
if ( (uri != NULL) && (*uri != '\0') )
{ cm_add(strReload, cm_handle_command_code, pccDocumentReload);
cm_add(strEnforcedReload, cm_handle_command_code,
pccDocumentReloadEnforced);
cm_add(strSaveAs, cm_handle_command_code, pccDocumentSave);
cm_add(strOpenInNewWindow, cm_handle_command_code,
pccWindowNewFromDocument);
#if 0
cm_add(strAddBookmark, cm_handle_command_code, pccBookmarkAdd);
#endif
}
cm_add(strSourceCode, cm_handle_command_code, pccDocumentEnforceSource);
cm_add_separator();
}
}
#endif /* #if CONFIG_MENUS & MENUS_CONTEXT */
#if CONFIG_SESSIONS
static void wop_browser_save_session(tWindow* window, int fd)
{ tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
tWindowView *view = wksd->first_view, *currview = wksd->current_view;
tBoolean is_fuiw = truE; /* first URI in window? */
while (view != NULL)
{ const tBrowserDocument* document = &(view->bd);
const tResourceRequest* request;
const tWindowViewFlags wvf = document->flags;
tBrowserDocumentDisplayMode bddm;
const char *uri, *html_title, *flagsptr, *linenumptr;
char* spfbuf;
tLinenumber linenum;
tBoolean is_currview;
if (wvf & wvfPost) goto nextview; /* can't handle this correctly */
is_currview = cond2boolean(view == currview); request = document->request;
if (request != NULL)
{ const tResource* resource = request->resource;
if ( (resource != NULL) && ( (uri = resource->uri_data->uri) != NULL ) &&
(*uri != '\0') )
{ goto write_uri; }
if ( ( (uri = request->uri_data->uri) != NULL ) && (*uri != '\0') )
goto write_uri;
}
if ( ( (uri = document->title) != NULL ) && (*uri != '\0') )
goto write_uri;
goto nextview; /* no usable URI found */
write_uri:
if (is_fuiw)
{ char* temp = winbuf + 2;
#if TGC_IS_CURSES
unsigned char num;
for (num = 0; num < 2; num++)
{ if (window == visible_window_x[num])
{ psm(temp, 'v'); temp = bdp(temp); *temp++ = '0' + num; break; }
}
#endif
*temp++ = '\n'; *temp = '\0'; my_write_str(fd, winbuf); is_fuiw = falsE;
}
bddm = document->bddm;
if ( (bddm != bddmAutodetect) || (is_currview) )
{ char* temp = bdp(flagsbuf);
if (bddm == bddmSource) *temp++ = 's';
else if (bddm == bddmHtml) *temp++ = 'h';
if (is_currview) *temp++ = 'c';
*temp = '\0';
flagsptr = flagsbuf;
}
else flagsptr = strEmpty;
linenum = document->origin_y;
if (linenum <= 0) linenumptr = strEmpty;
else
{ sprint_safe(bdp(linenumbuf), strPercd, linenum); linenumptr = linenumbuf;
}
html_title = ( (bddm == bddmSource) ? document->minor_html_title : NULL );
if ( (html_title != NULL) && (*html_title == '\0') ) html_title = NULL;
my_spf(strbuf, STRBUF_SIZE, &spfbuf, "U:%s%s%s%s%s%s\n", flagsptr,
linenumptr, urimarker, uri, ( (html_title != NULL) ? htmltitlemarker :
strEmpty ), null2empty(html_title));
my_write_str(fd, spfbuf); my_spf_cleanup(strbuf, spfbuf);
nextview: view = view->next;
}
}
#endif /* #if CONFIG_SESSIONS */
#if CONFIG_DO_TEXTMODEMOUSE
static void wop_browser_handle_mouse(tWindow* window __cunused, tCoordinate x
__cunused, tCoordinate y __cunused, int flags __cunused)
{ /* IMPLEMENTME! */
}
#endif
static const tWindowSpec wk_browser_spec =
{ wop_browser_create, wop_browser_remove, wop_browser_redraw,
wop_browser_is_precious, NULL, wop_browser_handle_pcc,
wop_browser_find_currdoc, wop_browser_get_info, wop_browser_get_menu_entry,
WSPEC_CM(wop_browser_setup_cm) WSPEC_SESSION(wop_browser_save_session)
WSPEC_MOUSE(wop_browser_handle_mouse) 'B', 'B', wkBrowser, wsfNone
};
/** Browser window stuff */
static void wk_browser_reload(tWindow* window)
{ const tWkBrowserData* wksd = (tWkBrowserData*) (window->wksd);
const tWindowView* view = wksd->current_view;
const tBrowserDocument* document;
const char* uri;
tBoolean do_post;
tPrrFlags prrf;
if (view == NULL) return; /* "should not happen" */
document = &(view->bd); uri = my_strdup(document->title);
prrf = lid.prrf | prrfRedrawOne; do_post = cond2boolean(prrf & prrfPost);
if (do_post)
{ const char* post = document->request->uri_data->post;
sfbuf = my_strdup(null2empty(post));
sfbuf_size = sfbuf_maxsize = strlen(sfbuf) + 1;
prrf |= prrfUseSfbuf;
}
cut_windowviewlist(window);
wk_browser_prr(window, uri, prrf, NULL); memory_deallocate(uri);
}
static tWindow* wk_browser_create(void)
{ return(window_create(&wk_browser_spec)); /* just a frequently used wrapper */
}
/*** Window kind: information window */
#if DO_WK_INFO
typedef struct
{ tBrowserDocument document; /* exactly one document per window */
const char *window_title, *message;
tBoolean is_finalized, message_is_error;
} tWkInfoData; /* for window->wksd */
/** Information window document operations interface */
static tBoolean wk_info_dop_find_coords(const tBrowserDocument* document,
/*@out@*/ short* _x1, /*@out@*/ short* _y1, /*@out@*/ short* _x2,
/*@out@*/ short* _y2)
{ const tWindow* window = (const tWindow*) (document->container);
short minrow, maxrow;
const tBoolean retval = window_contents_minmaxrow(window, &minrow, &maxrow);
if (retval) { *_x1 = 0; *_y1 = minrow; *_x2 = COLS - 1; *_y2 = maxrow; }
return(retval);
}
static void wk_info_dop_display_meta1(tBrowserDocument* document)
{
#if TGC_IS_CURSES
const tWindow* window = (const tWindow*) (document->container);
if (window == current_window_x)
#endif
{ const tWkInfoData* wksd = (const tWkInfoData*) (window->wksd);
const char* msg = wksd->message;
show_message(null2empty(msg), wksd->message_is_error);
}
}
static void wk_info_dop_display_meta2(tBrowserDocument* document)
{ short minrow, maxrow;
if (document_minmaxrow(document, &minrow, &maxrow))
{ const tWindow* window = (const tWindow*) (document->container);
const tWkInfoData* wksd = (const tWkInfoData*) (window->wksd);
cu_display_title(window, wksd->window_title, maxrow + 1);
}
}
static const tBrowserDocumentOps wk_info_document_ops =
{ wk_info_dop_find_coords, wk_info_dop_display_meta1, wk_info_dop_display_meta2
};
/** Information window operations interface */
static void wop_info_create(tWindow* window)
{ tWkInfoData* wksd = window->wksd = memory_allocate(sizeof(tWkInfoData),
mapWksd);
tBrowserDocument* document = &(wksd->document);
tCantent* cantent = cantent_create();
document_init(document, &wk_info_document_ops, window, NULL);
cantent_attach(document->cantent, cantent);
}
static void wop_info_remove(tWindow* window)
{ tWkInfoData* wksd = (tWkInfoData*) (window->wksd);
document_tear(&(wksd->document)); __dealloc(wksd->window_title);
memory_deallocate(wksd);
}
static void wop_info_redraw(const tWindow* window)
{ tWkInfoData* wksd = (tWkInfoData*) (window->wksd);
tBrowserDocument* document = &(wksd->document);
#if CONFIG_DEBUG
sprint_safe(debugstrbuf, "wop_info_redraw(): window=%p\n", window);
debugmsg(debugstrbuf);
#endif
document_display(document, wrtRedraw);
}
static tBrowserDocument* wop_info_find_currdoc(const tWindow* window)
{ tWkInfoData* wksd = (tWkInfoData*) (window->wksd);
tBrowserDocument* document = &(wksd->document);
return(document);
}
static const char* wop_info_get_info(tWindow* window,
/*@out@*/ tBoolean* _is_error)
{ const tWkInfoData* wksd = (tWkInfoData*) (window->wksd);
const char* retval = wksd->message; *_is_error = wksd->message_is_error;
return(retval);
}
static const char* wop_info_get_menu_entry(tWindow* window)
{ const tWkInfoData* wksd = (const tWkInfoData*) (window->wksd);
return(wksd->window_title);
}
static const tWindowSpec wk_info_spec =
{ wop_info_create, wop_info_remove, wop_info_redraw, NULL, NULL, NULL,
wop_info_find_currdoc, wop_info_get_info, wop_info_get_menu_entry,
WSPEC_CM(NULL) WSPEC_MOUSE(NULL) WSPEC_SESSION(NULL) 'I', 'I', wkInfo,
wsfNone /* IMPLEMENTME: cm etc.! */
};
/** Information window stuff */
static tWindow* wk_info_create(const char* title,
tBrowserDocumentDisplayMode bddm, /*@out@*/ tBrowserDocument** _document)
{ tWindow* retval = window_create(&wk_info_spec);
tWkInfoData* wksd = (tWkInfoData*) (retval->wksd);
tBrowserDocument* document = &(wksd->document);
wksd->window_title = title; document->bddm = bddm;
if (bddm == bddmHtml) cantent_collect_title(document->cantent, title);
if (_document != NULL) *_document = document;
return(retval);
}
static void wk_info_collect(tWindow* window, const char* str)
{ tWkInfoData* wksd = (tWkInfoData*) (window->wksd);
cantent_collect_str(wksd->document.cantent, str);
if (wksd->is_finalized) window_redraw(window);
}
static void wk_info_finalize(tWindow* window)
/* The ("initial amount" of) information which should be displayed in this
window has been collected, now it is displayed for the first time. */
{ tWkInfoData* wksd = (tWkInfoData*) (window->wksd);
wksd->is_finalized = truE; window_redraw_all();
}
static void wk_info_set_message(tWindow* window, const char* msg,
tBoolean is_error)
{ tWkInfoData* wksd = (tWkInfoData*) (window->wksd);
wksd->message = msg; wksd->message_is_error = is_error;
}
#endif /* #if DO_WK_INFO */
/*** Window kind: custom connection window */
#if DO_WK_CUSTOM_CONN
#endif /* #if DO_WK_CUSTOM_CONN */
/*** Window kind: built-in text editor */
#if DO_WK_EDITOR
#endif /* #if DO_WK_EDITOR */