summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/browser.c800
-rw-r--r--desktop/browser.h148
-rw-r--r--desktop/fetch.c344
-rw-r--r--desktop/fetch.h49
-rw-r--r--desktop/gui.h45
-rw-r--r--desktop/netsurf.c50
-rw-r--r--desktop/netsurf.h35
-rw-r--r--makefile19
-rw-r--r--render/box.c4
-rw-r--r--render/layout.c4
-rw-r--r--riscos/font.c86
-rw-r--r--riscos/font.h39
-rw-r--r--riscos/gui.c1057
-rw-r--r--riscos/gui.h47
-rw-r--r--utils/utils.c10
15 files changed, 2724 insertions, 13 deletions
diff --git a/desktop/browser.c b/desktop/browser.c
new file mode 100644
index 000000000..f21008abb
--- /dev/null
+++ b/desktop/browser.c
@@ -0,0 +1,800 @@
+/**
+ * $Id: browser.c,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#include "netsurf/riscos/font.h"
+#include "netsurf/render/box.h"
+#include "netsurf/render/layout.h"
+#include "netsurf/render/css.h"
+#include "netsurf/desktop/browser.h"
+#include "netsurf/render/utils.h"
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <limits.h>
+
+struct box_selection
+{
+ struct box* box;
+ int actual_x;
+ int actual_y;
+ int plot_index;
+};
+
+void browser_window_text_selection(struct browser_window* bw, int click_x, int click_y, int click_type);
+void browser_window_clear_text_selection(struct browser_window* bw);
+void browser_window_change_text_selection(struct browser_window* bw, struct box_position* new_start, struct box_position* new_end);
+void browser_window_redraw_boxes(struct browser_window* bw, struct box_position* start, struct box_position* end);
+void browser_window_follow_link(struct browser_window* bw,
+ int click_x, int click_y, int click_type);
+
+void box_under_area(struct box* box, int x, int y, int ox, int oy, struct box_selection** found, int* count, int* plot_index);
+
+
+void content_destroy(struct content* c)
+{
+ if (c == NULL)
+ return;
+
+ switch (c->type)
+ {
+ case CONTENT_HTML:
+ /* free other memory here */
+ break;
+ default:
+ break;
+ }
+
+ c->main_fetch = fetch_cancel(c->main_fetch);
+ xfree(c);
+
+ return;
+}
+
+size_t content_html_receive_data(struct content* c, void* data, size_t size, size_t nmemb)
+{
+ size_t amount = nmemb;
+ int offset = 0;
+ size_t numInChunk = 2048 / size; /* process in 2k chunks */
+
+ if (numInChunk > nmemb)
+ numInChunk = nmemb;
+ else if (numInChunk <= (size_t)0)
+ numInChunk = 1;
+
+ while (amount > 0)
+ {
+ htmlParseChunk(c->data.html.parser, (char*)data + (offset * size), numInChunk, 0);
+ offset += numInChunk;
+ amount -= numInChunk;
+ if (amount < numInChunk)
+ numInChunk = amount;
+ gui_multitask();
+ }
+
+ return size * nmemb;
+}
+
+void set_content_html(struct content* c)
+{
+ c->type = CONTENT_HTML;
+ c->data.html.parser = htmlCreatePushParserCtxt(0, 0, "", 0, 0, XML_CHAR_ENCODING_8859_1);
+ c->data.html.document = NULL;
+ c->data.html.markup = NULL;
+ c->data.html.layout = NULL;
+ c->data.html.stylesheet = NULL;
+ c->data.html.style = NULL;
+ return;
+}
+
+void content_html_reformat(struct content* c, int width)
+{
+ char* file;
+ struct css_selector* selector = xcalloc(1, sizeof(struct css_selector));
+
+ Log("content_html_reformat", "Starting stuff");
+ c->data.html.layout = NULL; /* should be a freeing operation here */
+ /* free other things too... */
+
+ Log("content_html_reformat", "Setting document to myDoc");
+ c->data.html.document = c->data.html.parser->myDoc;
+
+ /* skip to start of html */
+ Log("content_html_reformat", "Skipping to html");
+ if (c->data.html.document == NULL)
+ {
+ Log("content_html_reformat", "There is no document!");
+ return;
+ }
+ for (c->data.html.markup = c->data.html.document->children;
+ c->data.html.markup != 0 &&
+ c->data.html.markup->type != XML_ELEMENT_NODE;
+ c->data.html.markup = c->data.html.markup->next)
+ ;
+
+ if (c->data.html.markup == 0)
+ {
+ Log("content_html_reformat", "No markup");
+ return;
+ }
+ if (strcmp((const char *) c->data.html.markup->name, "html"))
+ {
+ Log("content_html_reformat", "Not html");
+ return;
+ }
+
+ Log("content_html_reformat", "Loading CSS");
+ file = load("<NetSurf$Dir>.Resources.CSS"); /*!!! not portable! !!!*/
+ c->data.html.stylesheet = css_new_stylesheet();
+ Log("content_html_reformat", "Parsing stylesheet");
+ css_parse_stylesheet(c->data.html.stylesheet, file);
+
+ Log("content_html_reformat", "Copying base style");
+ c->data.html.style = xcalloc(1, sizeof(struct css_style));
+ memcpy(c->data.html.style, &css_base_style, sizeof(struct css_style));
+
+ Log("content_html_reformat", "Creating box");
+ c->data.html.layout = xcalloc(1, sizeof(struct box));
+ c->data.html.layout->type = BOX_BLOCK;
+ c->data.html.layout->node = c->data.html.markup;
+
+ Log("content_html_reformat", "XML to box");
+ xml_to_box(c->data.html.markup, c->data.html.style, c->data.html.stylesheet, &selector, 0, c->data.html.layout, 0, 0);
+ Log("content_html_reformat", "Layout document");
+ layout_document(c->data.html.layout->children, (unsigned long)width);
+
+ /* can tidy up memory here? */
+
+ return;
+}
+
+void browser_window_reformat(struct browser_window* bw)
+{
+ Log("browser_window_reformat", "Entering...");
+ if (bw == NULL)
+ return;
+ if (bw->current_content == NULL)
+ return;
+
+ switch (bw->current_content->type)
+ {
+ case CONTENT_HTML:
+ Log("browser_window_reformat", "HTML content.");
+ browser_window_set_status(bw, "Formatting page...");
+ content_html_reformat(bw->current_content, bw->format_width);
+ Log("browser_window_reformat", "Content reformatted");
+ if (bw->current_content->data.html.layout != NULL)
+ {
+ Log("browser_window_reformat", "Setting extent");
+ gui_window_set_extent(bw->window, bw->current_content->data.html.layout->children->width, bw->current_content->data.html.layout->children->height);
+ Log("browser_window_reformat", "Setting scroll");
+ gui_window_set_scroll(bw->window, 0, 0);
+ Log("browser_window_reformat", "Redraw window");
+ gui_window_redraw_window(bw->window);
+ Log("browser_window_reformat", "Complete");
+ browser_window_set_status(bw, "Format complete.");
+ }
+ else
+ {
+ Log("browser_window_reformat", "This isn't html");
+ browser_window_set_status(bw, "This is not HTML!");
+ content_destroy(bw->current_content);
+ bw->current_content = NULL;
+ }
+ break;
+ default:
+ Log("browser_window_reformat", "Unknown content type");
+ break;
+ }
+}
+
+/* create a new history item */
+struct history* history_create(char* desc, char* url)
+{
+ struct history* h = xcalloc(1, sizeof(struct history));
+ h->description = xstrdup(desc);
+ h->url = xstrdup(url);
+ return h;
+}
+
+/* remember a new page after the current one. anything remembered after the
+ current page is forgotten. */
+void history_remember(struct history* current, char* desc, char* url)
+{
+ struct history* h;
+ assert(current != NULL);
+
+ /* forget later history items */
+ h = current->later;
+ while (h != NULL)
+ {
+ struct history* hh;
+ hh = h;
+ h = h->later;
+
+ if (hh->description != NULL)
+ xfree(hh->description);
+ if (hh->url != NULL)
+ xfree(hh->url);
+
+ xfree(hh);
+ }
+
+ current->later = history_create(desc, url);
+ return;
+}
+
+
+struct browser_window* create_browser_window(int flags, int width, int height)
+{
+ struct browser_window* bw;
+ bw = (struct browser_window*) xcalloc(1, sizeof(struct browser_window));
+
+ bw->flags = flags;
+ bw->format_width = width;
+ bw->format_height = height;
+
+ bw->scale.mult = 1;
+ bw->scale.div = 1;
+
+ bw->current_content = NULL;
+ bw->future_content = NULL;
+ bw->history = NULL;
+
+ bw->url = NULL;
+ bw->title = xstrdup("NetSurf");
+
+ bw->window = create_gui_browser_window(bw);
+
+ return bw;
+}
+
+void browser_window_set_status(struct browser_window* bw, char* text)
+{
+ if (bw->window != NULL)
+ gui_window_set_status(bw->window, text);
+}
+
+void browser_window_destroy(struct browser_window* bw)
+{
+ if (bw == NULL)
+ return;
+
+ content_destroy(bw->current_content);
+ content_destroy(bw->future_content);
+
+ if (bw->history != NULL)
+ {
+ struct history* current;
+
+ while (current->earlier != NULL)
+ current = current->earlier;
+
+ while (current != NULL)
+ {
+ struct history* hh;
+ hh = current;
+ current = current->later;
+
+ if (hh->description != NULL)
+ xfree(hh->description);
+ if (hh->url != NULL)
+ xfree(hh->url);
+
+ xfree(hh);
+ }
+ }
+
+ xfree(bw->url);
+ xfree(bw->title);
+
+ gui_window_destroy(bw->window);
+
+ xfree(bw);
+
+ return;
+}
+
+void browser_window_open_location(struct browser_window* bw, char* url)
+{
+ struct fetch_request* req;
+
+ if (bw == NULL)
+ return;
+
+ if (bw->future_content != NULL)
+ content_destroy(bw->future_content);
+
+ req = xcalloc(1, sizeof(struct fetch_request));
+ req->type = REQUEST_FROM_BROWSER;
+ req->requestor.browser = bw;
+
+ bw->future_content = (struct content*) xcalloc(1, sizeof(struct content));
+ bw->future_content->main_fetch = create_fetch(url, bw->url, 0, req);
+
+ return;
+}
+
+int browser_window_message(struct browser_window* bw, struct browser_message* msg)
+{
+ gui_safety previous_safety;
+
+ switch (msg->type)
+ {
+ case msg_FETCH_SENDING:
+ browser_window_set_status(bw, "Sending request...");
+ break;
+
+ case msg_FETCH_WAITING:
+ browser_window_set_status(bw, "Waiting for reply...");
+ break;
+
+ case msg_FETCH_FETCH_INFO:
+ browser_window_set_status(bw, "Request received...");
+ if (msg->f == bw->future_content->main_fetch)
+ {
+ switch (msg->data.fetch_info.type)
+ {
+ case type_HTML:
+ set_content_html(bw->future_content);
+ break;
+ default:
+ return 1;
+ }
+ }
+ break;
+
+ case msg_FETCH_DATA:
+ browser_window_set_status(bw, "Data received...");
+ if (msg->f == bw->future_content->main_fetch)
+ content_html_receive_data(bw->future_content, msg->data.fetch_data.block, sizeof(char), msg->data.fetch_data.block_size);
+ break;
+
+ case msg_FETCH_ABORT:
+ browser_window_set_status(bw, "Request failed.");
+ if (msg->f == bw->future_content->main_fetch)
+ {
+ bw->future_content->main_fetch = NULL;
+ content_destroy(bw->future_content);
+ bw->future_content = NULL;
+ }
+ break;
+
+ case msg_FETCH_FINISHED:
+ browser_window_set_status(bw, "Request complete.");
+ if (msg->f == bw->future_content->main_fetch)
+ {
+ struct gui_message gmsg;
+ if (bw->future_content->main_fetch->location != NULL)
+ xfree(bw->url);
+ bw->url = xstrdup(bw->future_content->main_fetch->location);
+
+ gmsg.type = msg_SET_URL;
+ gmsg.data.set_url.url = bw->url;
+ gui_window_message(bw->window, &gmsg);
+
+ htmlParseChunk(bw->future_content->data.html.parser, "", 0, 1);
+ bw->future_content->main_fetch = NULL;
+ previous_safety = gui_window_set_redraw_safety(bw->window, UNSAFE);
+ content_destroy(bw->current_content);
+ bw->current_content = bw->future_content;
+ bw->future_content = NULL;
+ browser_window_reformat(bw);
+ gui_window_set_redraw_safety(bw->window, previous_safety);
+ }
+ break;
+
+ default:
+ browser_window_set_status(bw, "???");
+ break;
+ }
+
+ return 0;
+}
+
+int browser_window_action(struct browser_window* bw, struct browser_action* act)
+{
+ switch (act->type)
+ {
+ case act_MOUSE_AT:
+ browser_window_follow_link(bw, act->data.mouse.x, act->data.mouse.y, 0);
+ break;
+ case act_MOUSE_CLICK:
+ break;
+ case act_CLEAR_SELECTION:
+ browser_window_text_selection(bw, act->data.mouse.x, act->data.mouse.y, 0);
+ break;
+ case act_START_NEW_SELECTION:
+ browser_window_text_selection(bw, act->data.mouse.x, act->data.mouse.y, 1);
+ break;
+ case act_ALTER_SELECTION:
+ browser_window_text_selection(bw, act->data.mouse.x, act->data.mouse.y, 2);
+ break;
+ case act_FOLLOW_LINK:
+ browser_window_follow_link(bw, act->data.mouse.x, act->data.mouse.y, 1);
+ break;
+ case act_FOLLOW_LINK_NEW_WINDOW:
+ browser_window_follow_link(bw, act->data.mouse.x, act->data.mouse.y, 2);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+void box_under_area(struct box* box, int x, int y, int ox, int oy,
+ struct box_selection** found, int* count, int* plot_index)
+{
+ struct box* c;
+
+ if (box == NULL)
+ return;
+
+ *plot_index = *plot_index + 1;
+
+ if (x >= box->x + ox && x <= box->x + ox + box->width &&
+ y >= box->y + oy && y <= box->y + oy + box->height)
+ {
+ *found = xrealloc(*found, sizeof(struct box_selection) * (*count + 1));
+ (*found)[*count].box = box;
+ (*found)[*count].actual_x = box->x + ox;
+ (*found)[*count].actual_y = box->y + oy;
+ (*found)[*count].plot_index = *plot_index;
+ *count = *count + 1;
+ }
+
+ for (c = box->children; c != 0; c = c->next)
+ if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT)
+ box_under_area(c, x, y, box->x + ox, box->y + oy, found, count, plot_index);
+
+ for (c = box->float_children; c != 0; c = c->next_float)
+ box_under_area(c, x, y, box->x + ox, box->y + oy, found, count, plot_index);
+
+ return;
+}
+
+void browser_window_follow_link(struct browser_window* bw,
+ int click_x, int click_y, int click_type)
+{
+ struct box_selection* click_boxes;
+ int found, plot_index;
+ int i;
+ int done = 0;
+
+ found = 0;
+ click_boxes = NULL;
+ plot_index = 0;
+
+ box_under_area(bw->current_content->data.html.layout->children,
+ click_x, click_y, 0, 0, &click_boxes, &found, &plot_index);
+
+ if (found == 0)
+ return;
+
+ for (i = found - 1; i >= 0; i--)
+ {
+ if (click_boxes[i].box->href != NULL)
+ {
+ if (click_type == 1)
+ browser_window_open_location(bw, (char*) click_boxes[i].box->href);
+ else if (click_type == 2)
+ {
+ struct browser_window* bw_new;
+ bw_new = create_browser_window(browser_TITLE | browser_TOOLBAR
+ | browser_SCROLL_X_NONE | browser_SCROLL_Y_ALWAYS, 640, 480);
+ gui_window_show(bw_new->window);
+ if (bw->url != NULL)
+ bw_new->url = xstrdup(bw->url);
+ browser_window_open_location(bw_new, (char*) click_boxes[i].box->href);
+ }
+ else if (click_type == 0)
+ {
+ browser_window_set_status(bw, (char*) click_boxes[i].box->href);
+ done = 1;
+ }
+ i = -1;
+ }
+ }
+
+ if (click_type == 0 && done == 0)
+ browser_window_set_status(bw, "");
+
+ free(click_boxes);
+
+ return;
+}
+
+void browser_window_text_selection(struct browser_window* bw,
+ int click_x, int click_y, int click_type)
+{
+ struct box_selection* click_boxes;
+ int found, plot_index;
+ int i;
+
+ if (click_type == 0 /* click_CLEAR_SELECTION */ )
+ {
+ browser_window_clear_text_selection(bw);
+ return;
+ }
+
+ found = 0;
+ click_boxes = NULL;
+ plot_index = 0;
+
+ box_under_area(bw->current_content->data.html.layout->children,
+ click_x, click_y, 0, 0, &click_boxes, &found, &plot_index);
+
+ if (found == 0)
+ return;
+
+ for (i = found - 1; i >= 0; i--)
+ {
+ if (click_boxes[i].box->type == BOX_INLINE)
+ {
+ struct box_position new_pos;
+ struct box_position* start;
+ struct box_position* end;
+ int click_char_offset, click_pixel_offset;
+
+ /* shortcuts */
+ start = &(bw->current_content->data.html.text_selection.start);
+ end = &(bw->current_content->data.html.text_selection.end);
+
+ font_position_in_string(click_boxes[i].box->text,
+ click_boxes[i].box->style, click_boxes[i].box->length,
+ click_x - click_boxes[i].actual_x,
+ &click_char_offset, &click_pixel_offset);
+
+ new_pos.box = click_boxes[i].box;
+ new_pos.actual_box_x = click_boxes[i].actual_x;
+ new_pos.actual_box_y = click_boxes[i].actual_y;
+ new_pos.plot_index = click_boxes[i].plot_index;
+ new_pos.char_offset = click_char_offset;
+ new_pos.pixel_offset = click_pixel_offset;
+
+ if (click_type == 1 /* click_START_SELECTION */ )
+ {
+ /* update both start and end */
+ browser_window_clear_text_selection(bw);
+ bw->current_content->data.html.text_selection.altering = alter_UNKNOWN;
+ bw->current_content->data.html.text_selection.selected = 1;
+ memcpy(start, &new_pos, sizeof(struct box_position));
+ memcpy(end, &new_pos, sizeof(struct box_position));
+ i = -1;
+ }
+ else if (bw->current_content->data.html.text_selection.selected == 1 &&
+ click_type == 2 /* click_ALTER_SELECTION */)
+ {
+ /* alter selection */
+
+ if (bw->current_content->data.html.text_selection.altering
+ != alter_UNKNOWN)
+ {
+ if (bw->current_content->data.html.text_selection.altering
+ == alter_START)
+ {
+ if (box_position_gt(&new_pos,end))
+ {
+ bw->current_content->data.html.text_selection.altering
+ = alter_END;
+ browser_window_change_text_selection(bw, end, &new_pos);
+ }
+ else
+ browser_window_change_text_selection(bw, &new_pos, end);
+ }
+ else
+ {
+ if (box_position_lt(&new_pos,start))
+ {
+ bw->current_content->data.html.text_selection.altering
+ = alter_START;
+ browser_window_change_text_selection(bw, &new_pos, start);
+ }
+ else
+ browser_window_change_text_selection(bw, start, &new_pos);
+ }
+ i = -1;
+ }
+ else
+ {
+ /* work out whether the start or end is being dragged */
+
+ int click_start_distance = 0;
+ int click_end_distance = 0;
+
+ int inside_block = 0;
+ int before_start = 0;
+ int after_end = 0;
+
+ if (box_position_lt(&new_pos, start))
+ before_start = 1;
+
+ if (box_position_gt(&new_pos, end))
+ after_end = 1;
+
+ if (!box_position_lt(&new_pos, start)
+ && !box_position_gt(&new_pos, end))
+ inside_block = 1;
+
+ if (inside_block == 1)
+ {
+ click_start_distance = box_position_distance(start, &new_pos);
+ click_end_distance = box_position_distance(end, &new_pos);
+ }
+
+ if (before_start == 1
+ || (after_end == 0 && inside_block == 1
+ && click_start_distance < click_end_distance))
+ {
+ /* alter the start position */
+ bw->current_content->data.html.text_selection.altering
+ = alter_START;
+ browser_window_change_text_selection(bw, &new_pos, end);
+ i = -1;
+ }
+ else if (after_end == 1
+ || (before_start == 0 && inside_block == 1
+ && click_start_distance >= click_end_distance))
+ {
+ /* alter the end position */
+ bw->current_content->data.html.text_selection.altering = alter_END;
+ browser_window_change_text_selection(bw, start, &new_pos);
+ i = -1;
+ }
+ }
+ }
+ }
+ }
+
+ free(click_boxes);
+
+ return;
+}
+
+void browser_window_clear_text_selection(struct browser_window* bw)
+{
+ struct box_position* old_start;
+ struct box_position* old_end;
+
+ old_start = &(bw->current_content->data.html.text_selection.start);
+ old_end = &(bw->current_content->data.html.text_selection.end);
+
+ if (bw->current_content->data.html.text_selection.selected == 1)
+ {
+ bw->current_content->data.html.text_selection.selected = 0;
+ browser_window_redraw_boxes(bw, old_start, old_end);
+ }
+
+ bw->current_content->data.html.text_selection.altering = alter_UNKNOWN;
+}
+
+void browser_window_change_text_selection(struct browser_window* bw,
+ struct box_position* new_start, struct box_position* new_end)
+{
+ struct box_position start;
+ struct box_position end;
+
+ memcpy(&start, &(bw->current_content->data.html.text_selection.start), sizeof(struct box_position));
+ memcpy(&end, &(bw->current_content->data.html.text_selection.end), sizeof(struct box_position));
+
+ if (!box_position_eq(new_start, &start))
+ {
+ if (box_position_lt(new_start, &start))
+ browser_window_redraw_boxes(bw, new_start, &start);
+ else
+ browser_window_redraw_boxes(bw, &start, new_start);
+ memcpy(&start, new_start, sizeof(struct box_position));
+ }
+
+ if (!box_position_eq(new_end, &end))
+ {
+ if (box_position_lt(new_end, &end))
+ browser_window_redraw_boxes(bw, new_end, &end);
+ else
+ browser_window_redraw_boxes(bw, &end, new_end);
+ memcpy(&end, new_end, sizeof(struct box_position));
+ }
+
+ memcpy(&(bw->current_content->data.html.text_selection.start), &start, sizeof(struct box_position));
+ memcpy(&(bw->current_content->data.html.text_selection.end), &end, sizeof(struct box_position));
+
+ bw->current_content->data.html.text_selection.selected = 1;
+}
+
+
+int box_position_lt(struct box_position* x, struct box_position* y)
+{
+ return (x->plot_index < y->plot_index ||
+ (x->plot_index == y->plot_index && x->char_offset < y->char_offset));
+}
+
+int box_position_gt(struct box_position* x, struct box_position* y)
+{
+ return (x->plot_index > y->plot_index ||
+ (x->plot_index == y->plot_index && x->char_offset > y->char_offset));
+}
+
+int box_position_eq(struct box_position* x, struct box_position* y)
+{
+ return (x->plot_index == y->plot_index && x->char_offset == y->char_offset);
+}
+
+int box_position_distance(struct box_position* x, struct box_position* y)
+{
+ int dx = (y->actual_box_x + y->pixel_offset)
+ - (x->actual_box_x + x->pixel_offset);
+ int dy = (y->actual_box_y + y->box->height / 2)
+ - (x->actual_box_y + x->box->height / 2);
+ return dx*dx + dy*dy;
+}
+
+int redraw_min_x = INT_MAX;
+int redraw_min_y = INT_MAX;
+int redraw_max_x = INT_MIN;
+int redraw_max_y = INT_MIN;
+
+int redraw_box_list(struct browser_window* bw, struct box* current,
+ int x, int y, struct box_position* start, struct box_position* end,
+ int* plot)
+{
+
+ struct box* c;
+
+ if (current == start->box)
+ *plot = 1;
+
+ if (*plot >= 1 && current->type == BOX_INLINE)
+ {
+ int minx = x + current->x;
+ int miny = y + current->y;
+ int maxx = x + current->x + current->width;
+ int maxy = y + current->y + current->height;
+
+ if (minx < redraw_min_x)
+ redraw_min_x = minx;
+ if (miny < redraw_min_y)
+ redraw_min_y = miny;
+ if (maxx > redraw_max_x)
+ redraw_max_x = maxx;
+ if (maxy > redraw_max_y)
+ redraw_max_y = maxy;
+
+ *plot = 2;
+ }
+
+ if (current == end->box)
+ return 1;
+
+ for (c = current->children; c != 0; c = c->next)
+ if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT)
+ if (redraw_box_list(bw, c, x + current->x, y + current->y,
+ start, end, plot) == 1)
+ return 1;
+
+ for (c = current->float_children; c != 0; c = c->next_float)
+ if (redraw_box_list(bw, c, x + current->x, y + current->y,
+ start, end, plot) == 1)
+ return 1;
+
+ return 0;
+}
+
+void browser_window_redraw_boxes(struct browser_window* bw, struct box_position* start, struct box_position* end)
+{
+ int plot = 0;
+
+ if (box_position_eq(start, end))
+ return;
+
+ redraw_min_x = INT_MAX;
+ redraw_min_y = INT_MAX;
+ redraw_max_x = INT_MIN;
+ redraw_max_y = INT_MIN;
+
+ redraw_box_list(bw, bw->current_content->data.html.layout,
+ 0,0, start, end, &plot);
+
+ if (plot == 2)
+ gui_window_redraw(bw->window, redraw_min_x, redraw_min_y,
+ redraw_max_x, redraw_max_y);
+}
diff --git a/desktop/browser.h b/desktop/browser.h
new file mode 100644
index 000000000..1e158b3a8
--- /dev/null
+++ b/desktop/browser.h
@@ -0,0 +1,148 @@
+/**
+ * $Id: browser.h,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#ifndef _NETSURF_DESKTOP_BROWSER_H_
+#define _NETSURF_DESKTOP_BROWSER_H_
+
+#include "libxml/HTMLparser.h"
+#include "netsurf/render/css.h"
+#include "netsurf/render/box.h"
+#include "netsurf/desktop/gui.h"
+#include "netsurf/desktop/fetch.h"
+
+typedef int browser_window_flags;
+#define browser_TOOLBAR ((browser_window_flags) 1)
+#define browser_TITLE ((browser_window_flags) 2)
+#define browser_SCROLL_X_NONE ((browser_window_flags) 4)
+#define browser_SCROLL_X_AUTO ((browser_window_flags) 8)
+#define browser_SCROLL_X_ALWAYS ((browser_window_flags) 16)
+#define browser_SCROLL_Y_NONE ((browser_window_flags) 32)
+#define browser_SCROLL_Y_AUTO ((browser_window_flags) 64)
+#define browser_SCROLL_Y_ALWAYS ((browser_window_flags) 128)
+
+typedef int action_buttons;
+#define act_BUTTON_NORMAL ((action_buttons) 4)
+#define act_BUTTON_ALTERNATIVE ((action_buttons) 1)
+#define act_BUTTON_CONTEXT_MENU ((action_buttons) 2)
+
+
+
+struct box_position
+{
+ struct box* box;
+ int actual_box_x;
+ int actual_box_y;
+ int plot_index;
+ int pixel_offset;
+ int char_offset;
+};
+
+struct content
+{
+ enum {CONTENT_UNKNOWN, CONTENT_HTML, CONTENT_IMAGE} type;
+
+ union
+ {
+ struct
+ {
+ htmlParserCtxt* parser;
+ xmlDoc* document;
+ xmlNode* markup;
+ struct box* layout;
+ struct css_stylesheet* stylesheet;
+ struct css_style* style;
+ struct {
+ struct box_position start;
+ struct box_position end;
+ enum {alter_UNKNOWN, alter_START, alter_END} altering;
+ int selected; /* 0 = unselected, 1 = selected */
+ } text_selection;
+ } html;
+ } data;
+ struct fetch* main_fetch;
+};
+
+
+struct history
+{
+ struct history* earlier;
+ struct history* later;
+ char* description;
+ char* url;
+};
+
+struct history* history_create(char* desc, char* url);
+void history_remember(struct history* current, char* desc, char* url);
+
+
+struct browser_window
+{
+ int format_width;
+ int format_height;
+ struct { int mult; int div; } scale;
+
+ struct content* current_content;
+ struct content* future_content;
+ struct history* history;
+
+ char* url;
+
+ browser_window_flags flags;
+ char* title;
+ gui_window* window;
+};
+
+
+struct browser_message
+{
+ enum { msg_UNKNOWN,
+ msg_FETCH_SENDING, msg_FETCH_WAITING, msg_FETCH_ABORT,
+ msg_FETCH_FETCH_INFO, msg_FETCH_DATA, msg_FETCH_FINISHED
+ } type;
+ struct fetch* f;
+ union {
+ struct {
+ enum { type_UNKNOWN, type_HTML } type; /* should be a MIME type ? */
+ int total_size; /* -1 == unknown size */
+ } fetch_info;
+ struct {
+ char* block;
+ int block_size;
+ } fetch_data;
+ } data;
+};
+
+
+struct browser_action
+{
+ enum { act_UNKNOWN,
+ act_MOUSE_AT, act_MOUSE_CLICK, act_START_NEW_SELECTION,
+ act_ALTER_SELECTION, act_CLEAR_SELECTION,
+ act_FOLLOW_LINK, act_FOLLOW_LINK_NEW_WINDOW
+ } type;
+ union {
+ struct {
+ int x;
+ int y;
+ action_buttons buttons;
+ } mouse;
+ } data;
+};
+
+/* public functions */
+
+struct browser_window* create_browser_window(int flags, int width, int height);
+void browser_window_destroy(struct browser_window* bw);
+void browser_window_open_location(struct browser_window* bw, char* url);
+int browser_window_message(struct browser_window* bw, struct browser_message* msg);
+int browser_window_action(struct browser_window* bw, struct browser_action* act);
+void browser_window_set_status(struct browser_window* bw, char* text);
+
+int box_position_lt(struct box_position* x, struct box_position* y);
+int box_position_gt(struct box_position* x, struct box_position* y);
+int box_position_eq(struct box_position* x, struct box_position* y);
+int box_position_distance(struct box_position* x, struct box_position* y);
+
+
+#endif
diff --git a/desktop/fetch.c b/desktop/fetch.c
new file mode 100644
index 000000000..a7881fcc2
--- /dev/null
+++ b/desktop/fetch.c
@@ -0,0 +1,344 @@
+/**
+ * $Id: fetch.c,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#include "libxml/HTMLparser.h"
+#include "netsurf/render/box.h"
+#include "netsurf/render/css.h"
+#include "netsurf/desktop/browser.h"
+#include "netsurf/desktop/netsurf.h"
+#include "netsurf/desktop/fetch.h"
+#include "netsurf/render/utils.h"
+#include "curl/curl.h"
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+
+void fetch_identify_location(struct fetch* f, char* location, char* previous)
+{
+ FILE* ff = fopen("identify", "a");
+ fprintf(ff, "identify: '%s' '%s'", location, previous);
+ if (f->location != NULL)
+ fprintf(ff, " '%s'\n", f->location);
+ else
+ fprintf(ff, "\n");
+ fclose(ff);
+
+ if (f->location != NULL)
+ xfree(f->location);
+
+ if (strspn(location, "http://") == strlen("http://"))
+ {
+ f->location = xstrdup(location);
+ f->type = fetch_CURL;
+ return;
+ }
+ else if (strspn(location, "file:/") == strlen("file:/"))
+ {
+ f->location = xstrdup(location);
+ f->type = fetch_FILE;
+ return;
+ }
+ else if (previous != NULL)
+ {
+ char* ext = strrchr(previous, '/');
+
+ if (ext != NULL && ext != previous)
+ {
+ int len = (int)(ext - previous) + strlen(location) + 2;
+ char* combined = xcalloc(len, sizeof(char));
+ strncpy(combined, previous, (int)(ext - previous));
+ strcpy(combined + (ext - previous), "/");
+ strcpy(combined + (ext - previous) + 1, location);
+ fetch_identify_location(f, combined, NULL);
+ xfree(combined);
+ return;
+ }
+ }
+
+ f->location = xcalloc(strlen(location) + strlen("http://") + 1, sizeof(char));
+ sprintf(f->location, "http://%s", location);
+ f->type = fetch_CURL;
+ return;
+}
+
+struct fetch* create_fetch(char* location, char* previous, fetch_flags f, struct fetch_request* r)
+{
+ struct fetch* fetch = (struct fetch*) xcalloc(1, sizeof(struct fetch));
+
+ fetch_identify_location(fetch, location, previous);
+
+ fetch->flags = f;
+
+ fetch->status = fetch_STATUS_WAIT;
+ fetch->bytes_fetched = 0;
+ fetch->bytes_total = -1;
+
+ fetch->request = r;
+
+ fetch->start_time = time(&fetch->start_time);
+
+ fetch->next = netsurf_fetches;
+ netsurf_fetches = fetch;
+
+ return fetch;
+}
+
+void fetch_destroy(struct fetch* f)
+{
+ if (f == NULL)
+ return;
+
+ if (netsurf_fetches == f)
+ netsurf_fetches = f->next;
+ else
+ {
+ struct fetch* ff = netsurf_fetches;
+ while (ff->next != f && ff->next != NULL)
+ ff = ff->next;
+ if (ff->next == f)
+ ff->next = f->next;
+ }
+
+ xfree(f->location);
+ xfree(f->request);
+ xfree(f);
+}
+
+struct fetch* fetch_cancel(struct fetch* f)
+{
+ if (f == NULL)
+ return NULL;
+
+ /* may need to contact server here */
+
+ f->status = fetch_DELETED;
+ /* fetch may not necessarily be destroyed if the cancelling can't be done
+ instantly */
+ return f;
+}
+
+void fetch_receive(struct fetch* f, int amount, char* bytes)
+{
+ struct browser_message msg;
+
+ f->bytes_fetched = f->bytes_fetched + amount;
+
+ switch (f->request->type)
+ {
+ case REQUEST_FROM_BROWSER:
+ msg.type = msg_FETCH_DATA;
+ msg.f = f;
+ msg.data.fetch_data.block = bytes;
+ msg.data.fetch_data.block_size = amount;
+ if (browser_window_message(f->request->requestor.browser, &msg) != 0)
+ {
+ fetch_cancel(f);
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (f->bytes_fetched >= f->bytes_total && f->bytes_total != -1)
+ {
+ msg.type = msg_FETCH_FINISHED;
+ msg.f = f;
+ browser_window_message(f->request->requestor.browser, &msg);
+ fetch_destroy(f);
+ }
+
+ return;
+}
+
+size_t fetch_curl_data(void * data, size_t size, size_t nmemb, struct fetch* f)
+{
+ struct browser_message msg;
+ msg.type = msg_FETCH_DATA;
+ msg.f = f;
+ msg.data.fetch_data.block = data;
+ msg.data.fetch_data.block_size = size * nmemb;
+ Log("fetch_poll","sending curl's FETCH_DATA to browser");
+ browser_window_message(f->request->requestor.browser, &msg);
+ return size * nmemb;
+}
+
+struct fetch* fetch_poll(struct fetch* f)
+{
+ struct fetch* ret = f;
+
+ Log("fetch_poll","polling...");
+
+ if (f == NULL)
+ {
+ Log("fetch_poll","null fetch; returning");
+ return f;
+ }
+
+ if (f->type == fetch_DELETED)
+ {
+ ret = f->next;
+ Log("fetch_poll", "deleting marked fetch");
+ fetch_destroy(f);
+ Log("fetch_poll", "moving on...");
+ return fetch_poll(ret);
+ }
+ else if (f->type == fetch_CURL && f->status == fetch_STATUS_WAIT)
+ {
+ struct browser_message msg;
+ CURL* curl;
+
+ Log("fetch_poll","init curl");
+ curl = curl_easy_init();
+ Log("fetch_poll","init curl returned");
+ if (curl != 0)
+ {
+ Log("fetch_poll","init curl OK");
+ /* shouldn't assume this! somehow work it out instead. */
+ msg.type = msg_FETCH_FETCH_INFO;
+ msg.f = f;
+ msg.data.fetch_info.type = type_HTML;
+ msg.data.fetch_info.total_size = -1;
+
+ if (browser_window_message(f->request->requestor.browser, &msg) == 0)
+ {
+ Log("fetch_poll","about to set options");
+ curl_easy_setopt(curl, CURLOPT_URL, f->location);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fetch_curl_data);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, f);
+ Log("fetch_poll","about to perform");
+ curl_easy_perform(curl);
+ Log("fetch_poll","about to cleanup");
+ curl_easy_cleanup(curl);
+
+ Log("fetch_poll","cleanup finished");
+ msg.type = msg_FETCH_FINISHED;
+ msg.f = f;
+ Log("fetch_poll","sending FETCH_FINISHED to browser");
+ browser_window_message(f->request->requestor.browser, &msg);
+ Log("fetch_poll","FETCH_FINISHED accepted");
+
+ ret = f->next;
+ Log("fetch_poll","Destroying f");
+ fetch_destroy(f);
+ Log("fetch_poll","Moving on...");
+ return fetch_poll(ret);
+ }
+ Log("fetch_poll","about to cleanup since requestor went funny");
+ curl_easy_cleanup(curl);
+
+ Log("fetch_poll","Requesting browser didn't like something");
+ ret = f->next;
+ Log("fetch_poll","Cancelling fetch");
+ f = fetch_cancel(f);
+ return fetch_poll(ret);
+ }
+
+ Log("fetch_poll","we are aborting the mission");
+ msg.type = msg_FETCH_ABORT;
+ msg.f = f;
+ browser_window_message(f->request->requestor.browser, &msg);
+ Log("fetch_poll","ABORT message sent to browser");
+
+ ret = f->next;
+ fetch_destroy(f);
+ return fetch_poll(ret); /* carry on polling */
+ }
+ else if (f->type == fetch_FILE && f->status == fetch_STATUS_WAIT)
+ {
+ struct browser_message msg;
+ char actual_filename[1024];
+ FILE* in;
+
+ gui_file_to_filename(f->location, actual_filename, 1024);
+ in = fopen("files","a");
+ fprintf(in, "%s\n%s\n\n",f->location, actual_filename);
+ fclose(in);
+ in = fopen(actual_filename, "r");
+
+ if (in == NULL)
+ {
+ /* can't open file -- send abort to requestor, then destroy */
+ Log("fetch_poll","can't open file");
+ msg.type = msg_FETCH_ABORT;
+ msg.f = f;
+ browser_window_message(f->request->requestor.browser, &msg);
+ Log("fetch_poll","ABORT message sent to browser");
+
+ ret = f->next;
+ fetch_destroy(f);
+ Log("fetch_poll","destroyed f; moving on");
+
+ return fetch_poll(ret); /* carry on polling */
+ }
+ else
+ {
+ /* file opened successfully. now to send size and type to requestor,
+ then the data, then finish. */
+ int size;
+
+ /* calculate size */
+ Log("fetch_poll","calculating file size");
+ fseek(in, 0, SEEK_END);
+ size = (int) ftell(in);
+ fclose(in);
+
+ /* send file info. (assuming HTML at the mo, but should work out
+ what it is, somehow) */
+ msg.type = msg_FETCH_FETCH_INFO;
+ msg.f = f;
+ msg.data.fetch_info.type = type_HTML;
+ msg.data.fetch_info.total_size = size;
+
+ Log("fetch_poll","sending FETCH_INFO to browser");
+ if (browser_window_message(f->request->requestor.browser, &msg) == 0)
+ {
+ /* file info accepted. can now load the data and send it */
+ Log("fetch_poll","FETCH_INFO accepted");
+ f->status = fetch_STATUS_FETCH;
+
+ /* load and send data */
+ msg.type = msg_FETCH_DATA;
+ msg.f = f;
+ msg.data.fetch_data.block = load(actual_filename);
+ msg.data.fetch_data.block_size = size;
+ Log("fetch_poll","sending FETCH_DATA to browser");
+ if (browser_window_message(f->request->requestor.browser, &msg) == 0)
+ {
+ xfree(msg.data.fetch_data.block);
+ /* data accepted. no more data, so finish */
+ Log("fetch_poll","FETCH_DATA accepted");
+ f->status = fetch_STATUS_FINISH;
+
+ /* send finish */
+ msg.type = msg_FETCH_FINISHED;
+ msg.f = f;
+ Log("fetch_poll","sending FETCH_FINISHED to browser");
+ browser_window_message(f->request->requestor.browser, &msg);
+ Log("fetch_poll","FETCH_FINISHED accepted");
+
+ ret = f->next;
+ Log("fetch_poll","Destroying f");
+ fetch_destroy(f);
+ Log("fetch_poll","Moving on...");
+ return fetch_poll(ret);
+ /* destroy this fetch, then move on to next fetch to poll */
+ }
+ xfree(msg.data.fetch_data.block);
+ }
+
+ /* requestor didn't like something, and wants the fetch cancelled */
+ Log("fetch_poll","Requesting browser didn't like something");
+ ret = f->next;
+ Log("fetch_poll","Cancelling fetch");
+ f = fetch_cancel(f);
+ return fetch_poll(ret);
+ }
+ }
+
+ Log("fetch_poll","Moving on (at end of function with f->next)");
+ f->next = fetch_poll(f->next);
+ return f;
+}
+
diff --git a/desktop/fetch.h b/desktop/fetch.h
new file mode 100644
index 000000000..c0c2c06ac
--- /dev/null
+++ b/desktop/fetch.h
@@ -0,0 +1,49 @@
+/**
+ * $Id: fetch.h,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#ifndef _NETSURF_DESKTOP_FETCH_H_
+#define _NETSURF_DESKTOP_FETCH_H_
+
+#include "libxml/HTMLparser.h"
+#include "netsurf/render/box.h"
+#include "netsurf/render/css.h"
+#include "netsurf/desktop/browser.h"
+#include <time.h>
+
+typedef enum {fetch_FILE, fetch_CURL} fetch_type;
+typedef enum {fetch_STATUS_SEND, fetch_STATUS_WAIT, fetch_STATUS_FETCH, fetch_STATUS_FINISH, fetch_DELETED} fetch_status;
+
+typedef int fetch_flags;
+#define fetch_DO_NOT_CHECK_CACHE ((fetch_flags) 1);
+#define fetch_DO_NOT_STORE_IN_CACHE ((fetch_flags) 2);
+
+struct fetch_request {
+ enum {REQUEST_FROM_BROWSER} type;
+ union {struct browser_window* browser;} requestor;
+};
+
+struct fetch
+{
+ char* location;
+ fetch_type type;
+ fetch_flags flags;
+
+ fetch_status status;
+ int bytes_fetched;
+ int bytes_total;
+
+ struct fetch_request* request;
+
+ time_t start_time;
+
+ struct fetch* next;
+};
+
+struct fetch* create_fetch(char* location, char* previous, fetch_flags f, struct fetch_request* r);
+void fetch_destroy(struct fetch* f);
+struct fetch* fetch_cancel(struct fetch* f);
+void fetch_receive(struct fetch* f, int amount, char* bytes);
+struct fetch* fetch_poll(struct fetch* f);
+
+#endif
diff --git a/desktop/gui.h b/desktop/gui.h
new file mode 100644
index 000000000..5d5607065
--- /dev/null
+++ b/desktop/gui.h
@@ -0,0 +1,45 @@
+/**
+ * $Id: gui.h,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#ifndef _NETSURF_DESKTOP_GUI_H_
+#define _NETSURF_DESKTOP_GUI_H_
+
+typedef enum { GUI_BROWSER_WINDOW } gui_window_type;
+typedef enum { SAFE, UNSAFE } gui_safety;
+
+#include "netsurf/riscos/gui.h"
+#include "netsurf/desktop/browser.h"
+
+struct gui_message
+{
+ enum { msg_SET_URL } type;
+ union {
+ struct {
+ char* url;
+ } set_url;
+ } data;
+};
+
+typedef struct gui_message gui_message;
+
+gui_window* create_gui_browser_window(struct browser_window* bw);
+void gui_window_destroy(gui_window* g);
+void gui_window_show(gui_window* g);
+void gui_window_hide(gui_window* g);
+void gui_window_redraw(gui_window* g, int x0, int y0, int x1, int y1);
+void gui_window_redraw_window(gui_window* g);
+void gui_window_set_scroll(gui_window* g, int sx, int sy);
+void gui_window_set_extent(gui_window* g, int width, int height);
+void gui_window_set_status(gui_window* g, char* text);
+
+void gui_window_message(gui_window* g, gui_message* msg);
+
+void gui_init(int argc, char** argv);
+void gui_multitask(void);
+void gui_poll(void);
+
+gui_safety gui_window_set_redraw_safety(gui_window* g, gui_safety s);
+int gui_file_to_filename(char* location, char* actual_filename, int size);
+
+#endif
diff --git a/desktop/netsurf.c b/desktop/netsurf.c
new file mode 100644
index 000000000..cc53acc05
--- /dev/null
+++ b/desktop/netsurf.c
@@ -0,0 +1,50 @@
+/**
+ * $Id: netsurf.c,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#include "netsurf/desktop/netsurf.h"
+#include "netsurf/desktop/fetch.h"
+#include "netsurf/desktop/browser.h"
+#include "netsurf/desktop/gui.h"
+#include <stdlib.h>
+
+int netsurf_quit = 0;
+gui_window* netsurf_gui_windows = NULL;
+struct fetch* netsurf_fetches = NULL;
+
+
+void netsurf_poll(void)
+{
+ gui_poll();
+ netsurf_fetches = fetch_poll(netsurf_fetches);
+}
+
+
+void netsurf_init(int argc, char** argv)
+{
+ gui_init(argc, argv);
+}
+
+
+int main(int argc, char** argv)
+{
+ netsurf_init(argc, argv);
+
+ while (netsurf_quit == 0)
+ netsurf_poll();
+
+ return 0;
+}
+
+
+void Log(char* func, char* msg)
+{
+#ifdef NETSURF_DUMP
+ FILE* logfile = NULL;
+ logfile = fopen("logfile","a");
+ if (logfile == NULL)
+ die("can't open logfile");
+ fprintf(logfile, "%s: %s\n", func, msg);
+ fclose(logfile);
+#endif
+}
diff --git a/desktop/netsurf.h b/desktop/netsurf.h
new file mode 100644
index 000000000..1ebdf9d88
--- /dev/null
+++ b/desktop/netsurf.h
@@ -0,0 +1,35 @@
+/**
+ * $Id: netsurf.h,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#ifndef _NETSURF_DESKTOP_NETSURF_H_
+#define _NETSURF_DESKTOP_NETSURF_H_
+
+#include "netsurf/desktop/fetch.h"
+#include "netsurf/desktop/browser.h"
+
+extern struct fetch* netsurf_fetches;
+extern gui_window* netsurf_gui_windows;
+
+extern int netsurf_quit;
+
+void netsurf_poll(void);
+void Log(char* func, char* msg);
+
+#endif
+
+#ifndef _NETSURF_DESKTOP_NETSURF_H_
+#define _NETSURF_DESKTOP_NETSURF_H_
+
+#include "netsurf/desktop/fetch.h"
+#include "netsurf/desktop/browser.h"
+
+extern struct fetch* netsurf_fetches;
+extern gui_window* netsurf_gui_windows;
+
+extern int netsurf_quit;
+
+void netsurf_poll(void);
+void Log(char* func, char* msg);
+
+#endif
diff --git a/makefile b/makefile
index 489135a5b..c9f1de94f 100644
--- a/makefile
+++ b/makefile
@@ -1,21 +1,24 @@
-# $Id: makefile,v 1.1 2002/07/27 21:10:45 bursa Exp $
+# $Id: makefile,v 1.2 2002/09/11 14:24:02 monkeyson Exp $
all: netsurf,ff8
clean:
rm */objs-riscos/*
-FLAGS = -g -Wall -W -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual \
+FLAGS = -g -Wall -W -Wundef -Wpointer-arith -Wbad-function-cast -Wcast-qual \
-Wcast-align -Wwrite-strings -Wconversion -Wstrict-prototypes -Wmissing-prototypes \
-Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -std=c9x \
-I.. -I../../Tools/libxml2/include -I../../Tools/oslib \
- -I../../Tools/curl/include -Dfd_set=long
+ -I../../Tools/curl/include -Dfd_set=long -mpoke-function-name
CC = riscos-gcc
OBJECTS = render/objs-riscos/utils.o render/objs-riscos/css.o \
render/objs-riscos/css_enum.o render/objs-riscos/box.o \
render/objs-riscos/layout.o \
- riscos/objs-riscos/netsurf.o riscos/objs-riscos/font.o
-HEADERS = render/box.h render/css.h render/css_enum.h render/font.h \
- render/layout.h render/utils.h
+ riscos/objs-riscos/gui.o riscos/objs-riscos/font.o \
+ desktop/objs-riscos/browser.o desktop/objs-riscos/fetch.o \
+ desktop/objs-riscos/netsurf.o
+HEADERS = render/box.h render/css.h render/css_enum.h \
+ render/layout.h render/utils.h riscos/font.h riscos/gui.h \
+ desktop/browser.h desktop/fetch.h desktop/gui.h desktop/netsurf.h
LIBS = ../../Tools/libxml2/libxml.ro ../../Tools/oslib/oslib.o ../../Tools/curl/libcurl.ro
netsurf,ff8: $(OBJECTS)
@@ -29,3 +32,7 @@ render/objs-riscos/%.o: render/%.c $(HEADERS)
riscos/objs-riscos/%.o: riscos/%.c $(HEADERS)
$(CC) $(FLAGS) -o $@ -c $<
+
+desktop/objs-riscos/%.o: desktop/%.c $(HEADERS)
+ $(CC) $(FLAGS) -o $@ -c $<
+
diff --git a/render/box.c b/render/box.c
index 94c550c69..ee9f5b1b4 100644
--- a/render/box.c
+++ b/render/box.c
@@ -1,5 +1,5 @@
/**
- * $Id: box.c,v 1.12 2002/09/08 18:11:56 bursa Exp $
+ * $Id: box.c,v 1.13 2002/09/11 14:24:02 monkeyson Exp $
*/
#include <assert.h>
@@ -113,6 +113,8 @@ struct box * convert_xml_to_box(xmlNode * n, struct css_style * parent_style,
xmlNode * c;
char * s;
+ gui_multitask();
+
if (n->type == XML_ELEMENT_NODE) {
/* work out the style for this element */
*selector = xrealloc(*selector, (depth + 1) * sizeof(struct css_selector));
diff --git a/render/layout.c b/render/layout.c
index 7d15fb11b..53f4eedea 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -1,5 +1,5 @@
/**
- * $Id: layout.c,v 1.14 2002/09/08 18:11:56 bursa Exp $
+ * $Id: layout.c,v 1.15 2002/09/11 14:24:02 monkeyson Exp $
*/
#include <assert.h>
@@ -86,6 +86,8 @@ void layout_node(struct box * box, unsigned long width, struct box * cont,
box, width, cont, cx, cy);
#endif
+ gui_multitask();
+
switch (box->type) {
case BOX_BLOCK:
layout_block(box, width, cont, cx, cy);
diff --git a/riscos/font.c b/riscos/font.c
index a12ff2241..05faf50cf 100644
--- a/riscos/font.c
+++ b/riscos/font.c
@@ -1,31 +1,56 @@
/**
- * $Id: font.c,v 1.1 2002/07/27 21:10:45 bursa Exp $
+ * $Id: font.c,v 1.2 2002/09/11 14:24:02 monkeyson Exp $
*/
#include <stdio.h>
#include "netsurf/render/css.h"
#include "netsurf/render/font.h"
#include "netsurf/render/utils.h"
+#include "netsurf/desktop/gui.h"
#include "oslib/font.h"
/**
* functions
*/
-extern font_f font;
+/** it is rather inefficient calling this all the time **/
+font_f riscos_font_css_to_handle(struct css_style* style)
+{
+ int width = 12 * 16;
+ int height = 12 * 16;
+ char font_name[255];
+
+ if (style->font_size.size == CSS_FONT_SIZE_LENGTH)
+ width = height = style->font_size.value.length.value * 16;
+
+ strcpy(font_name, "Homerton.");
+ if (style->font_weight == CSS_FONT_WEIGHT_BOLD)
+ strcat(font_name, "Bold");
+ else
+ strcat(font_name, "Medium");
+
+ if (style->font_style == CSS_FONT_STYLE_ITALIC || style->font_style == CSS_FONT_STYLE_OBLIQUE)
+ strcat(font_name, ".Oblique");
+
+ return font_find_font(font_name, width, height, 0, 0, 0, 0);
+}
unsigned long font_width(struct css_style * style, const char * text, unsigned int length)
{
font_scan_block block;
os_error * error;
+ font_f font;
- if (length == 0) return 0;
+ if (length == 0)
+ return 0;
block.space.x = block.space.y = 0;
block.letter.x = block.letter.y = 0;
block.split_char = -1;
- error = xfont_scan_string(font, text,
+ font = riscos_font_css_to_handle(style);
+
+ error = xfont_scan_string(font, (char*) text,
font_GIVEN_BLOCK | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN | font_RETURN_BBOX,
0x7fffffff, 0x7fffffff,
&block,
@@ -35,6 +60,59 @@ unsigned long font_width(struct css_style * style, const char * text, unsigned i
fprintf(stderr, "%s\n", error->errmess);
die("font_scan_string failed");
}
+
+// fprintf(stderr, "Stated length %d, strlen %d\n", (int)length, strlen(text));
+
+ if (length < 0x7fffffff)
+ {
+ if (text[length - 1] == ' ')
+// {
+ block.bbox.x1 += 4*800;
+/* int minx,miny,maxx,maxy;
+ char space = ' ';
+// fprintf(stderr, "Space at the end!\n");
+ error = xfont_char_bbox(font, space, 0, &minx, &miny, &maxx, &maxy);
+ if (error != 0) {
+ fprintf(stderr, "%s\n", error->errmess);
+ die("font_char_bbox failed");
+ }
+ block.bbox.x1 += maxx;
+ }
+// else
+// fprintf(stderr, "No space\n");*/
+ }
+
+ font_lose_font(font);
+
return block.bbox.x1 / 800;
}
+void font_position_in_string(const char* text, struct css_style* style, int length, int x, int* char_offset, int* pixel_offset)
+{
+ font_f font;
+ font_scan_block block;
+ char* split_point;
+ int x_out, y_out, length_out;
+
+ block.space.x = block.space.y = 0;
+ block.letter.x = block.letter.y = 0;
+ block.split_char = -1;
+
+ font = riscos_font_css_to_handle(style);
+
+ xfont_scan_string(font, (char*) text,
+ font_GIVEN_BLOCK | font_GIVEN_LENGTH |
+ font_GIVEN_FONT | font_KERN | font_RETURN_CARET_POS,
+ ro_x_units(x) * 400,
+ 0x7fffffff,
+ &block, 0, length,
+ &split_point, &x_out, &y_out, &length_out);
+
+ font_lose_font(font);
+
+ *char_offset = (int)(split_point - text);
+ *pixel_offset = browser_x_units(x_out / 400);
+
+ return;
+}
+
diff --git a/riscos/font.h b/riscos/font.h
new file mode 100644
index 000000000..ee3e4c2b2
--- /dev/null
+++ b/riscos/font.h
@@ -0,0 +1,39 @@
+/**
+ * $Id: font.h,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#ifndef _NETSURF_RISCOS_FONT_H_
+#define _NETSURF_RISCOS_FONT_H_
+
+/**
+ * structures and typedefs
+ */
+
+#include "netsurf/render/css.h"
+#include "oslib/font.h"
+
+struct font_set;
+typedef unsigned int font_id;
+struct font_split {
+ unsigned long width;
+ unsigned long height;
+ const char * end;
+};
+
+/**
+ * interface
+ */
+
+struct font_set * font_set_create(void);
+font_id font_add(struct font_set * font_set, const char * name, unsigned int weight,
+ unsigned int size);
+void font_set_free(struct font_set * font_set);
+struct font_split font_split(struct font_set * font_set, font_id id, const char * text,
+ unsigned long width, int force);
+unsigned long font_width(struct css_style * style, const char * text, unsigned int length);
+
+font_f riscos_font_css_to_handle(struct css_style* style);
+
+void font_position_in_string(const char* text, struct css_style* style, int length, int x, int* char_offset, int* pixel_offset);
+
+#endif
diff --git a/riscos/gui.c b/riscos/gui.c
new file mode 100644
index 000000000..15d38b540
--- /dev/null
+++ b/riscos/gui.c
@@ -0,0 +1,1057 @@
+/**
+ * $Id: gui.c,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#include "netsurf/riscos/font.h"
+#include "netsurf/desktop/gui.h"
+#include "netsurf/render/utils.h"
+#include "netsurf/desktop/netsurf.h"
+#include "oslib/wimp.h"
+#include "oslib/colourtrans.h"
+#include <string.h>
+#include <stdlib.h>
+
+#define TOOLBAR_HEIGHT 128;
+
+char* BROWSER_VALIDATION = "\0";
+
+const char* task_name = "NetSurf";
+const wimp_MESSAGE_LIST(1) task_messages = { {0} };
+wimp_t task_handle;
+
+wimp_i ro_gui_iconbar_i;
+
+gui_window* over_window = NULL;
+
+int ro_x_units(int browser_units)
+{
+ return (browser_units << 1);
+}
+
+int ro_y_units(int browser_units)
+{
+ return -(browser_units << 1);
+}
+
+int browser_x_units(int ro_units)
+{
+ return (ro_units >> 1);
+}
+
+int browser_y_units(int ro_units)
+{
+ return -(ro_units >> 1);
+}
+
+int window_x_units(int scr_units, wimp_window_state* win)
+{
+ return scr_units - (win->visible.x0 - win->xscroll);
+}
+
+int window_y_units(int scr_units, wimp_window_state* win)
+{
+ return scr_units - (win->visible.y1 - win->yscroll);
+}
+
+gui_window* create_gui_browser_window(struct browser_window* bw)
+{
+ struct wimp_window window;
+
+ gui_window* g = (gui_window*) xcalloc(1, sizeof(gui_window));
+ g->type = GUI_BROWSER_WINDOW;
+ g->data.browser.bw = bw;
+ /* create browser and toolbar windows here */
+
+ window.visible.x0 = 0;
+ window.visible.y0 = 0;
+ window.visible.x1 = ro_x_units(bw->format_width);
+ window.visible.y1 = 2000;
+ window.xscroll = 0;
+ window.yscroll = 0;
+ window.next = wimp_TOP;
+ window.flags =
+ wimp_WINDOW_MOVEABLE | wimp_WINDOW_NEW_FORMAT | wimp_WINDOW_BACK_ICON |
+ wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | wimp_WINDOW_VSCROLL |
+ wimp_WINDOW_SIZE_ICON | wimp_WINDOW_TOGGLE_ICON;
+ window.title_fg = wimp_COLOUR_BLACK;
+ window.title_bg = wimp_COLOUR_LIGHT_GREY;
+ window.work_fg = wimp_COLOUR_LIGHT_GREY;
+ window.work_bg = wimp_COLOUR_WHITE;
+ window.scroll_outer = wimp_COLOUR_DARK_GREY;
+ window.scroll_inner = wimp_COLOUR_MID_LIGHT_GREY;
+ window.highlight_bg = wimp_COLOUR_CREAM;
+ window.extra_flags = 0;
+ window.extent.x0 = 0;
+ window.extent.y0 = ro_y_units(bw->format_height);
+ window.extent.x1 = ro_x_units(bw->format_width);
+ if ((bw->flags & browser_TOOLBAR) != 0)
+ {
+ window.extent.y1 = TOOLBAR_HEIGHT;
+ }
+ else
+ {
+ window.extent.y1 = 0;
+ }
+ window.title_flags = wimp_ICON_TEXT | wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED;
+ window.work_flags = wimp_BUTTON_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT;
+ window.sprite_area = NULL;
+ window.xmin = 0;
+ window.ymin = 2;
+ window.title_data.indirected_text.text = g->title;
+ window.title_data.indirected_text.validation = BROWSER_VALIDATION;
+ window.title_data.indirected_text.size = 255;
+ window.icon_count = 0;
+ g->data.browser.window = wimp_create_window(&window);
+
+ strcpy(g->title, "NetSurf");
+
+ if ((bw->flags & browser_TOOLBAR) != 0)
+ {
+ struct wimp_window toolbar;
+ wimp_icon_create status_icon;
+ wimp_icon_create url_icon;
+
+ toolbar.visible.x0 = 0;
+ toolbar.visible.y0 = 0;
+ toolbar.visible.x1 = 4096;
+ toolbar.visible.y1 = TOOLBAR_HEIGHT;
+ toolbar.xscroll = 0;
+ toolbar.yscroll = 0;
+ toolbar.next = wimp_TOP;
+ toolbar.flags =
+ wimp_WINDOW_MOVEABLE | wimp_WINDOW_NEW_FORMAT |
+ wimp_WINDOW_AUTO_REDRAW | wimp_WINDOW_FURNITURE_WINDOW;
+ toolbar.title_fg = wimp_COLOUR_BLACK;
+ toolbar.title_bg = wimp_COLOUR_LIGHT_GREY;
+ toolbar.work_fg = wimp_COLOUR_LIGHT_GREY;
+ toolbar.work_bg = wimp_COLOUR_VERY_LIGHT_GREY;
+ toolbar.scroll_outer = wimp_COLOUR_DARK_GREY;
+ toolbar.scroll_inner = wimp_COLOUR_MID_LIGHT_GREY;
+ toolbar.highlight_bg = wimp_COLOUR_CREAM;
+ toolbar.extra_flags = 0;
+ toolbar.extent.x0 = 0;
+ toolbar.extent.y0 = -TOOLBAR_HEIGHT;
+ toolbar.extent.x1 = 4096;
+ if ((bw->flags & browser_TOOLBAR) != 0)
+ {
+ toolbar.extent.y1 = TOOLBAR_HEIGHT;
+ }
+ else
+ {
+ toolbar.extent.y1 = 0;
+ }
+ toolbar.title_flags = wimp_ICON_TEXT;
+ toolbar.work_flags = wimp_BUTTON_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT;
+ toolbar.sprite_area = NULL;
+ toolbar.xmin = 0;
+ toolbar.ymin = 2;
+ toolbar.icon_count = 0;
+ g->data.browser.toolbar = wimp_create_window(&toolbar);
+
+ status_icon.w = g->data.browser.toolbar;
+ status_icon.icon.extent.x0 = 0;
+ status_icon.icon.extent.y0 = -128;
+ status_icon.icon.extent.x1 = 4096;
+ status_icon.icon.extent.y1 = -64;
+ status_icon.icon.flags =
+ wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED |
+ wimp_ICON_INDIRECTED | wimp_ICON_FILLED |
+ (wimp_BUTTON_NEVER << wimp_ICON_BUTTON_TYPE_SHIFT) |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT);
+ status_icon.icon.data.indirected_text.text = g->status;
+ status_icon.icon.data.indirected_text.validation = "R2;";
+ status_icon.icon.data.indirected_text.size = 255;
+ wimp_create_icon(&status_icon);
+
+ url_icon.w = g->data.browser.toolbar;
+ url_icon.icon.extent.x0 = 0;
+ url_icon.icon.extent.y0 = -64;
+ url_icon.icon.extent.x1 = 4096;
+ url_icon.icon.extent.y1 = 0;
+ url_icon.icon.flags =
+ wimp_ICON_TEXT | wimp_ICON_BORDER | wimp_ICON_VCENTRED |
+ wimp_ICON_INDIRECTED | wimp_ICON_FILLED |
+ (wimp_BUTTON_WRITE_CLICK_DRAG << wimp_ICON_BUTTON_TYPE_SHIFT) |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
+ url_icon.icon.data.indirected_text.text = g->url;
+ url_icon.icon.data.indirected_text.validation = "Pptr_write;";
+ url_icon.icon.data.indirected_text.size = 255;
+ wimp_create_icon(&url_icon);
+ }
+
+ g->redraw_safety = SAFE;
+
+ g->next = netsurf_gui_windows;
+ netsurf_gui_windows = g;
+ return g;
+}
+
+void gui_window_destroy(gui_window* g)
+{
+ if (g == NULL)
+ return;
+
+ if (g == netsurf_gui_windows)
+ netsurf_gui_windows = g->next;
+ else
+ {
+ gui_window* gg;
+ gg = netsurf_gui_windows;
+ while (gg->next != g && gg->next != NULL)
+ gg = gg->next;
+ if (gg->next == g)
+ gg->next = g->next;
+ }
+ xfree(g);
+}
+
+void gui_window_show(gui_window* g)
+{
+ wimp_window_state state;
+ if (g == NULL)
+ return;
+ state.w = g->data.browser.window;
+ wimp_get_window_state(&state);
+ state.next = wimp_TOP;
+ ro_gui_window_open(g, (wimp_open*)&state);
+}
+
+void gui_window_hide(gui_window* g)
+{
+ if (g == NULL)
+ return;
+ wimp_close_window(g->data.browser.window);
+}
+
+void gui_window_redraw(gui_window* g, int x0, int y0, int x1, int y1)
+{
+ if (g == NULL)
+ return;
+
+ wimp_force_redraw(g->data.browser.window,
+ ro_x_units(x0), ro_y_units(y1), ro_x_units(x1), ro_y_units(y0));
+}
+
+void gui_window_redraw_window(gui_window* g)
+{
+ wimp_window_info info;
+ if (g == NULL)
+ return;
+ info.w = g->data.browser.window;
+ wimp_get_window_info_header_only(&info);
+ wimp_force_redraw(g->data.browser.window, info.extent.x0, info.extent.y0, info.extent.x1, info.extent.y1);
+}
+
+gui_safety gui_window_set_redraw_safety(gui_window* g, gui_safety s)
+{
+ gui_safety old;
+
+ if (g == NULL)
+ return SAFE;
+
+ old = g->redraw_safety;
+ g->redraw_safety = s;
+
+ return old;
+}
+
+int select_on = 0;
+
+void ro_gui_window_redraw_box(gui_window* g, struct box * box, signed long x, signed long y, os_box* clip)
+{
+ struct box * c;
+ const char * const noname = "";
+ const char * name = noname;
+ font_f font;
+
+ switch (box->type)
+ {
+ case BOX_TABLE:
+ case BOX_TABLE_ROW:
+ case BOX_TABLE_CELL:
+ case BOX_FLOAT_LEFT:
+ case BOX_FLOAT_RIGHT:
+ case BOX_BLOCK: if (box->node) name = (const char *) box->node->name;
+ break;
+ case BOX_INLINE:
+ case BOX_INLINE_CONTAINER:
+ default:
+ break;
+ }
+
+ if (x + box->x*2 + box->width*2 /* right edge */ >= clip->x0 &&
+ x + box->x*2 /* left edge */ <= clip->x1 &&
+ y - box->y*2 - box->height*2 - 8 /* bottom edge */ <= clip->y1 &&
+ y - box->y*2 /* top edge */ >= clip->y0)
+ {
+
+#ifdef FANCY_LINKS
+ if (box == g->link_box)
+ {
+ colourtrans_set_gcol(os_COLOUR_BLACK, 0, os_ACTION_OVERWRITE, 0);
+ os_plot(os_MOVE_TO, x + box->x * 2, y - box->y * 2 - box->height * 2 - 4);
+ os_plot(os_PLOT_SOLID | os_PLOT_BY, box->width * 2, 0);
+ }
+#endif
+
+ if (box->type == BOX_INLINE)
+ {
+
+ font = riscos_font_css_to_handle(box->style);
+
+if (g->data.browser.bw->current_content->data.html.text_selection.selected == 1)
+{
+ struct box_position* start;
+ struct box_position* end;
+
+ start = &(g->data.browser.bw->current_content->data.html.text_selection.start);
+ end = &(g->data.browser.bw->current_content->data.html.text_selection.end);
+
+ if (start->box == box)
+ {
+ if (end->box == box)
+ {
+ colourtrans_set_gcol(os_COLOUR_VERY_LIGHT_GREY, colourtrans_SET_FG, 0, 0);
+ os_plot(os_MOVE_TO,
+ x + box->x * 2 + start->pixel_offset * 2,
+ y - box->y * 2 - box->height * 2);
+ os_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
+ x + box->x * 2 + end->pixel_offset * 2 - 2,
+ y - box->y * 2 - 2);
+ }
+ else
+ {
+ colourtrans_set_gcol(os_COLOUR_VERY_LIGHT_GREY, colourtrans_SET_FG, 0, 0);
+ os_plot(os_MOVE_TO,
+ x + box->x * 2 + start->pixel_offset * 2,
+ y - box->y * 2 - box->height * 2);
+ os_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
+ x + box->x * 2 + box->width * 2 - 2,
+ y - box->y * 2 - 2);
+ select_on = 1;
+ }
+ }
+ else if (select_on == 1)
+ {
+ if (end->box != box)
+ {
+ colourtrans_set_gcol(os_COLOUR_VERY_LIGHT_GREY, colourtrans_SET_FG, 0, 0);
+ os_plot(os_MOVE_TO,
+ x + box->x * 2,
+ y - box->y * 2 - box->height * 2);
+ os_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
+ x + box->x * 2 + box->width * 2 - 2,
+ y - box->y * 2 - 2);
+ }
+ else
+ {
+ colourtrans_set_gcol(os_COLOUR_VERY_LIGHT_GREY, colourtrans_SET_FG, 0, 0);
+ os_plot(os_MOVE_TO,
+ x + box->x * 2,
+ y - box->y * 2 - box->height * 2);
+ os_plot(os_PLOT_RECTANGLE | os_PLOT_TO,
+ x + box->x * 2 + end->pixel_offset * 2 - 2,
+ y - box->y * 2 - 2);
+ select_on = 0;
+ }
+ }
+}
+
+ font_paint(font, (char*) box->text,
+ font_OS_UNITS | font_GIVEN_LENGTH | font_GIVEN_FONT | font_KERN,
+ x + box->x * 2, y - box->y * 2 - box->height * 2,
+ NULL, NULL,
+ box->length);
+
+ font_lose_font(font);
+
+ }
+ }
+ else
+ {
+ if (g->data.browser.bw->current_content->data.html.text_selection.selected == 1)
+ {
+ struct box_position* start;
+ struct box_position* end;
+
+ start = &(g->data.browser.bw->current_content->data.html.text_selection.start);
+ end = &(g->data.browser.bw->current_content->data.html.text_selection.end);
+
+ if (start->box == box && end->box != box)
+ select_on = 1;
+ else if (select_on == 1 && end->box == box)
+ select_on = 0;
+ }
+ }
+
+ for (c = box->children; c != 0; c = c->next)
+ if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT)
+ ro_gui_window_redraw_box(g, c, x + box->x * 2, y - box->y * 2, clip);
+
+ for (c = box->float_children; c != 0; c = c->next_float)
+ ro_gui_window_redraw_box(g, c, x + box->x * 2, y - box->y * 2, clip);
+}
+
+
+void ro_gui_window_redraw(gui_window* g, wimp_draw* redraw)
+{
+ osbool more;
+
+ if (g->redraw_safety == SAFE && g->type == GUI_BROWSER_WINDOW)
+ {
+ if (g->data.browser.bw->current_content != NULL)
+ {
+ if (g->data.browser.bw->current_content->data.html.layout != NULL)
+ {
+ more = wimp_redraw_window(redraw);
+ wimp_set_font_colours(wimp_COLOUR_WHITE, wimp_COLOUR_BLACK);
+
+ select_on = 0;
+
+ while (more)
+ {
+ ro_gui_window_redraw_box(g,
+ g->data.browser.bw->current_content->data.html.layout->children,
+ redraw->box.x0 - redraw->xscroll, redraw->box.y1 - redraw->yscroll,
+ &redraw->clip);
+ more = wimp_get_rectangle(redraw);
+ }
+ return;
+ }
+ }
+ }
+
+ more = wimp_redraw_window(redraw);
+ while (more)
+ more = wimp_get_rectangle(redraw);
+}
+
+void gui_window_set_scroll(gui_window* g, int sx, int sy)
+{
+ wimp_window_state state;
+ if (g == NULL)
+ return;
+ state.w = g->data.browser.window;
+ wimp_get_window_state(&state);
+ state.xscroll = ro_x_units(sx);
+ state.yscroll = ro_y_units(sy);
+ if ((g->data.browser.bw->flags & browser_TOOLBAR) != 0)
+ state.yscroll += TOOLBAR_HEIGHT;
+ ro_gui_window_open(g, (wimp_open*)&state);
+}
+
+void gui_window_set_extent(gui_window* g, int width, int height)
+{
+ os_box extent;
+
+ if (g == 0)
+ return;
+
+ extent.x0 = 0;
+ extent.y0 = ro_y_units(height);
+ if (extent.y0 > -960)
+ extent.y0 = -960;
+ extent.x1 = ro_x_units(width);
+ if ((g->data.browser.bw->flags & browser_TOOLBAR) != 0)
+ {
+ extent.y1 = TOOLBAR_HEIGHT;
+ }
+ else
+ {
+ extent.y1 = 0;
+ }
+ wimp_set_extent(g->data.browser.window, &extent);
+
+}
+
+void gui_window_set_status(gui_window* g, char* text)
+{
+ if (strcmp(g->status, text) != 0)
+ {
+ strncpy(g->status, text, 255);
+ wimp_set_icon_state(g->data.browser.toolbar, 0, 0, 0);
+ }
+}
+
+void gui_window_message(gui_window* g, gui_message* msg)
+{
+ if (g == NULL || msg == NULL)
+ return;
+
+ switch (msg->type)
+ {
+ case msg_SET_URL:
+ strncpy(g->url, msg->data.set_url.url, 255);
+ wimp_set_icon_state(g->data.browser.toolbar, 1, 0, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+void ro_gui_window_open(gui_window* g, wimp_open* open)
+{
+ wimp_open_window(open);
+
+ if (g->type == GUI_BROWSER_WINDOW)
+ {
+ if ((g->data.browser.bw->flags & browser_TOOLBAR) != 0)
+ {
+ wimp_outline outline;
+ wimp_window_state tstate;
+
+ outline.w = g->data.browser.window;
+ wimp_get_window_outline(&outline);
+
+ tstate.w = g->data.browser.toolbar;
+ tstate.visible.x0 = open->visible.x0;
+ tstate.visible.x1 = outline.outline.x1 - 2;
+ tstate.visible.y1 = open->visible.y1;
+ tstate.visible.y0 = tstate.visible.y1 - TOOLBAR_HEIGHT;
+ tstate.xscroll = 0;
+ tstate.yscroll = 0;
+ tstate.next = wimp_TOP;
+
+ wimp_open_window_nested((wimp_open *) &tstate, g->data.browser.window,
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_LS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_BS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT
+ << wimp_CHILD_RS_EDGE_SHIFT |
+ wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT
+ << wimp_CHILD_TS_EDGE_SHIFT);
+ }
+ }
+}
+
+void ro_gui_icon_bar_click(wimp_pointer* pointer)
+{
+ if (pointer->buttons == wimp_CLICK_SELECT)
+ {
+ struct browser_window* bw;
+ bw = create_browser_window(browser_TITLE | browser_TOOLBAR
+ | browser_SCROLL_X_NONE | browser_SCROLL_Y_ALWAYS, 640, 480);
+ gui_window_show(bw->window);
+ browser_window_open_location(bw, "file:/<NetSurf$Dir>/Resources/intro.html");
+ wimp_set_caret_position(bw->window->data.browser.toolbar, 1,
+ 0,0,-1, strlen(bw->window->url));
+ }
+ else if (pointer->buttons == wimp_CLICK_ADJUST)
+ netsurf_quit = 1;
+}
+
+
+/*** bodge to fix filenames in unixlib. there's probably a proper way
+ of doing this, but 'ck knows what it is. ***/
+extern int __riscosify_control;
+#define __RISCOSIFY_NO_PROCESS 0x0040
+
+void gui_init(int argc, char** argv)
+{
+ wimp_icon_create iconbar;
+ wimp_version_no version;
+
+ __riscosify_control = __RISCOSIFY_NO_PROCESS;
+
+ task_handle = wimp_initialise(wimp_VERSION_RO38, task_name, (wimp_message_list*) &task_messages, &version);
+
+ iconbar.w = wimp_ICON_BAR_RIGHT;
+ iconbar.icon.extent.x0 = 0;
+ iconbar.icon.extent.y0 = 0;
+ iconbar.icon.extent.x1 = 68;
+ iconbar.icon.extent.y1 = 68;
+ iconbar.icon.flags = wimp_ICON_SPRITE | wimp_ICON_HCENTRED
+ | wimp_ICON_VCENTRED | (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT);
+ strcpy(iconbar.icon.data.sprite, "!netsurf");
+ ro_gui_iconbar_i = wimp_create_icon(&iconbar);
+}
+
+gui_window* ro_lookup_gui_from_w(wimp_w window)
+{
+ gui_window* g = netsurf_gui_windows;
+ while (g != NULL)
+ {
+ if (g->type == GUI_BROWSER_WINDOW)
+ {
+ if (g->data.browser.window == window)
+ return g;
+ }
+ g = g->next;
+ }
+ return NULL;
+}
+
+gui_window* ro_lookup_gui_toolbar_from_w(wimp_w window)
+{
+ gui_window* g = netsurf_gui_windows;
+ while (g != NULL)
+ {
+ if (g->type == GUI_BROWSER_WINDOW)
+ {
+ if (g->data.browser.toolbar == window)
+ return g;
+ }
+ g = g->next;
+ }
+ return NULL;
+}
+
+
+struct ro_gui_drag_info
+{
+ enum { draginfo_UNKNOWN, draginfo_NONE, draginfo_BROWSER_TEXT_SELECTION } type;
+ union
+ {
+ struct
+ {
+ gui_window* gui;
+ } selection;
+ } data;
+};
+
+struct ro_gui_drag_info current_drag;
+
+void ro_gui_drag_box(wimp_drag* drag, struct ro_gui_drag_info* drag_info)
+{
+ wimp_drag_box(drag);
+
+ if (drag_info != NULL)
+ memcpy(&current_drag, drag_info, sizeof(struct ro_gui_drag_info));
+ else
+ current_drag.type = draginfo_NONE;
+}
+
+void ro_gui_drag_end(wimp_dragged* drag)
+{
+ if (current_drag.type == draginfo_BROWSER_TEXT_SELECTION)
+ {
+ struct browser_action msg;
+ int final_x0, final_y0;
+ wimp_window_state state;
+
+ state.w = current_drag.data.selection.gui->data.browser.window;
+ wimp_get_window_state(&state);
+
+ final_x0 = browser_x_units(window_x_units(drag->final.x0, &state));
+ final_y0 = browser_y_units(window_y_units(drag->final.y0, &state));
+
+ msg.data.mouse.x = final_x0;
+ msg.data.mouse.y = final_y0;
+ msg.type = act_ALTER_SELECTION;
+ browser_window_action(current_drag.data.selection.gui->data.browser.bw, &msg);
+
+ if (box_position_eq(&(current_drag.data.selection.gui->data.browser.bw->current_content->data.html.text_selection.start),
+ &(current_drag.data.selection.gui->data.browser.bw->current_content->data.html.text_selection.end)))
+ {
+ msg.type = act_CLEAR_SELECTION;
+ browser_window_action(current_drag.data.selection.gui->data.browser.bw, &msg);
+ }
+ current_drag.data.selection.gui->drag_status = drag_NONE;
+ current_drag.data.selection.gui->data.browser.bw->current_content->data.html.text_selection.altering = alter_UNKNOWN;
+ }
+
+ current_drag.type = draginfo_NONE;
+}
+
+void ro_gui_window_mouse_at(wimp_pointer* pointer)
+{
+ int x,y;
+ wimp_window_state state;
+ gui_window* g;
+
+ g = ro_lookup_gui_from_w(pointer->w);
+
+ if (g == NULL)
+ return;
+
+ state.w = pointer->w;
+ wimp_get_window_state(&state);
+
+ x = browser_x_units(window_x_units(pointer->pos.x, &state));
+ y = browser_y_units(window_y_units(pointer->pos.y, &state));
+
+ if (g->drag_status == drag_BROWSER_TEXT_SELECTION)
+ {
+ struct browser_action msg;
+ msg.type = act_ALTER_SELECTION;
+ msg.data.mouse.x = x;
+ msg.data.mouse.y = y;
+ browser_window_action(g->data.browser.bw, &msg);
+ }
+
+ if (g->type == GUI_BROWSER_WINDOW)
+ {
+ if (g->data.browser.bw->current_content != NULL)
+ {
+ struct browser_action msg;
+ msg.type = act_MOUSE_AT;
+ msg.data.mouse.x = x;
+ msg.data.mouse.y = y;
+ browser_window_action(g->data.browser.bw, &msg);
+ }
+ }
+}
+
+void ro_gui_window_click(gui_window* g, wimp_pointer* pointer)
+{
+ struct browser_action msg;
+ int x,y;
+ wimp_window_state state;
+ state.w = pointer->w;
+ wimp_get_window_state(&state);
+
+ if (g->type == GUI_BROWSER_WINDOW)
+ {
+ x = browser_x_units(window_x_units(pointer->pos.x, &state));
+ y = browser_y_units(window_y_units(pointer->pos.y, &state));
+
+ if (g->data.browser.bw->current_content != NULL)
+ {
+ if (g->data.browser.bw->current_content->type == CONTENT_HTML)
+ {
+ if (pointer->buttons == wimp_CLICK_SELECT && g->data.browser.bw->current_content->data.html.text_selection.selected == 1)
+ msg.type = act_CLEAR_SELECTION;
+ else if (pointer->buttons == wimp_CLICK_ADJUST && g->data.browser.bw->current_content->data.html.text_selection.selected == 1)
+ msg.type = act_ALTER_SELECTION;
+ else if (pointer->buttons == wimp_DRAG_SELECT ||
+ pointer->buttons == wimp_DRAG_ADJUST)
+ {
+ wimp_drag drag;
+ struct ro_gui_drag_info drag_info;
+
+ msg.type = act_START_NEW_SELECTION;
+ if (pointer->buttons == wimp_DRAG_ADJUST && g->data.browser.bw->current_content->data.html.text_selection.selected == 1)
+ msg.type = act_ALTER_SELECTION;
+
+ drag.type = wimp_DRAG_USER_POINT;
+ drag.initial.x0 = pointer->pos.x;
+ drag.initial.y0 = pointer->pos.y;
+ drag.initial.x1 = pointer->pos.x;
+ drag.initial.y1 = pointer->pos.y;
+ drag.bbox.x0 = state.visible.x0;
+ drag.bbox.y0 = state.visible.y0;
+ drag.bbox.x1 = state.visible.x1;
+ drag.bbox.y1 = state.visible.y1;
+ drag_info.type = draginfo_BROWSER_TEXT_SELECTION;
+ drag_info.data.selection.gui = g;
+ ro_gui_drag_box(&drag, &drag_info);
+ g->drag_status = drag_BROWSER_TEXT_SELECTION;
+ }
+ msg.data.mouse.x = x;
+ msg.data.mouse.y = y;
+ if (msg.type != act_UNKNOWN)
+ browser_window_action(g->data.browser.bw, &msg);
+
+ if (pointer->buttons == wimp_CLICK_ADJUST && g->data.browser.bw->current_content->data.html.text_selection.selected == 1)
+ {
+ current_drag.data.selection.gui->data.browser.bw->current_content->data.html.text_selection.altering = alter_UNKNOWN;
+ }
+
+ if (pointer->buttons == wimp_CLICK_SELECT
+ || pointer->buttons == wimp_CLICK_ADJUST)
+ {
+ if (pointer->buttons == wimp_CLICK_SELECT)
+ msg.type = act_FOLLOW_LINK;
+ else
+ msg.type = act_FOLLOW_LINK_NEW_WINDOW;
+ msg.data.mouse.x = x;
+ msg.data.mouse.y = y;
+ browser_window_action(g->data.browser.bw, &msg);
+ }
+ }
+ }
+ }
+}
+
+struct ro_gui_poll_block
+{
+ wimp_event_no event;
+ wimp_block* block;
+ struct ro_gui_poll_block* next;
+};
+
+struct ro_gui_poll_block* ro_gui_poll_queued_blocks = NULL;
+
+void ro_gui_poll_queue(wimp_event_no event, wimp_block* block)
+{
+ struct ro_gui_poll_block* q = xcalloc(1, sizeof(struct ro_gui_poll_block));
+
+ q->event = event;
+ q->block = xcalloc(1, sizeof(block));
+ memcpy(q->block, block, sizeof(block));
+ q->next = NULL;
+
+ if (ro_gui_poll_queued_blocks == NULL)
+ {
+ ro_gui_poll_queued_blocks = q;
+ return;
+ }
+ else
+ {
+ struct ro_gui_poll_block* current = ro_gui_poll_queued_blocks;
+ while (current->next != NULL)
+ current = current->next;
+ current->next = q;
+ }
+ return;
+}
+
+void gui_multitask(void)
+{
+ wimp_event_no event;
+ wimp_block block;
+ gui_window* g;
+
+ event = wimp_poll(wimp_QUEUE_KEY |
+ wimp_MASK_LOSE | wimp_MASK_GAIN | wimp_MASK_POLLWORD, &block, 0);
+
+ switch (event)
+ {
+ case wimp_NULL_REASON_CODE:
+ if (over_window != NULL)
+ {
+ wimp_pointer pointer;
+ wimp_get_pointer_info(&pointer);
+ ro_gui_window_mouse_at(&pointer);
+ }
+ break;
+
+ case wimp_REDRAW_WINDOW_REQUEST :
+ g = ro_lookup_gui_from_w(block.redraw.w);
+ if (g != NULL)
+ ro_gui_window_redraw(g, &(block.redraw));
+ break;
+
+ case wimp_OPEN_WINDOW_REQUEST :
+ g = ro_lookup_gui_from_w(block.open.w);
+ if (g != NULL)
+ ro_gui_window_open(g, &(block.open));
+ break;
+
+ case wimp_CLOSE_WINDOW_REQUEST :
+ ro_gui_poll_queue(event, &block);
+ break;
+
+ case wimp_MOUSE_CLICK :
+ if (block.pointer.w == wimp_ICON_BAR)
+ ro_gui_icon_bar_click(&(block.pointer));
+ else
+ {
+ g = ro_lookup_gui_from_w(block.pointer.w);
+ if (g != NULL)
+ {
+ if (g->redraw_safety == SAFE)
+ ro_gui_window_click(g, &(block.pointer));
+ else
+ ro_gui_poll_queue(event, &block);
+ }
+ else
+ ro_gui_poll_queue(event, &block);
+ }
+ break;
+
+ case wimp_POINTER_LEAVING_WINDOW :
+ over_window = NULL;
+ break;
+ case wimp_POINTER_ENTERING_WINDOW :
+ over_window = ro_lookup_gui_from_w(block.leaving.w);
+ break;
+ case wimp_USER_DRAG_BOX :
+ ro_gui_drag_end(&(block.dragged));
+ break;
+ case wimp_MENU_SELECTION :
+ case wimp_USER_MESSAGE :
+ case wimp_USER_MESSAGE_RECORDED :
+ case wimp_USER_MESSAGE_ACKNOWLEDGE:
+ if (block.message.action == message_QUIT)
+ netsurf_quit = 1;
+ else
+ ro_gui_poll_queue(event, &block);
+ break;
+ default:
+ break;
+ }
+
+}
+
+void ro_gui_keypress(wimp_key* key)
+{
+ gui_window* g;
+
+ if (key == NULL)
+ return;
+
+ g = ro_lookup_gui_toolbar_from_w(key->w);
+ if (g != NULL)
+ {
+ if (key->c == wimp_KEY_RETURN)
+ {
+ if (g->data.browser.bw->url != NULL)
+ {
+ xfree(g->data.browser.bw->url);
+ g->data.browser.bw->url = NULL;
+ }
+ browser_window_open_location(g->data.browser.bw, g->url);
+ return;
+ }
+ }
+ wimp_process_key(key->c);
+ return;
+}
+
+void gui_poll(void)
+{
+ wimp_event_no event;
+ wimp_block block;
+ gui_window* g;
+ int finished = 0;
+
+ do
+ {
+ if (ro_gui_poll_queued_blocks == NULL)
+ {
+ event = wimp_poll(0, &block, 0);
+ finished = 1;
+ }
+ else
+ {
+ struct ro_gui_poll_block* next;
+ event = ro_gui_poll_queued_blocks->event;
+ memcpy(&block, ro_gui_poll_queued_blocks->block, sizeof(block));
+ next = ro_gui_poll_queued_blocks->next;
+ xfree(ro_gui_poll_queued_blocks->block);
+ xfree(ro_gui_poll_queued_blocks);
+ ro_gui_poll_queued_blocks = next;
+ finished = 0;
+ }
+ switch (event)
+ {
+ case wimp_NULL_REASON_CODE :
+ if (over_window != NULL
+ || current_drag.type == draginfo_BROWSER_TEXT_SELECTION)
+ {
+ wimp_pointer pointer;
+ wimp_get_pointer_info(&pointer);
+ ro_gui_window_mouse_at(&pointer);
+ }
+ break;
+
+ case wimp_REDRAW_WINDOW_REQUEST :
+ g = ro_lookup_gui_from_w(block.redraw.w);
+ if (g != NULL)
+ ro_gui_window_redraw(g, &(block.redraw));
+ break;
+
+ case wimp_OPEN_WINDOW_REQUEST :
+ g = ro_lookup_gui_from_w(block.open.w);
+ if (g != NULL)
+ ro_gui_window_open(g, &(block.open));
+ break;
+
+ case wimp_CLOSE_WINDOW_REQUEST :
+ g = ro_lookup_gui_from_w(block.close.w);
+ if (g != NULL)
+ gui_window_hide(g);
+ break;
+
+ case wimp_POINTER_LEAVING_WINDOW :
+ g = ro_lookup_gui_from_w(block.leaving.w);
+ if (g == over_window)
+ over_window = NULL;
+ break;
+
+ case wimp_POINTER_ENTERING_WINDOW :
+ g = ro_lookup_gui_from_w(block.entering.w);
+ if (g != NULL)
+ over_window = g;
+ break;
+
+ case wimp_MOUSE_CLICK :
+ if (block.pointer.w == wimp_ICON_BAR)
+ ro_gui_icon_bar_click(&(block.pointer));
+ else
+ {
+ g = ro_lookup_gui_from_w(block.pointer.w);
+ if (g != NULL)
+ ro_gui_window_click(g, &(block.pointer));
+ }
+ break;
+
+ case wimp_USER_DRAG_BOX :
+ ro_gui_drag_end(&(block.dragged));
+ break;
+
+ case wimp_KEY_PRESSED :
+ ro_gui_keypress(&(block.key));
+ break;
+
+ case wimp_MENU_SELECTION :
+ break;
+
+ case wimp_LOSE_CARET :
+ break;
+ case wimp_GAIN_CARET :
+ break;
+
+ case wimp_USER_MESSAGE :
+ case wimp_USER_MESSAGE_RECORDED :
+ case wimp_USER_MESSAGE_ACKNOWLEDGE:
+ if (block.message.action == message_QUIT)
+ netsurf_quit = 1;
+ break;
+ }
+ } while (finished == 0);
+
+ return;
+}
+
+int gui_file_to_filename(char* location, char* actual_filename, int size)
+{
+ char* current;
+ int count = 0;
+
+ if (strspn(location, "file:/") != strlen("file:/"))
+ return -1;
+
+ current = location + strlen("file:/");
+ while (*current != '\0' && count < size - 1)
+ {
+ if (strspn(current, "..") == 2)
+ {
+ if (actual_filename != NULL)
+ actual_filename[count] = '^';
+ count++;
+ current += 2;
+ }
+ if (*current == '/')
+ {
+ if (actual_filename != NULL)
+ actual_filename[count] = '.';
+ count++;
+ current += 1;
+ }
+ else if (*current == '.')
+ {
+ if (actual_filename != NULL)
+ actual_filename[count] = '/';
+ count++;
+ current += 1;
+ }
+ else
+ {
+ if (actual_filename != NULL)
+ actual_filename[count] = *current;
+ count++;
+ current += 1;
+ }
+ }
+
+ if (actual_filename != NULL)
+ actual_filename[count] = '\0';
+
+ return count + 1;
+}
+
diff --git a/riscos/gui.h b/riscos/gui.h
new file mode 100644
index 000000000..c7644623d
--- /dev/null
+++ b/riscos/gui.h
@@ -0,0 +1,47 @@
+/**
+ * $Id: gui.h,v 1.1 2002/09/11 14:24:02 monkeyson Exp $
+ */
+
+#ifndef _NETSURF_RISCOS_GUI_H_
+#define _NETSURF_RISCOS_GUI_H_
+
+#include "oslib/wimp.h"
+
+struct ro_gui_window;
+typedef struct ro_gui_window gui_window;
+
+ int ro_x_units (int browser_units);
+ int ro_y_units (int browser_units);
+ int browser_x_units (int ro_units) ;
+ int browser_y_units (int ro_units) ;
+
+struct ro_gui_window
+{
+ gui_window_type type;
+
+ union {
+ struct {
+ wimp_w window;
+ wimp_w toolbar;
+ struct browser_window* bw;
+ } browser;
+ } data;
+
+ char status[256];
+ char title[256];
+ char url[256];
+ gui_window* next;
+
+ gui_safety redraw_safety;
+ enum { drag_NONE, drag_UNKNOWN, drag_BROWSER_TEXT_SELECTION } drag_status;
+};
+
+#include "netsurf/desktop/browser.h"
+
+void ro_gui_window_click(gui_window* g, wimp_pointer* mouse);
+//void ro_gui_window_mouse_at(gui_window* g, wimp_pointer* mouse);
+void ro_gui_window_open(gui_window* g, wimp_open* open);
+void ro_gui_window_redraw(gui_window* g, wimp_draw* redraw);
+//void ro_gui_window_keypress(gui_window* g, wimp_key* key);
+
+#endif
diff --git a/utils/utils.c b/utils/utils.c
index ffdf029ae..923c16e26 100644
--- a/utils/utils.c
+++ b/utils/utils.c
@@ -1,5 +1,5 @@
/**
- * $Id: utils.c,v 1.4 2002/06/21 18:16:24 bursa Exp $
+ * $Id: utils.c,v 1.5 2002/09/11 14:24:02 monkeyson Exp $
*/
#include <ctype.h>
@@ -46,6 +46,14 @@ void * xrealloc(void * p, const size_t size)
return p;
}
+void xfree(void* p)
+{
+ if (p == 0)
+ fprintf(stderr, "Attempt to free NULL pointer\n");
+ else
+ free(p);
+}
+
char * xstrdup(const char * const s)
{
char * c = malloc(strlen(s) + 1);