[project @ 2003-09-22 21:55:08 by bursa]
Experimental textarea editing code. svn path=/import/netsurf/; revision=309
This commit is contained in:
parent
84dd766141
commit
287986b28a
|
@ -45,6 +45,13 @@ static int browser_window_gadget_click(struct browser_window* bw, unsigned long
|
|||
static void browser_form_submit(struct browser_window *bw, struct form *form);
|
||||
static char* browser_form_construct_get(struct page_elements *elements, struct formsubmit* fs);
|
||||
static void browser_form_get_append(char **s, int *length, char sep, char *name, char *value);
|
||||
static void browser_window_textarea_click(struct browser_window* bw,
|
||||
unsigned long actual_x, unsigned long actual_y,
|
||||
unsigned long x, unsigned long y,
|
||||
struct box *box);
|
||||
static void browser_window_textarea_callback(struct browser_window *bw, char key, void *p);
|
||||
static void browser_window_place_caret(struct browser_window *bw, int x, int y,
|
||||
int height, void (*callback)(struct browser_window *bw, char key, void *p), void *p);
|
||||
|
||||
|
||||
void browser_window_start_throbber(struct browser_window* bw)
|
||||
|
@ -167,6 +174,7 @@ struct browser_window* create_browser_window(int flags, int width, int height)
|
|||
bw->history = NULL;
|
||||
|
||||
bw->url = NULL;
|
||||
bw->caret_callback = 0;
|
||||
|
||||
bw->window = gui_create_browser_window(bw);
|
||||
|
||||
|
@ -323,6 +331,7 @@ void browser_window_callback(content_msg msg, struct content *c,
|
|||
}
|
||||
bw->current_content = c;
|
||||
bw->loading_content = 0;
|
||||
bw->caret_callback = 0;
|
||||
}
|
||||
gui_window_set_redraw_safety(bw->window, previous_safety);
|
||||
if (bw->current_content->status == CONTENT_STATUS_DONE) {
|
||||
|
@ -493,7 +502,7 @@ int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x
|
|||
|
||||
for (i = found - 1; i >= 0; i--)
|
||||
{
|
||||
if (click_boxes[i].box->type == BOX_INLINE && click_boxes[i].box->gadget != 0)
|
||||
if (click_boxes[i].box->gadget)
|
||||
{
|
||||
struct gui_gadget* g = click_boxes[i].box->gadget;
|
||||
|
||||
|
@ -522,7 +531,12 @@ int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x
|
|||
gui_redraw_gadget(bw,g);
|
||||
break;
|
||||
case GADGET_TEXTAREA:
|
||||
gui_edit_textarea(bw, g);
|
||||
browser_window_textarea_click(bw,
|
||||
click_boxes[i].actual_x,
|
||||
click_boxes[i].actual_y,
|
||||
click_x - click_boxes[i].actual_x,
|
||||
click_y - click_boxes[i].actual_y,
|
||||
click_boxes[i].box);
|
||||
break;
|
||||
case GADGET_TEXTBOX:
|
||||
gui_edit_textbox(bw, g);
|
||||
|
@ -548,6 +562,156 @@ int browser_window_gadget_click(struct browser_window* bw, unsigned long click_x
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle clicks in a text area by placing the caret.
|
||||
*/
|
||||
|
||||
void browser_window_textarea_click(struct browser_window* bw,
|
||||
unsigned long actual_x, unsigned long actual_y,
|
||||
unsigned long x, unsigned long y,
|
||||
struct box *textarea)
|
||||
{
|
||||
/* a textarea contains one or more inline containers, which contain
|
||||
* the formatted paragraphs of text as inline boxes */
|
||||
|
||||
int char_offset, pixel_offset;
|
||||
struct box *inline_container, *text_box;
|
||||
|
||||
for (inline_container = textarea->children;
|
||||
inline_container && inline_container->y + inline_container->height < y;
|
||||
inline_container = inline_container->next)
|
||||
;
|
||||
if (!inline_container) {
|
||||
/* below the bottom of the textarea: place caret at end */
|
||||
inline_container = textarea->last;
|
||||
text_box = inline_container->last;
|
||||
assert(text_box->type == BOX_INLINE);
|
||||
assert(text_box->text && text_box->font);
|
||||
font_position_in_string(text_box->text, text_box->font,
|
||||
text_box->length, textarea->width,
|
||||
&char_offset, &pixel_offset);
|
||||
} else {
|
||||
/* find the relevant text box */
|
||||
y -= inline_container->y;
|
||||
for (text_box = inline_container->children;
|
||||
text_box && (text_box->y + text_box->height < y ||
|
||||
text_box->x + text_box->width < x);
|
||||
text_box = text_box->next)
|
||||
;
|
||||
if (!text_box) {
|
||||
/* past last text box */
|
||||
text_box = inline_container->last;
|
||||
assert(text_box->type == BOX_INLINE);
|
||||
assert(text_box->text && text_box->font);
|
||||
font_position_in_string(text_box->text, text_box->font,
|
||||
text_box->length, textarea->width,
|
||||
&char_offset, &pixel_offset);
|
||||
} else {
|
||||
/* in a text box */
|
||||
assert(text_box->type == BOX_INLINE);
|
||||
assert(text_box->text && text_box->font);
|
||||
font_position_in_string(text_box->text, text_box->font,
|
||||
text_box->length, x - text_box->x,
|
||||
&char_offset, &pixel_offset);
|
||||
}
|
||||
}
|
||||
textarea->gadget->data.textarea.caret_inline_container = inline_container;
|
||||
textarea->gadget->data.textarea.caret_text_box = text_box;
|
||||
textarea->gadget->data.textarea.caret_char_offset = char_offset;
|
||||
browser_window_place_caret(bw, actual_x + text_box->x + pixel_offset,
|
||||
actual_y + inline_container->y + text_box->y,
|
||||
text_box->height,
|
||||
browser_window_textarea_callback, textarea);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Key press callback for text areas.
|
||||
*/
|
||||
|
||||
void browser_window_textarea_callback(struct browser_window *bw, char key, void *p)
|
||||
{
|
||||
struct box *textarea = p;
|
||||
struct box *inline_container = textarea->gadget->data.textarea.caret_inline_container;
|
||||
struct box *text_box = textarea->gadget->data.textarea.caret_text_box;
|
||||
int char_offset = textarea->gadget->data.textarea.caret_char_offset;
|
||||
int pixel_offset;
|
||||
unsigned long actual_x, actual_y;
|
||||
unsigned long width, height;
|
||||
|
||||
box_coords(textarea, &actual_x, &actual_y);
|
||||
|
||||
if (32 <= key && key != 127) {
|
||||
/* normal character insertion */
|
||||
text_box->text = xrealloc(text_box->text, text_box->length + 2);
|
||||
memmove(text_box->text + char_offset + 1,
|
||||
text_box->text + char_offset,
|
||||
text_box->length - char_offset);
|
||||
text_box->text[char_offset] = key;
|
||||
text_box->length++;
|
||||
text_box->text[text_box->length] = 0;
|
||||
text_box->width = UNKNOWN_WIDTH;
|
||||
char_offset++;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* reflow textarea preserving width and height */
|
||||
width = textarea->width;
|
||||
height = textarea->height;
|
||||
layout_block(textarea, textarea->parent->width, textarea, 0, 0);
|
||||
textarea->width = width;
|
||||
textarea->height = height;
|
||||
|
||||
if (text_box->length < char_offset) {
|
||||
/* the text box has been split and the caret is in the second part */
|
||||
char_offset -= text_box->length;
|
||||
text_box = text_box->next;
|
||||
}
|
||||
|
||||
pixel_offset = font_width(text_box->font, text_box->text, char_offset);
|
||||
|
||||
textarea->gadget->data.textarea.caret_text_box = text_box;
|
||||
textarea->gadget->data.textarea.caret_char_offset = char_offset;
|
||||
browser_window_place_caret(bw, actual_x + text_box->x + pixel_offset,
|
||||
actual_y + inline_container->y + text_box->y,
|
||||
text_box->height,
|
||||
browser_window_textarea_callback, textarea);
|
||||
|
||||
gui_window_redraw(bw->window,
|
||||
actual_x,
|
||||
actual_y + inline_container->y,
|
||||
actual_x + width,
|
||||
actual_y + height);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Position the caret and assign a callback for key presses.
|
||||
*/
|
||||
|
||||
void browser_window_place_caret(struct browser_window *bw, int x, int y,
|
||||
int height, void (*callback)(struct browser_window *bw, char key, void *p), void *p)
|
||||
{
|
||||
gui_window_place_caret(bw->window, x, y, height);
|
||||
bw->caret_callback = callback;
|
||||
bw->caret_p = p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle key presses in a browser window.
|
||||
*/
|
||||
|
||||
void browser_window_key_press(struct browser_window *bw, char key)
|
||||
{
|
||||
if (!bw->caret_callback)
|
||||
return;
|
||||
bw->caret_callback(bw, key, bw->caret_p);
|
||||
}
|
||||
|
||||
|
||||
int browser_window_action(struct browser_window* bw, struct browser_action* act)
|
||||
{
|
||||
switch (act->type)
|
||||
|
@ -1062,7 +1226,7 @@ char* browser_form_construct_get(struct page_elements *elements, struct formsubm
|
|||
opt = opt->next;
|
||||
}
|
||||
break;
|
||||
case GADGET_TEXTAREA: value = elements->gadgets[i]->data.textarea.text;
|
||||
case GADGET_TEXTAREA: /* TODO */
|
||||
break;
|
||||
case GADGET_IMAGE: sprintf(elements->gadgets[i]->data.image.name,
|
||||
"%s.x",
|
||||
|
|
|
@ -59,6 +59,9 @@ struct browser_window
|
|||
gui_window* window;
|
||||
|
||||
int throbbing;
|
||||
|
||||
void (*caret_callback)(struct browser_window *bw, char key, void *p);
|
||||
void *caret_p;
|
||||
};
|
||||
|
||||
|
||||
|
@ -116,4 +119,6 @@ void gui_redraw_gadget(struct browser_window* bw, struct gui_gadget* g);
|
|||
void browser_window_stop_throbber(struct browser_window* bw);
|
||||
void browser_window_reformat(struct browser_window* bw, int scroll_to_top);
|
||||
|
||||
void browser_window_key_press(struct browser_window *bw, char key);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -60,7 +60,8 @@ void gui_window_stop_throbber(gui_window* g);
|
|||
|
||||
void gui_gadget_combo(struct browser_window* bw, struct gui_gadget* g, unsigned long mx, unsigned long my);
|
||||
void gui_edit_textarea(struct browser_window* bw, struct gui_gadget* g);
|
||||
void gui_edit_textbox(struct browser_window* bw, struct gui_gadget* g);
|
||||
void gui_edit_password(struct browser_window* bw, struct gui_gadget* g);
|
||||
|
||||
void gui_window_place_caret(gui_window *g, int x, int y, int height);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -709,8 +709,7 @@ struct result box_textarea(xmlNode *n, struct status *status,
|
|||
/* split the content at newlines and make an inline container with an
|
||||
* inline box for each line */
|
||||
current = content = xmlNodeGetContent(n);
|
||||
current += strspn(current, "\r\n"); /* skip any initial CR, LF */
|
||||
while (*current) {
|
||||
do {
|
||||
size_t len = strcspn(current, "\r\n");
|
||||
char old = current[len];
|
||||
current[len] = 0;
|
||||
|
@ -727,7 +726,7 @@ struct result box_textarea(xmlNode *n, struct status *status,
|
|||
current[len] = old;
|
||||
current += len;
|
||||
current += strspn(current, "\r\n");
|
||||
}
|
||||
} while (*current);
|
||||
xmlFree(content);
|
||||
|
||||
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name")))
|
||||
|
@ -1444,8 +1443,6 @@ void gadget_free(struct gui_gadget* g)
|
|||
xmlFree(g->data.checkbox.value);
|
||||
break;
|
||||
case GADGET_TEXTAREA:
|
||||
if (g->data.textarea.text != 0)
|
||||
xmlFree(g->data.textarea.text);
|
||||
break;
|
||||
case GADGET_TEXTBOX:
|
||||
gui_remove_gadget(g);
|
||||
|
|
|
@ -39,6 +39,8 @@ struct formoption {
|
|||
struct formoption* next;
|
||||
};
|
||||
|
||||
struct box;
|
||||
|
||||
struct gui_gadget {
|
||||
enum { GADGET_HIDDEN = 0, GADGET_TEXTBOX, GADGET_RADIO, GADGET_CHECKBOX,
|
||||
GADGET_SELECT, GADGET_TEXTAREA, GADGET_ACTIONBUTTON,
|
||||
|
@ -86,9 +88,9 @@ struct gui_gadget {
|
|||
char* value;
|
||||
} radio;
|
||||
struct {
|
||||
int cols;
|
||||
int rows;
|
||||
char* text;
|
||||
struct box *caret_inline_container;
|
||||
struct box *caret_text_box;
|
||||
int caret_char_offset;
|
||||
} textarea;
|
||||
} data;
|
||||
};
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
static void layout_node(struct box * box, unsigned long width, struct box * cont,
|
||||
unsigned long cx, unsigned long cy);
|
||||
static void layout_block(struct box * box, unsigned long width, struct box * cont,
|
||||
unsigned long cx, unsigned long cy);
|
||||
static unsigned long layout_block_children(struct box * box, unsigned long width, struct box * cont,
|
||||
unsigned long cx, unsigned long cy);
|
||||
static void find_sides(struct box * fl, unsigned long y0, unsigned long y1,
|
||||
|
|
|
@ -13,5 +13,7 @@
|
|||
*/
|
||||
|
||||
void layout_document(struct box * box, unsigned long width);
|
||||
void layout_block(struct box * box, unsigned long width, struct box * cont,
|
||||
unsigned long cx, unsigned long cy);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,7 +61,7 @@ unsigned long font_width(struct font_data *font, const char * text, unsigned int
|
|||
0, &width, 0, 0);
|
||||
if (error != 0) {
|
||||
fprintf(stderr, "%s\n", error->errmess);
|
||||
die("font_scan_string failed");
|
||||
die("font_width: font_scan_string failed");
|
||||
}
|
||||
|
||||
return width / 800;
|
||||
|
@ -212,7 +212,7 @@ char * font_split(struct font_data *data, const char * text, unsigned int length
|
|||
used_width, 0, 0);
|
||||
if (error != 0) {
|
||||
fprintf(stderr, "%s\n", error->errmess);
|
||||
die("font_scan_string failed");
|
||||
die("font_split: font_scan_string failed");
|
||||
}
|
||||
|
||||
*used_width = browser_x_units(*used_width / 400);
|
||||
|
|
30
riscos/gui.c
30
riscos/gui.c
|
@ -1368,8 +1368,13 @@ void ro_gui_keypress(wimp_key* key)
|
|||
{
|
||||
gui_window* g;
|
||||
|
||||
if (key == NULL)
|
||||
return;
|
||||
if (key->i == -1 && key->c < 256) {
|
||||
g = ro_lookup_gui_from_w(key->w);
|
||||
if (g) {
|
||||
browser_window_key_press(g->data.browser.bw, (char) key->c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g = ro_lookup_gui_toolbar_from_w(key->w);
|
||||
if (g != NULL)
|
||||
|
@ -1686,20 +1691,10 @@ void gui_gadget_combo(struct browser_window* bw, struct gui_gadget* g, unsigned
|
|||
ro_gui_create_menu(combo_menu, pointer.pos.x - 64, pointer.pos.y, bw->window);
|
||||
}
|
||||
|
||||
void gui_edit_textarea(struct browser_window* bw, struct gui_gadget* g)
|
||||
void gui_window_place_caret(gui_window *g, int x, int y, int height)
|
||||
{
|
||||
FILE* file;
|
||||
|
||||
xosfile_create_dir("<Wimp$ScrapDir>.WWW", 77);
|
||||
xosfile_create_dir("<Wimp$ScrapDir>.WWW.NetSurf", 77);
|
||||
file = fopen("<Wimp$ScrapDir>/WWW/NetSurf/TextArea", "w");
|
||||
if (g->data.textarea.text != 0)
|
||||
fprintf(file, "%s", g->data.textarea.text);
|
||||
fprintf(stderr, "closing file.\n");
|
||||
fclose(file);
|
||||
|
||||
xosfile_set_type("<Wimp$ScrapDir>.WWW.NetSurf.TextArea", osfile_TYPE_TEXT);
|
||||
xos_cli("filer_run <Wimp$ScrapDir>.WWW.NetSurf.TextArea");
|
||||
wimp_set_caret_position(g->data.browser.window, -1,
|
||||
x * 2, -(y + height) * 2, height * 2, -1);
|
||||
}
|
||||
|
||||
void ro_msg_datasave(wimp_message* block)
|
||||
|
@ -1799,10 +1794,7 @@ void ro_msg_dataload(wimp_message* block)
|
|||
if (click_boxes[i].box->gadget->type == GADGET_TEXTAREA && data->file_type == 0xFFF)
|
||||
{
|
||||
/* load the text in! */
|
||||
if (click_boxes[i].box->gadget->data.textarea.text != 0)
|
||||
xfree(click_boxes[i].box->gadget->data.textarea.text);
|
||||
click_boxes[i].box->gadget->data.textarea.text = load(data->file_name);
|
||||
gui_redraw_gadget(bw, click_boxes[i].box->gadget);
|
||||
/* TODO */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,19 +137,6 @@ void html_redraw_box(struct content *content, struct box * box,
|
|||
icon.extent.y1 = -gadget_subtract_y + y;
|
||||
|
||||
switch (box->gadget->type) {
|
||||
case GADGET_TEXTAREA:
|
||||
icon.flags = wimp_ICON_TEXT | wimp_ICON_BORDER |
|
||||
wimp_ICON_VCENTRED | wimp_ICON_FILLED |
|
||||
wimp_ICON_INDIRECTED |
|
||||
(wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
|
||||
(wimp_COLOUR_WHITE << wimp_ICON_BG_COLOUR_SHIFT);
|
||||
icon.data.indirected_text.text = box->gadget->data.textarea.text;
|
||||
icon.data.indirected_text.size = strlen(box->gadget->data.textarea.text);
|
||||
icon.data.indirected_text.validation = validation_textarea;
|
||||
LOG(("writing GADGET TEXTAREA"));
|
||||
wimp_plot_icon(&icon);
|
||||
break;
|
||||
|
||||
case GADGET_TEXTBOX:
|
||||
colourtrans_set_font_colours(box->font->handle, current_background_color << 8,
|
||||
box->style->color << 8, 14, 0, 0, 0);
|
||||
|
|
Loading…
Reference in New Issue