1 /* view_gr.c
2 * (c) 2002 Mikulas Patocka
3 * This file is a part of the Links program, released under GPL.
4 */
5
6 #include "cfg.h"
7
8 #ifdef G
9
10 #include "links.h"
11
12 static int *highlight_positions = NULL;
13 static int *highlight_lengths = NULL;
14 static int n_highlight_positions = 0;
15
16 static int root_x = 0;
17 static int root_y = 0;
18
19 static void get_object_pos(struct g_object *o, int *x, int *y);
20 static void g_get_search_data(struct f_data *f);
21 static struct g_object_text * g_find_nearest_object(struct f_data *f, int x, int y);
22
23 static int previous_link=-1; /* for mouse event handlers */
24
g_dummy_draw(struct f_data_c * fd,struct g_object * t,int x,int y)25 void g_dummy_draw(struct f_data_c *fd, struct g_object *t, int x, int y)
26 {
27 }
28
g_tag_destruct(struct g_object * t_)29 void g_tag_destruct(struct g_object *t_)
30 {
31 struct g_object_tag *t = get_struct(t_, struct g_object_tag, go);
32 mem_free(t);
33 }
34
g_dummy_mouse(struct f_data_c * fd,struct g_object * a,int x,int y,int b)35 void g_dummy_mouse(struct f_data_c *fd, struct g_object *a, int x, int y, int b)
36 {
37 }
38
39 static unsigned char print_all_textarea = 0;
40
41
42 /* returns byte index of x in t->text */
43 /* x is relative coordinate within the text (can be out of bounds) */
g_find_text_pos(struct g_object_text * t,int x)44 static int g_find_text_pos(struct g_object_text *t, int x)
45 {
46 int i=0, p=0;
47 unsigned char *text=t->text;
48 int ox, oy;
49
50 get_object_pos(&t->goti.go, &ox, &oy);
51 x -= ox;
52
53 if (x < 0) x = 0;
54 if (x > t->goti.go.xw) x = t->goti.go.xw;
55
56 while (1) {
57 unsigned c;
58 unsigned char *old_text;
59 int w;
60
61 old_text = text;
62 if (!*text) break;
63 GET_UTF_8(text, c);
64 w = g_char_width(t->style, c);
65 if (x < (p + (w >> 1))) break;
66 p += w;
67 i += (int)(text - old_text);
68 if (p >= x) break;
69 }
70 return i;
71 }
72
g_text_no_search(struct f_data * f,struct g_object_text * t)73 static int g_text_no_search(struct f_data *f, struct g_object_text *t)
74 {
75 struct link *l;
76 if (t->goti.link_num < 0) return 0;
77 l = f->links + t->goti.link_num;
78 if (l->type == L_SELECT || l->type == L_FIELD || l->type == L_AREA) return 1;
79 return 0;
80 }
81
prepare_input_field_char(unsigned char * p,unsigned char tx[7])82 static int prepare_input_field_char(unsigned char *p, unsigned char tx[7])
83 {
84 unsigned char *pp = p;
85 unsigned un;
86 unsigned char *en;
87 GET_UTF_8(p, un);
88 if (!un) un = '*';
89 if (un == 0xad) un = '-';
90 en = encode_utf_8(un);
91 strcpy(cast_char tx, cast_const_char en);
92 return (int)(p - pp);
93 }
94
g_text_draw(struct f_data_c * fd,struct g_object * t_,int x,int y)95 void g_text_draw(struct f_data_c *fd, struct g_object *t_, int x, int y)
96 {
97 struct g_object_text *t = get_struct(t_, struct g_object_text, goti.go);
98 struct form_control *form;
99 struct form_state *fs;
100 struct link *link;
101 int l;
102 int ll;
103 int i, j;
104 int yy;
105 int cur;
106 struct format_text_cache_entry *ftce;
107 struct graphics_device *dev = fd->ses->term->dev;
108
109 if (x + t->goti.go.xw <= fd->ses->term->dev->clip.x1)
110 return;
111 if (x >= fd->ses->term->dev->clip.x2)
112 return;
113 if (!print_all_textarea) {
114 if (y + t->goti.go.yw <= fd->ses->term->dev->clip.y1)
115 return;
116 if (y >= fd->ses->term->dev->clip.y2)
117 return;
118 }
119
120 link = t->goti.link_num >= 0 ? fd->f_data->links + t->goti.link_num : NULL;
121 if (link && ((form = link->form))) {
122 fs = find_form_state(fd, form);
123 switch (form->type) {
124 struct style *inv;
125 int in, lid;
126 int sl, td;
127 case FC_RADIO:
128 if (link && fd->active && fd->vs->g_display_link && fd->vs->current_link == link - fd->f_data->links) inv = g_invert_style(t->style), in = 1;
129 else inv = t->style, in = 0;
130 g_print_text(dev, x, y, inv, fs->state ? cast_uchar "[X]" : cast_uchar "[ ]", NULL);
131 if (in) g_free_style(inv);
132 return;
133 case FC_CHECKBOX:
134 if (link && fd->active && fd->vs->g_display_link && fd->vs->current_link == link - fd->f_data->links) inv = g_invert_style(t->style), in = 1;
135 else inv = t->style, in = 0;
136 g_print_text(dev, x, y, inv, fs->state ? cast_uchar "[X]" : cast_uchar "[ ]", NULL);
137 if (in) g_free_style(inv);
138 return;
139 case FC_SELECT:
140 if (link && fd->active && fd->vs->g_display_link && fd->vs->current_link == link - fd->f_data->links) inv = g_invert_style(t->style), in = 1;
141 else inv = t->style, in = 0;
142 fixup_select_state(form, fs);
143 l = 0;
144 if (fs->state < form->nvalues) g_print_text(dev, x, y, inv, form->labels[fs->state], &l);
145 while (l < t->goti.go.xw) g_print_text(dev, x + l, y, inv, cast_uchar "_", &l);
146 if (in) g_free_style(inv);
147 return;
148 case FC_TEXT:
149 case FC_PASSWORD:
150 case FC_FILE_UPLOAD:
151 if ((size_t)fs->vpos > strlen(cast_const_char fs->string)) fs->vpos = (int)strlen(cast_const_char fs->string);
152 sl = (int)strlen(cast_const_char fs->string);
153 td = textptr_diff(fs->string + fs->state, fs->string + fs->vpos, fd->f_data->opt.cp);
154 while (fs->vpos < sl && td >= form->size) {
155 unsigned char *p = fs->string + fs->vpos;
156 FWD_UTF_8(p);
157 fs->vpos = (int)(p - fs->string);
158 td--;
159 }
160 while (fs->vpos > fs->state) {
161 unsigned char *p = fs->string + fs->vpos;
162 BACK_UTF_8(p, fs->string);
163 fs->vpos = (int)(p - fs->string);
164 }
165 l = 0;
166 i = 0;
167 ll = (int)strlen(cast_const_char fs->string);
168 while (l < t->goti.go.xw) {
169 struct style *st = t->style;
170 int sm = 0;
171 unsigned char tx[7];
172 if (fs->state == fs->vpos + i && t->goti.link_num == fd->vs->current_link && fd->ses->locked_link) {
173 st = g_invert_style(t->style);
174 sm = 1;
175 }
176 if (fs->vpos + i >= ll) {
177 tx[0] = '_', tx[1] = 0, i++;
178 } else {
179 i += prepare_input_field_char(fs->string + fs->vpos + i, tx);
180 if (form->type == FC_PASSWORD) tx[0] = '*', tx[1] = 0;
181 }
182 g_print_text(dev, x + l, y, st, tx, &l);
183 if (sm) g_free_style(st);
184 }
185 return;
186 case FC_TEXTAREA:
187 cur = area_cursor(fd, form, fs);
188 ftce = format_text(fd, form, fs);
189
190 yy = y - t->goti.link_order * t->style->height;
191 lid = fs->vypos;
192 for (j = 0; j < form->rows; j++) {
193 unsigned char *pp, *en;
194 int remaining_chars;
195 int xx = fs->vpos;
196 if (lid < ftce->n_lines) {
197 pp = fs->string + ftce->ln[lid].st_offs;
198 en = fs->string + ftce->ln[lid].en_offs;
199 remaining_chars = ftce->ln[lid].chars;
200 } else {
201 pp = en = NULL;
202 remaining_chars = 0;
203 }
204 while (pp && pp < en && xx > 0) {
205 FWD_UTF_8(pp);
206 xx--;
207 remaining_chars--;
208 }
209 if (cur >= 0 && cur < form->cols && t->goti.link_num == fd->vs->current_link && fd->ses->locked_link && fd->active) {
210 unsigned char tx[7];
211 int xx = x;
212
213 if (print_all_textarea || j == t->goti.link_order) while (xx < x + t->goti.go.xw) {
214 struct style *st = t->style;
215 if (pp && pp < en) {
216 pp += prepare_input_field_char(pp, tx);
217 } else {
218 tx[0] = '_';
219 tx[1] = 0;
220 }
221 if (!cur) {
222 st = g_invert_style(t->style);
223 }
224 g_print_text(dev, xx, yy + j * t->style->height, st, tx, &xx);
225 if (!cur) {
226 g_free_style(st);
227 }
228 cur--;
229 } else cur -= form->cols;
230 } else {
231 if (print_all_textarea || j == t->goti.link_order) {
232 unsigned char *a;
233 struct rect old;
234 size_t text_size;
235 if (remaining_chars <= form->cols)
236 remaining_chars = form->cols - remaining_chars;
237 else
238 remaining_chars = 0;
239 text_size = pp ? en - pp : 0;
240 a = mem_alloc(text_size + remaining_chars + 1);
241 if (text_size) memcpy(a, pp, text_size);
242 memset(a + text_size, '_', remaining_chars);
243 a[text_size + remaining_chars] = 0;
244 restrict_clip_area(dev, &old, x, 0, x + t->goti.go.xw, dev->size.y2);
245 g_print_text(dev, x, yy + j * t->style->height, t->style, a, NULL);
246 set_clip_area(dev, &old);
247 mem_free(a);
248 }
249 cur -= form->cols;
250 }
251 if (lid < ftce->n_lines) lid++;
252 }
253 return;
254 }
255 }
256 if (link && fd->active && fd->vs->g_display_link && fd->vs->current_link == link - fd->f_data->links) {
257 struct style *inv;
258 inv = g_invert_style(t->style);
259 g_print_text(dev, x, y, inv, t->text, NULL);
260 g_free_style(inv);
261 } else if ((!fd->f_data->hlt_len && (!highlight_positions || !n_highlight_positions)) || g_text_no_search(fd->f_data, t)) {
262 prn:
263 g_print_text(dev, x, y, t->style, t->text, NULL);
264 } else {
265 int tlen = (int)strlen(cast_const_char t->text);
266 int found;
267 int start = t->srch_pos;
268 int end = t->srch_pos + tlen;
269 int hl_start, hl_len;
270 unsigned char *mask;
271 unsigned char *tx;
272 int txl;
273 int pmask;
274 int ii;
275 struct style *inv;
276
277 intersect(fd->f_data->hlt_pos, fd->f_data->hlt_len, start, tlen, &hl_start, &hl_len);
278
279 #define B_EQUAL(t, m) (highlight_positions[t] + highlight_lengths[t] > start && highlight_positions[t] < end)
280 #define B_ABOVE(t, m) (highlight_positions[t] >= end)
281 BIN_SEARCH(n_highlight_positions, B_EQUAL, B_ABOVE, *, found);
282 mask = mem_calloc(tlen);
283 if (found != -1) {
284 while (found > 0 && B_EQUAL(found - 1, *)) found--;
285 while (found < n_highlight_positions && !B_ABOVE(found, *)) {
286 int pos = highlight_positions[found] - t->srch_pos;
287 for (ii = 0; ii < highlight_lengths[found]; ii++) {
288 if (pos >= 0 && pos < tlen) mask[pos] = 1;
289 pos++;
290 }
291 found++;
292 }
293 if (hl_len) goto hl;
294 }
295 else if (hl_len)
296 {
297 int x;
298 hl:
299 for (x = 0; x < hl_len; x++) mask[hl_start - t->srch_pos + x] ^= 1;
300 /*memset(mask+hl_start-t->srch_pos, 1, hl_len);*/
301 }
302 else
303 {
304 mem_free(mask);
305 goto prn;
306 }
307
308 inv = g_invert_style(t->style);
309 tx = init_str();;
310 txl = 0;
311 pmask = -1;
312 for (ii = 0; ii < tlen; ii++) {
313 if (mask[ii] != pmask) {
314 g_print_text(dev, x, y, pmask ? inv : t->style, tx, &x);
315 mem_free(tx);
316 tx = init_str();
317 txl = 0;
318 }
319 add_chr_to_str(&tx, &txl, t->text[ii]);
320 pmask = mask[ii];
321 }
322 g_print_text(dev, x, y, pmask ? inv : t->style, tx, &x);
323 mem_free(tx);
324 g_free_style(inv);
325 mem_free(mask);
326 }
327 }
328
g_text_destruct(struct g_object * t_)329 void g_text_destruct(struct g_object *t_)
330 {
331 struct g_object_text *t = get_struct(t_, struct g_object_text, goti.go);
332 release_image_map(t->goti.map);
333 g_free_style(t->style);
334 mem_free(t);
335 }
336
g_line_draw(struct f_data_c * fd,struct g_object * l_,int xx,int yy)337 void g_line_draw(struct f_data_c *fd, struct g_object *l_, int xx, int yy)
338 {
339 struct g_object_line *l = get_struct(l_, struct g_object_line, go);
340 struct graphics_device *dev = fd->ses->term->dev;
341 int i;
342 int x = 0;
343 for (i = 0; i < l->n_entries; i++) {
344 struct g_object *o = l->entries[i];
345 if (o->x > x) g_draw_background(dev, l->bg, xx + x, yy, o->x - x, l->go.yw);
346 if (o->y > 0) g_draw_background(dev, l->bg, xx + o->x, yy, o->xw, o->y);
347 if (o->y + o->yw < l->go.yw) g_draw_background(dev, l->bg, xx + o->x, yy + o->y + o->yw, o->xw, l->go.yw - o->y - o->yw);
348 o->draw(fd, o, xx + o->x, yy + o->y);
349 x = o->x + o->xw;
350 }
351 if (x < l->go.xw) g_draw_background(dev, l->bg, xx + x, yy, l->go.xw - x, l->go.yw);
352 }
353
g_line_destruct(struct g_object * l_)354 void g_line_destruct(struct g_object *l_)
355 {
356 struct g_object_line *l = get_struct(l_, struct g_object_line, go);
357 int i;
358 for (i = 0; i < l->n_entries; i++) l->entries[i]->destruct(l->entries[i]);
359 mem_free(l);
360 }
361
g_line_bg_destruct(struct g_object * l_)362 void g_line_bg_destruct(struct g_object *l_)
363 {
364 struct g_object_line *l = get_struct(l_, struct g_object_line, go);
365 g_release_background(l->bg);
366 g_line_destruct(&l->go);
367 }
368
g_line_get_list(struct g_object * l_,void (* f)(struct g_object * parent,struct g_object * child))369 void g_line_get_list(struct g_object *l_, void (*f)(struct g_object *parent, struct g_object *child))
370 {
371 struct g_object_line *l = get_struct(l_, struct g_object_line, go);
372 int i;
373 for (i = 0; i < l->n_entries; i++) f(&l->go, l->entries[i]);
374 }
375
376 #define OBJ_EQ(n, b) (*a[n]).go.y <= (b) && (*a[n]).go.y + (*a[n]).go.yw > (b)
377 #define OBJ_ABOVE(n, b) (*a[n]).go.y > (b)
378
g_find_line(struct g_object_line ** a,int n,int p)379 static inline struct g_object_line **g_find_line(struct g_object_line **a, int n, int p)
380 {
381 int res = -1;
382 BIN_SEARCH(n, OBJ_EQ, OBJ_ABOVE, p, res);
383 if (res == -1) return NULL;
384 return &a[res];
385 }
386
387 #undef OBJ_EQ
388 #undef OBJ_ABOVE
389
g_area_draw(struct f_data_c * fd,struct g_object * a_,int xx,int yy)390 void g_area_draw(struct f_data_c *fd, struct g_object *a_, int xx, int yy)
391 {
392 struct g_object_area *a = get_struct(a_, struct g_object_area, go);
393 struct g_object_line **i;
394 int rx = root_x, ry = root_y;
395 int y1 = fd->ses->term->dev->clip.y1 - yy;
396 int y2 = fd->ses->term->dev->clip.y2 - yy - 1;
397 struct g_object_line **l1;
398 struct g_object_line **l2;
399 if (fd->ses->term->dev->clip.y1 == fd->ses->term->dev->clip.y2 || fd->ses->term->dev->clip.x1 == fd->ses->term->dev->clip.x2) return;
400 l1 = g_find_line(a->lines, a->n_lines, y1);
401 l2 = g_find_line(a->lines, a->n_lines, y2);
402 root_x = xx, root_y = yy;
403 if (!l1) {
404 if (y1 > a->go.yw) return;
405 else l1 = &a->lines[0];
406 }
407 if (!l2) {
408 if (y2 < 0) return;
409 else l2 = &a->lines[a->n_lines - 1];
410 }
411 for (i = l1; i <= l2; i++) {
412 struct g_object *o = &(*i)->go;
413 o->draw(fd, o, xx + o->x, yy + o->y);
414 }
415 root_x = rx, root_y = ry;
416 }
417
g_area_destruct(struct g_object * a_)418 void g_area_destruct(struct g_object *a_)
419 {
420 struct g_object_area *a = get_struct(a_, struct g_object_area, go);
421 int i;
422 g_release_background(a->bg);
423 for (i = 0; i < a->n_lines; i++) {
424 struct g_object *o = &a->lines[i]->go;
425 o->destruct(o);
426 }
427 mem_free(a);
428 }
429
g_area_get_list(struct g_object * a_,void (* f)(struct g_object * parent,struct g_object * child))430 void g_area_get_list(struct g_object *a_, void (*f)(struct g_object *parent, struct g_object *child))
431 {
432 struct g_object_area *a = get_struct(a_, struct g_object_area, go);
433 int i;
434 for (i = 0; i < a->n_lines; i++) f(&a->go, &a->lines[i]->go);
435 }
436
437 /*
438 * dsize - size of scrollbar
439 * total - total data
440 * vsize - visible data
441 * vpos - position of visible data
442 */
443
get_scrollbar_pos(int dsize,int total,int vsize,int vpos,int * start,int * end)444 void get_scrollbar_pos(int dsize, int total, int vsize, int vpos, int *start, int *end)
445 {
446 int ssize;
447 if (!total) {
448 *start = *end = 0;
449 return;
450 }
451 ssize = (int)((double)dsize * vsize / total);
452 if (ssize < G_SCROLL_BAR_MIN_SIZE) ssize = G_SCROLL_BAR_MIN_SIZE;
453 if (total == vsize) {
454 *start = 0; *end = dsize;
455 return;
456 }
457 *start = (int)((double)(dsize - ssize) * vpos / (total - vsize) + 0.5);
458 *end = *start + ssize;
459 if (*start > dsize) *start = dsize;
460 if (*start < 0) *start = 0;
461 if (*end > dsize) *end = dsize;
462 if (*end < 0) *end = 0;
463 /*
464 else {
465 *start = (double)vpos * dsize / total;
466 *end = (double)(vpos + vsize) * dsize / total;
467 }
468 if (*end > dsize) *end = dsize;
469 */
470 }
471
472 static long scroll_bar_frame_color;
473 static long scroll_bar_area_color;
474 static long scroll_bar_bar_color;
475
draw_vscroll_bar(struct graphics_device * dev,int x,int y,int yw,int total,int view,int pos)476 void draw_vscroll_bar(struct graphics_device *dev, int x, int y, int yw, int total, int view, int pos)
477 {
478 int spos, epos;
479 drv->draw_hline(dev, x, y, x + G_SCROLL_BAR_WIDTH, scroll_bar_frame_color);
480 drv->draw_vline(dev, x, y, y + yw, scroll_bar_frame_color);
481 drv->draw_vline(dev, x + G_SCROLL_BAR_WIDTH - 1, y, y + yw, scroll_bar_frame_color);
482 drv->draw_hline(dev, x, y + yw - 1, x + G_SCROLL_BAR_WIDTH, scroll_bar_frame_color);
483 drv->draw_vline(dev, x + 1, y + 1, y + yw - 1, scroll_bar_area_color);
484 drv->draw_vline(dev, x + G_SCROLL_BAR_WIDTH - 2, y + 1, y + yw - 1, scroll_bar_area_color);
485 get_scrollbar_pos(yw - 4, total, view, pos, &spos, &epos);
486 drv->fill_area(dev, x + 2, y + 1, x + G_SCROLL_BAR_WIDTH - 2, y + 2 + spos, scroll_bar_area_color);
487 drv->fill_area(dev, x + 2, y + 2 + spos, x + G_SCROLL_BAR_WIDTH - 2, y + 2 + epos, scroll_bar_bar_color);
488 drv->fill_area(dev, x + 2, y + 2 + epos, x + G_SCROLL_BAR_WIDTH - 2, y + yw - 1, scroll_bar_area_color);
489 }
490
draw_hscroll_bar(struct graphics_device * dev,int x,int y,int xw,int total,int view,int pos)491 void draw_hscroll_bar(struct graphics_device *dev, int x, int y, int xw, int total, int view, int pos)
492 {
493 int spos, epos;
494 drv->draw_vline(dev, x, y, y + G_SCROLL_BAR_WIDTH, scroll_bar_frame_color);
495 drv->draw_hline(dev, x, y, x + xw, scroll_bar_frame_color);
496 drv->draw_hline(dev, x, y + G_SCROLL_BAR_WIDTH - 1, x + xw, scroll_bar_frame_color);
497 drv->draw_vline(dev, x + xw - 1, y, y + G_SCROLL_BAR_WIDTH, scroll_bar_frame_color);
498 drv->draw_hline(dev, x + 1, y + 1, x + xw - 1, scroll_bar_area_color);
499 drv->draw_hline(dev, x + 1, y + G_SCROLL_BAR_WIDTH - 2, x + xw - 1, scroll_bar_area_color);
500 get_scrollbar_pos(xw - 4, total, view, pos, &spos, &epos);
501 drv->fill_area(dev, x + 1, y + 2, x + 2 + spos, y + G_SCROLL_BAR_WIDTH - 2, scroll_bar_area_color);
502 drv->fill_area(dev, x + 2 + spos, y + 2, x + 2 + epos, y + G_SCROLL_BAR_WIDTH - 2, scroll_bar_bar_color);
503 drv->fill_area(dev, x + 2 + epos, y + 2, x + xw - 1, y + G_SCROLL_BAR_WIDTH - 2, scroll_bar_area_color);
504 }
505
g_get_search(struct f_data * f,unsigned char * s)506 static void g_get_search(struct f_data *f, unsigned char *s)
507 {
508 int i;
509 if (!s || !*s) return;
510 if (f->last_search && !strcmp(cast_const_char f->last_search, cast_const_char s)) return;
511 mem_free(f->search_positions);
512 mem_free(f->search_lengths);
513 f->search_positions = DUMMY, f->search_lengths = DUMMY, f->n_search_positions = 0;
514 if (f->last_search) mem_free(f->last_search);
515 if (!(f->last_search = stracpy(s))) return;
516 for (i = 0; i < f->srch_string_size; i++) {
517 int len;
518 /*debug("%d: %d", i, f->srch_string[i]);*/
519 if ((s[0] | f->srch_string[i]) < 0x80) {
520 if ((f->srch_string[i] ^ s[0]) & 0xdf) continue;
521 if (s[1] != 0 && (s[1] ^ f->srch_string[i + 1]) < 0x80) {
522 if ((f->srch_string[i + 1] ^ s[1]) & 0xdf) continue;
523 }
524 }
525 len = compare_case_utf8(f->srch_string + i, s);
526 if (!len) continue;
527 if (!(f->n_search_positions & (ALLOC_GR - 1))) {
528 if ((unsigned)f->n_search_positions > MAXINT / sizeof(int) - ALLOC_GR) overalloc();
529 f->search_positions = mem_realloc(f->search_positions, (f->n_search_positions + ALLOC_GR) * sizeof(int));
530 f->search_lengths = mem_realloc(f->search_lengths, (f->n_search_positions + ALLOC_GR) * sizeof(int));
531 }
532 f->search_positions[f->n_search_positions] = i;
533 f->search_lengths[f->n_search_positions] = len;
534 f->n_search_positions++;
535 }
536 }
537
draw_root(struct f_data_c * scr,int x,int y)538 static void draw_root(struct f_data_c *scr, int x, int y)
539 {
540 scr->f_data->root->draw(scr, scr->f_data->root, x, y);
541 }
542
draw_graphical_doc(struct terminal * t,struct f_data_c * scr,int active)543 void draw_graphical_doc(struct terminal *t, struct f_data_c *scr, int active)
544 {
545 struct rect old;
546 struct view_state *vs = scr->vs;
547 struct rect_set *rs;
548 int xw = scr->xw;
549 int yw = scr->yw;
550 int vx, vy;
551 int j;
552
553 if (active) {
554 if (scr->ses->search_word && scr->ses->search_word[0]) {
555 g_get_search_data(scr->f_data);
556 g_get_search(scr->f_data, scr->ses->search_word);
557 highlight_positions = scr->f_data->search_positions;
558 highlight_lengths = scr->f_data->search_lengths;
559 n_highlight_positions = scr->f_data->n_search_positions;
560 }
561 }
562
563 if (vs->view_pos > scr->f_data->y - scr->yw + scr->hsb * G_SCROLL_BAR_WIDTH) vs->view_pos = scr->f_data->y - scr->yw + scr->hsb * G_SCROLL_BAR_WIDTH;
564 if (vs->view_pos < 0) vs->view_pos = 0;
565 if (vs->view_posx > scr->f_data->x - scr->xw + scr->vsb * G_SCROLL_BAR_WIDTH) vs->view_posx = scr->f_data->x - scr->xw + scr->vsb * G_SCROLL_BAR_WIDTH;
566 if (vs->view_posx < 0) vs->view_posx = 0;
567 vx = vs->view_posx;
568 vy = vs->view_pos;
569 restrict_clip_area(t->dev, &old, scr->xp, scr->yp, scr->xp + xw, scr->yp + yw);
570 if (scr->vsb) draw_vscroll_bar(t->dev, scr->xp + xw - G_SCROLL_BAR_WIDTH, scr->yp, yw - scr->hsb * G_SCROLL_BAR_WIDTH, scr->f_data->y, yw - scr->hsb * G_SCROLL_BAR_WIDTH, vs->view_pos);
571 if (scr->hsb) draw_hscroll_bar(t->dev, scr->xp, scr->yp + yw - G_SCROLL_BAR_WIDTH, xw - scr->vsb * G_SCROLL_BAR_WIDTH, scr->f_data->x, xw - scr->vsb * G_SCROLL_BAR_WIDTH, vs->view_posx);
572 if (scr->vsb && scr->hsb) drv->fill_area(t->dev, scr->xp + xw - G_SCROLL_BAR_WIDTH, scr->yp + yw - G_SCROLL_BAR_WIDTH, scr->xp + xw, scr->yp + yw, scroll_bar_frame_color);
573 restrict_clip_area(t->dev, NULL, scr->xp, scr->yp, scr->xp + xw - scr->vsb * G_SCROLL_BAR_WIDTH, scr->yp + yw - scr->hsb * G_SCROLL_BAR_WIDTH);
574 /*debug("buu: %d %d %d, %d %d %d", scr->xl, vx, xw, scr->yl, vy, yw);*/
575 if (drv->flags & GD_DONT_USE_SCROLL && overwrite_instead_of_scroll) goto rrr;
576 if (scr->xl == -1 || scr->yl == -1) goto rrr;
577 if (is_rect_valid(&scr->ses->win->redr)) goto rrr;
578 if (scr->xl - vx > xw || vx - scr->xl > xw ||
579 scr->yl - vy > yw || vy - scr->yl > yw) {
580 goto rrr;
581 }
582
583 rs = g_scroll(t->dev, scr->xl - vx, scr->yl - vy);
584 for (j = 0; j < rs->m; j++) {
585 struct rect *r = &rs->r[j];
586 struct rect clip1;
587 restrict_clip_area(t->dev, &clip1, r->x1, r->y1, r->x2, r->y2);
588 draw_root(scr, scr->xp - vs->view_posx, scr->yp - vs->view_pos);
589 set_clip_area(t->dev, &clip1);
590 }
591 mem_free(rs);
592
593 if (0) {
594 rrr:
595 draw_root(scr, scr->xp - vs->view_posx, scr->yp - vs->view_pos);
596 }
597 scr->xl = vx;
598 scr->yl = vy;
599 set_clip_area(t->dev, &old);
600
601 highlight_positions = NULL;
602 highlight_lengths = NULL;
603 n_highlight_positions = 0;
604 }
605
606 struct draw_data {
607 struct f_data_c *fd;
608 struct g_object *o;
609 };
610
draw_one_object_fn(struct terminal * t,void * d_)611 static void draw_one_object_fn(struct terminal *t, void *d_)
612 {
613 struct draw_data *d = (struct draw_data *)d_;
614 struct rect clip;
615 struct f_data_c *scr = d->fd;
616 struct g_object *o = d->o;
617 int x, y;
618 restrict_clip_area(t->dev, &clip, scr->xp, scr->yp, scr->xp + scr->xw - scr->vsb * G_SCROLL_BAR_WIDTH, scr->yp + scr->yw - scr->hsb * G_SCROLL_BAR_WIDTH);
619 get_object_pos(o, &x, &y);
620 o->draw(scr, o, scr->xp - scr->vs->view_posx + x, scr->yp - scr->vs->view_pos + y);
621 set_clip_area(t->dev, &clip);
622 }
623
draw_one_object(struct f_data_c * scr,struct g_object * o)624 void draw_one_object(struct f_data_c *scr, struct g_object *o)
625 {
626 struct draw_data d;
627 int *h1, *h2, h3;
628 d.fd = scr;
629 d.o = o;
630 h1 = highlight_positions;
631 h2 = highlight_lengths;
632 h3 = n_highlight_positions;
633 if (scr->ses->search_word && scr->ses->search_word[0]) {
634 g_get_search_data(scr->f_data);
635 g_get_search(scr->f_data, scr->ses->search_word);
636 highlight_positions = scr->f_data->search_positions;
637 highlight_lengths = scr->f_data->search_lengths;
638 n_highlight_positions = scr->f_data->n_search_positions;
639 }
640 draw_to_window(scr->ses->win, draw_one_object_fn, &d);
641 highlight_positions = h1;
642 highlight_lengths = h2;
643 n_highlight_positions = h3;
644 }
645
g_forward_mouse(struct f_data_c * fd,struct g_object * a,int x,int y,int b)646 int g_forward_mouse(struct f_data_c *fd, struct g_object *a, int x, int y, int b)
647 {
648 int r = 0;
649 if (x < a->x) r |= 1;
650 if (x >= a->x + a->xw) r |= 2;
651 if (y < a->y) r |= 4;
652 if (y >= a->y + a->yw) r |= 8;
653 if (!r) {
654 a->mouse_event(fd, a, x - a->x, y - a->y, b);
655 return 0;
656 }
657 return r;
658 }
659
g_area_mouse(struct f_data_c * fd,struct g_object * a_,int x,int y,int b)660 void g_area_mouse(struct f_data_c *fd, struct g_object *a_, int x, int y, int b)
661 {
662 struct g_object_area *a = get_struct(a_, struct g_object_area, go);
663 int found, g;
664 #define A_EQ(m, n) ((g = g_forward_mouse(fd, &a->lines[m]->go, x, y, b)), !g)
665 #define A_AB(m, n) (g & 4)
666 BIN_SEARCH(a->n_lines, A_EQ, A_AB, *, found);
667 found = found + 1; /* against warning */
668 #undef A_EQ
669 #undef A_AB
670 /*int i;
671 for (i = 0; i < a->n_lines; i++) if (!g_forward_mouse(fd, &a->lines[i]->go, x, y, b)) return;*/
672 }
673
g_line_mouse(struct f_data_c * fd,struct g_object * a_,int x,int y,int b)674 void g_line_mouse(struct f_data_c *fd, struct g_object *a_, int x, int y, int b)
675 {
676 struct g_object_line *a = get_struct(a_, struct g_object_line, go);
677 int found, g;
678 #define A_EQ(m, n) ((g = g_forward_mouse(fd, a->entries[m], x, y, b)), !g)
679 #define A_AB(m, n) (g & 1)
680 BIN_SEARCH(a->n_entries, A_EQ, A_AB, *, found);
681 found = found + 1; /* against warning */
682 #undef A_EQ
683 #undef A_AB
684 /*int i;
685 for (i = 0; i < a->n_entries; i++) if (!g_forward_mouse(fd, a->entries[i], x, y, b)) return;*/
686 }
687
688 static struct f_data *ffff;
689
get_parents_sub(struct g_object * p,struct g_object * c)690 static void get_parents_sub(struct g_object *p, struct g_object *c)
691 {
692 c->parent = p;
693 if (c->get_list) c->get_list(c, get_parents_sub);
694 if (c->destruct == g_tag_destruct) {
695 struct g_object_tag *tg = get_struct(c, struct g_object_tag, go);
696 int x = 0, y = 0;
697 struct g_object *o;
698 c->y -= c->parent->yw;
699 for (o = c; o; o = o->parent) x += o->x, y += o->y;
700 html_tag(ffff, tg->name, x, y);
701 }
702 if (c->mouse_event == g_text_mouse) {
703 struct g_object_text_image *tc = get_struct(c, struct g_object_text_image, go);
704 int l = tc->link_num;
705 if (l >= 0) {
706 struct link *link = &ffff->links[l];
707 int x = 0, y = 0;
708 struct g_object *o;
709 for (o = c; o; o = o->parent) x += o->x, y += o->y;
710 if (x < link->r.x1) link->r.x1 = x;
711 if (y < link->r.y1) link->r.y1 = y;
712 if (x + c->xw > link->r.x2) link->r.x2 = x + c->xw;
713 if (y + c->yw > link->r.y2) link->r.y2 = y + c->yw;
714 link->obj = c;
715 }
716 }
717 }
718
get_parents(struct f_data * f,struct g_object * a)719 void get_parents(struct f_data *f, struct g_object *a)
720 {
721 ffff = f;
722 a->parent = NULL;
723 if (a->get_list) a->get_list(a, get_parents_sub);
724 }
725
get_object_pos(struct g_object * o,int * x,int * y)726 static void get_object_pos(struct g_object *o, int *x, int *y)
727 {
728 *x = *y = 0;
729 while (o) {
730 *x += o->x;
731 *y += o->y;
732 o = o->parent;
733 }
734 }
735
736 /* if set_position is 1 sets cursor position in FIELD/AREA elements */
g_set_current_link(struct f_data_c * fd,struct g_object_text_image * a,int x,int y,int set_position)737 static void g_set_current_link(struct f_data_c *fd, struct g_object_text_image *a, int x, int y, int set_position)
738 {
739 if (a->map) {
740 int i;
741 for (i = 0; i < a->map->n_areas; i++) {
742 if (is_in_area(&a->map->area[i], x, y) && a->map->area[i].link_num >= 0) {
743 fd->vs->current_link = a->map->area[i].link_num;
744 fd->vs->orig_link = fd->vs->current_link;
745 return;
746 }
747 }
748 }
749 fd->vs->current_link = -1;
750 fd->vs->orig_link = fd->vs->current_link;
751 if (a->link_num >= 0) {
752 fd->vs->current_link = a->link_num;
753 fd->vs->orig_link = fd->vs->current_link;
754 /* if link is a field, set cursor position */
755 if (set_position && a->link_num >= 0 && a->link_num < fd->f_data->nlinks) { /* valid link */
756 struct link *l = &fd->f_data->links[a->link_num];
757 struct form_state *fs;
758 int xx, yy;
759
760 if (!l->form) return;
761 if (l->type == L_AREA) {
762 struct g_object_text *at = get_struct(a, struct g_object_text, goti);
763 struct format_text_cache_entry *ftce;
764 fs = find_form_state(fd,l->form);
765
766 if (g_char_width(at->style, ' '))
767 xx = x / g_char_width(at->style, ' ');
768 else
769 xx = x;
770 xx += fs->vpos;
771 xx = xx < 0 ? 0 : xx;
772 yy = a->link_order;
773 yy += fs->vypos;
774 ftce = format_text(fd, l->form, fs);
775 if (yy >= ftce->n_lines)
776 yy = ftce->n_lines - 1;
777 if (yy >= 0) {
778 int bla = textptr_diff(fs->string + ftce->ln[yy].en_offs, fs->string + ftce->ln[yy].st_offs, fd->f_data->opt.cp);
779
780 fs->state = ftce->ln[yy].st_offs;
781 fs->state = (int)(textptr_add(fs->string + fs->state, xx < bla ? xx : bla, fd->f_data->opt.cp) - fs->string);
782 }
783 return;
784 }
785 if (l->type == L_FIELD) {
786 struct g_object_text *at = get_struct(a, struct g_object_text, goti);
787 fs = find_form_state(fd, l->form);
788 if (g_char_width(at->style, ' '))
789 xx = x / g_char_width(at->style, ' ');
790 else
791 xx = x;
792 fs->state = (int)(textptr_add(fs->string + ((size_t)fs->vpos > strlen(cast_const_char fs->string) ? strlen(cast_const_char fs->string) : (size_t)fs->vpos), (xx < 0 ? 0 : xx), fd->f_data->opt.cp) - fs->string);
793 }
794 }
795 }
796 }
797
g_text_mouse(struct f_data_c * fd,struct g_object * a_,int x,int y,int b)798 void g_text_mouse(struct f_data_c *fd, struct g_object *a_, int x, int y, int b)
799 {
800 struct g_object_text_image *a = get_struct(a_, struct g_object_text_image, go);
801 int e;
802 g_set_current_link(fd, a, x, y, (b == (B_UP | B_LEFT)));
803
804 #ifdef JS
805 if (fd->vs && fd->f_data && fd->vs->current_link >= 0 && fd->vs->current_link < fd->f_data->nlinks) {
806 /* fd->vs->current links is a valid link */
807
808 struct link *l = &fd->f_data->links[fd->vs->current_link];
809
810 if (l->js_event && l->js_event->up_code && (b & BM_ACT) == B_UP)
811 jsint_execute_code(fd, l->js_event->up_code, strlen(cast_const_char l->js_event->up_code), -1, -1, -1, NULL);
812
813 if (l->js_event && l->js_event->down_code && (b & BM_ACT) == B_DOWN)
814 jsint_execute_code(fd, l->js_event->down_code, strlen(cast_const_char l->js_event->down_code), -1, -1, -1, NULL);
815 }
816 #endif
817
818 if (b == (B_UP | B_LEFT)) {
819 int ix = ismap_x, iy = ismap_y, il = ismap_link;
820 ismap_x = x;
821 ismap_y = y;
822 ismap_link = a->ismap;
823 e = enter(fd->ses, fd, 1);
824 ismap_x = ix;
825 ismap_y = iy;
826 ismap_link = il;
827 if (e) {
828 print_all_textarea = 1;
829 draw_one_object(fd, &a->go);
830 print_all_textarea = 0;
831 }
832 if (e == 2) fd->f_data->locked_on = &a->go;
833 return;
834 }
835 if (b == (B_UP | B_RIGHT)) {
836 if (fd->vs->current_link != -1) link_menu(fd->ses->term, NULL, fd->ses);
837 }
838 }
839
horizontal_page_jump(struct f_data_c * fd)840 static int horizontal_page_jump(struct f_data_c *fd)
841 {
842 int j = fd->xw - fd->vsb * G_SCROLL_BAR_WIDTH;
843 if (j <= 0) j = 1;
844 return j;
845 }
846
vertical_page_jump(struct f_data_c * fd)847 static int vertical_page_jump(struct f_data_c *fd)
848 {
849 int j = fd->yw - fd->hsb * G_SCROLL_BAR_WIDTH;
850 if (j >= fd->ses->ds.font_size * 2) j -= fd->ses->ds.font_size;
851 if (j <= 0) j = 1;
852 return j;
853 }
854
process_sb_event(struct f_data_c * fd,int off,int h)855 static void process_sb_event(struct f_data_c *fd, int off, int h)
856 {
857 int spos, epos;
858 int w = h ? fd->hsbsize : fd->vsbsize;
859 get_scrollbar_pos(w - 4, h ? fd->f_data->x : fd->f_data->y, w, h ? fd->vs->view_posx : fd->vs->view_pos, &spos, &epos);
860 spos += 2;
861 epos += 2;
862 /*debug("%d %d %d", spos, epos, off);*/
863 if (off >= spos && off < epos) {
864 fd->ses->scrolling = 1;
865 fd->ses->scrolltype = h;
866 fd->ses->scrolloff = off - spos;
867 return;
868 }
869 if (off < spos) {
870 if (h) fd->vs->view_posx -= horizontal_page_jump(fd);
871 else fd->vs->view_pos -= vertical_page_jump(fd);
872 } else {
873 if (h) fd->vs->view_posx += horizontal_page_jump(fd);
874 else fd->vs->view_pos += vertical_page_jump(fd);
875 }
876 fd->vs->orig_view_pos = fd->vs->view_pos;
877 fd->vs->orig_view_posx = fd->vs->view_posx;
878 draw_graphical_doc(fd->ses->term, fd, 1);
879 }
880
process_sb_move(struct f_data_c * fd,int off)881 static void process_sb_move(struct f_data_c *fd, int off)
882 {
883 int h = fd->ses->scrolltype;
884 int w = h ? fd->hsbsize : fd->vsbsize;
885 int rpos = off - 2 - fd->ses->scrolloff;
886 int st, en;
887 int new_val;
888 get_scrollbar_pos(w - 4, h ? fd->f_data->x : fd->f_data->y, w, h ? fd->vs->view_posx : fd->vs->view_pos, &st, &en);
889 if (en - st >= w - 4) return;
890 /*
891 *(h ? &fd->vs->view_posx : &fd->vs->view_pos) = rpos * (h ? fd->f_data->x : fd->f_data->y) / (w - 4);
892 */
893 if (w - 4 - (en - st) <= 0) return;
894 new_val = (int)(rpos * (double)(h ? fd->f_data->x - w : fd->f_data->y - w) / (w - 4 - (en - st)) + 0.5);
895 *(h ? &fd->vs->view_posx : &fd->vs->view_pos) = new_val;
896 fd->vs->orig_view_pos = fd->vs->view_pos;
897 fd->vs->orig_view_posx = fd->vs->view_posx;
898 draw_graphical_doc(fd->ses->term, fd, 1);
899 }
900
ev_in_rect(struct links_event * ev,int x1,int y1,int x2,int y2)901 static inline int ev_in_rect(struct links_event *ev, int x1, int y1, int x2, int y2)
902 {
903 return ev->x >= x1 && ev->y >= y1 && ev->x < x2 && ev->y < y2;
904 }
905
is_link_in_view(struct f_data_c * fd,int nl)906 int is_link_in_view(struct f_data_c *fd, int nl)
907 {
908 struct link *l = &fd->f_data->links[nl];
909 return fd->vs->view_pos < l->r.y2 && fd->vs->view_pos + fd->yw - fd->hsb * G_SCROLL_BAR_WIDTH > l->r.y1;
910 }
911
skip_link(struct f_data_c * fd,int nl)912 static int skip_link(struct f_data_c *fd, int nl)
913 {
914 struct link *l = &fd->f_data->links[nl];
915 return !l->where && !l->form;
916 }
917
redraw_link(struct f_data_c * fd,int nl)918 static void redraw_link(struct f_data_c *fd, int nl)
919 {
920 struct link *l = &fd->f_data->links[nl];
921 struct rect r;
922 memcpy(&r, &l->r, sizeof(struct rect));
923 r.x1 += fd->xp - fd->vs->view_posx;
924 r.x2 += fd->xp - fd->vs->view_posx;
925 r.y1 += fd->yp - fd->vs->view_pos;
926 r.y2 += fd->yp - fd->vs->view_pos;
927 t_redraw(fd->ses->term->dev, &r);
928 }
929
lr_link(struct f_data_c * fd,int nl)930 static int lr_link(struct f_data_c *fd, int nl)
931 {
932 struct link *l = &fd->f_data->links[nl];
933 int xx = fd->vs->view_posx;
934 if (l->r.x2 > fd->vs->view_posx + fd->xw - fd->vsb * G_SCROLL_BAR_WIDTH) fd->vs->view_posx = l->r.x2 - (fd->xw - fd->vsb * G_SCROLL_BAR_WIDTH);
935 if (l->r.x1 < fd->vs->view_posx) fd->vs->view_posx = l->r.x1;
936 fd->vs->orig_view_posx = fd->vs->view_posx;
937 return xx != fd->vs->view_posx;
938 }
939
g_next_link(struct f_data_c * fd,int dir,int do_scroll)940 int g_next_link(struct f_data_c *fd, int dir, int do_scroll)
941 {
942 int orig_link = -1;
943 int r = 2;
944 int n, pn;
945 if (fd->vs->current_link >= 0 && fd->vs->current_link < fd->f_data->nlinks) {
946 orig_link = fd->vs->current_link;
947 n = (pn = fd->vs->current_link) + dir;
948 } else retry: n = dir > 0 ? 0 : fd->f_data->nlinks - 1, pn = -1;
949 again:
950 if (n < 0 || n >= fd->f_data->nlinks) {
951 if (!do_scroll)
952 return 0;
953 if (r == 1) {
954 fd->vs->current_link = -1;
955 if (fd->vs->view_pos > fd->f_data->y - fd->yw + fd->hsb * G_SCROLL_BAR_WIDTH) fd->vs->view_pos = fd->f_data->y - fd->yw + fd->hsb * G_SCROLL_BAR_WIDTH;
956 if (fd->vs->view_pos < 0) fd->vs->view_pos = 0;
957 if (orig_link != -1 && is_link_in_view(fd, orig_link)) fd->vs->current_link = orig_link;
958 fd->vs->orig_link = fd->vs->current_link;
959 if (fd->vs->current_link == -1) fd->ses->locked_link = 0;
960 return 1;
961 }
962 if (dir < 0) {
963 if (!fd->vs->view_pos) {
964 fd->vs->orig_view_pos = fd->vs->view_pos;
965 return 0;
966 }
967 fd->vs->view_pos -= vertical_page_jump(fd);
968 fd->vs->orig_view_pos = fd->vs->view_pos;
969 } else {
970 if (fd->vs->view_pos >= fd->f_data->y - fd->yw + fd->hsb * G_SCROLL_BAR_WIDTH) return 0;
971 fd->vs->view_pos += vertical_page_jump(fd);
972 fd->vs->orig_view_pos = fd->vs->view_pos;
973 }
974 r = 1;
975 goto retry;
976 }
977 if (!is_link_in_view(fd, n) || skip_link(fd, n)) {
978 n += dir;
979 goto again;
980 }
981 if (fd->vs->current_link >= 0 && fd->vs->current_link < fd->f_data->nlinks) {
982 redraw_link(fd, fd->vs->current_link);
983 }
984 fd->vs->current_link = n;
985 fd->vs->orig_link = fd->vs->current_link;
986 fd->vs->g_display_link = 1;
987 redraw_link(fd, n);
988 fd->ses->locked_link = 0;
989 if (fd->f_data->links[fd->vs->current_link].type == L_FIELD || fd->f_data->links[fd->vs->current_link].type == L_AREA) {
990 if ((fd->f_data->locked_on = fd->f_data->links[fd->vs->current_link].obj)) fd->ses->locked_link = 1;
991 }
992 set_textarea(fd->ses, fd, -dir);
993 change_screen_status(fd->ses);
994 print_screen_status(fd->ses);
995 if (lr_link(fd, fd->vs->current_link)) r = 1;
996 return r;
997 }
998
unset_link(struct f_data_c * fd)999 static void unset_link(struct f_data_c *fd)
1000 {
1001 int n = fd->vs->current_link;
1002 fd->vs->current_link = -1;
1003 fd->vs->orig_link = fd->vs->current_link;
1004 fd->vs->g_display_link = 0;
1005 fd->ses->locked_link = 0;
1006 if (n >= 0 && n < fd->f_data->nlinks) {
1007 redraw_link(fd, n);
1008 }
1009 }
1010
scroll_vh(int * vp,int * ovp,int * sc,int d,int limit)1011 static int scroll_vh(int *vp, int *ovp, int *sc, int d, int limit)
1012 {
1013 int o = *vp;
1014 *vp += d;
1015 if (*vp > limit)
1016 *vp = limit;
1017 if (*vp < 0)
1018 *vp = 0;
1019 *ovp = *vp;
1020 o -= *vp;
1021 if (sc) *sc -= o;
1022 return o ? 3 : 0;
1023 }
1024
scroll_v(struct f_data_c * fd,int y)1025 static int scroll_v(struct f_data_c *fd, int y)
1026 {
1027 return scroll_vh(&fd->vs->view_pos, &fd->vs->orig_view_pos, fd->ses->scrolling == 2 ? &fd->ses->scrolloff : NULL, y, fd->f_data->y - fd->yw + fd->hsb * G_SCROLL_BAR_WIDTH);
1028 }
1029
scroll_h(struct f_data_c * fd,int x)1030 static int scroll_h(struct f_data_c *fd, int x)
1031 {
1032 return scroll_vh(&fd->vs->view_posx, &fd->vs->orig_view_posx, fd->ses->scrolling == 2 ? &fd->ses->scrolltype : NULL, x, fd->f_data->x - fd->xw + fd->vsb * G_SCROLL_BAR_WIDTH);
1033 }
1034
g_frame_ev(struct session * ses,struct f_data_c * fd,struct links_event * ev)1035 int g_frame_ev(struct session *ses, struct f_data_c *fd, struct links_event *ev)
1036 {
1037 if (!fd->f_data) return 0;
1038 switch ((int)ev->ev) {
1039 case EV_MOUSE:
1040 if (BM_IS_WHEEL(ev->b) && ses->locked_link) {
1041 if (fd->vs->current_link >= 0 && fd->vs->current_link < fd->f_data->nlinks && fd->f_data->links[fd->vs->current_link].type == L_AREA) {
1042 if (field_op(ses, fd, &fd->f_data->links[fd->vs->current_link], ev)) {
1043 if (fd->f_data->locked_on) {
1044 print_all_textarea = 1;
1045 draw_one_object(fd, fd->f_data->locked_on);
1046 print_all_textarea = 0;
1047 return 2;
1048 }
1049 }
1050 }
1051 return 1;
1052 }
1053 if ((ev->b & BM_BUTT) == B_WHEELUP)
1054 return scroll_v(fd, -64);
1055 if ((ev->b & BM_BUTT) == B_WHEELDOWN)
1056 return scroll_v(fd, 64);
1057 if ((ev->b & BM_BUTT) == B_WHEELUP1)
1058 return scroll_v(fd, -16);
1059 if ((ev->b & BM_BUTT) == B_WHEELDOWN1)
1060 return scroll_v(fd, 16);
1061 if ((ev->b & BM_BUTT) == B_WHEELLEFT)
1062 return scroll_h(fd, -64);
1063 if ((ev->b & BM_BUTT) == B_WHEELRIGHT)
1064 return scroll_h(fd, 64);
1065 if ((ev->b & BM_BUTT) == B_WHEELLEFT1)
1066 return scroll_h(fd, -16);
1067 if ((ev->b & BM_BUTT) == B_WHEELRIGHT1)
1068 return scroll_h(fd, 16);
1069 if ((ev->b & BM_ACT) == B_MOVE) ses->scrolling = 0;
1070 if (ses->scrolling == 1) process_sb_move(fd, ses->scrolltype ? ev->x : ev->y);
1071 if (ses->scrolling == 2) {
1072 fd->vs->view_pos = -ev->y + ses->scrolloff;
1073 fd->vs->view_posx = -ev->x + ses->scrolltype;
1074 fd->vs->orig_view_pos = fd->vs->view_pos;
1075 fd->vs->orig_view_posx = fd->vs->view_posx;
1076 draw_graphical_doc(ses->term, fd, 1);
1077 if ((ev->b & BM_ACT) == B_UP) {
1078 ses->scrolling = 0;
1079 }
1080 break;
1081 }
1082 if (ses->scrolling) {
1083 if ((ev->b & BM_ACT) == B_UP) {
1084 ses->scrolling = 0;
1085 }
1086 break;
1087 }
1088
1089 if ((ev->b & BM_ACT) == B_DOWN && fd->vsb && ev_in_rect(ev, fd->xw - G_SCROLL_BAR_WIDTH, 0, fd->xw, fd->yw - fd->hsb * G_SCROLL_BAR_WIDTH)) {
1090 process_sb_event(fd, ev->y, 0);
1091 break;
1092 }
1093 if ((ev->b & BM_ACT) == B_DOWN && fd->hsb && ev_in_rect(ev, 0, fd->yw - G_SCROLL_BAR_WIDTH, fd->xw - fd->vsb * G_SCROLL_BAR_WIDTH, fd->yw)) {
1094 process_sb_event(fd, ev->x, 1);
1095 break;
1096 }
1097 if (fd->vsb && ev_in_rect(ev, fd->xw - G_SCROLL_BAR_WIDTH, 0, fd->xw, fd->yw)) return 0;
1098 if (fd->hsb && ev_in_rect(ev, 0, fd->yw - G_SCROLL_BAR_WIDTH, fd->xw, fd->yw)) return 0;
1099
1100 if ((ev->b & BM_ACT) == B_DOWN && (ev->b & BM_BUTT) == B_MIDDLE) {
1101 scrll:
1102 ses->scrolltype = ev->x + fd->vs->view_posx;
1103 ses->scrolloff = ev->y + fd->vs->view_pos;
1104 ses->scrolling = 2;
1105 break;
1106 }
1107
1108 previous_link=fd->vs->current_link;
1109 if (fd->vs->g_display_link) {
1110 fd->vs->g_display_link = 0;
1111 if (fd->vs->current_link >= 0 && fd->vs->current_link < fd->f_data->nlinks) redraw_link(fd, fd->vs->current_link);
1112 }
1113 if (!(ev->b == (B_LEFT | B_UP) && fd->f_data->hlt_len && fd->f_data->start_highlight_x == -1)) {
1114 fd->vs->current_link = -1;
1115 fd->vs->orig_link = fd->vs->current_link;
1116 fd->f_data->root->mouse_event(fd, fd->f_data->root, ev->x + fd->vs->view_posx, ev->y + fd->vs->view_pos, (int)ev->b);
1117 if (previous_link!=fd->vs->current_link)
1118 change_screen_status(ses);
1119 print_screen_status(ses);
1120 }
1121
1122 /* highlight text */
1123 if ((ev->b & BM_ACT) == B_DOWN && (ev->b & BM_BUTT) == B_LEFT) { /* start highlighting */
1124 int need_redraw = !!fd->f_data->hlt_len;
1125 fd->f_data->start_highlight_x = ev->x;
1126 fd->f_data->start_highlight_y = ev->y;
1127 fd->f_data->hlt_len = 0;
1128 fd->f_data->hlt_pos = -1;
1129 return need_redraw;
1130 }
1131 if (((ev->b & BM_ACT) == B_DRAG || (ev->b & BM_ACT) == B_UP) && (ev->b & BM_BUTT) == B_LEFT) { /* stop highlighting */
1132 struct g_object_text *t;
1133 if (fd->f_data->start_highlight_x != -1) {
1134 if (abs(ev->x - fd->f_data->start_highlight_x) < 8 && abs(ev->y - fd->f_data->start_highlight_y) < 8) goto skip_hl;
1135 t = g_find_nearest_object(fd->f_data, fd->f_data->start_highlight_x + fd->vs->view_posx, fd->f_data->start_highlight_y + fd->vs->view_pos);
1136
1137 if (t) {
1138 g_get_search_data(fd->f_data);
1139 fd->f_data->hlt_pos = t->srch_pos+g_find_text_pos(t, fd->f_data->start_highlight_x+fd->vs->view_posx);
1140 fd->f_data->hlt_len=0;
1141 }
1142 fd->f_data->start_highlight_x = -1;
1143 fd->f_data->start_highlight_y = -1;
1144 }
1145 if (fd->f_data->hlt_pos == -1) goto skip_hl;
1146 t = g_find_nearest_object(fd->f_data, ev->x + fd->vs->view_posx, ev->y + fd->vs->view_pos);
1147
1148 if (t) {
1149 int end;
1150 g_get_search_data(fd->f_data);
1151 end = t->srch_pos + g_find_text_pos(t, ev->x+fd->vs->view_posx);
1152 fd->f_data->hlt_len = end-fd->f_data->hlt_pos;
1153 if ((ev->b & BM_ACT) == B_UP || (ev->b & BM_ACT) == B_DRAG) {
1154 unsigned char *m = memacpy(fd->f_data->srch_string + fd->f_data->hlt_pos + (fd->f_data->hlt_len > 0 ? 0 : fd->f_data->hlt_len), fd->f_data->hlt_len > 0 ? fd->f_data->hlt_len : -fd->f_data->hlt_len);
1155 if (m) {
1156 unsigned char *p = m;
1157 while ((p = cast_uchar strchr(cast_const_char p, 1))) *p++ = ' ';
1158 p = m;
1159 while ((p = cast_uchar strstr(cast_const_char p, "\302\255"))) memmove(p, p + 2, strlen(cast_const_char(p + 2)) + 1);
1160 if (*m) set_clipboard_text(ses->term, m);
1161 mem_free(m);
1162 }
1163 }
1164 return 1;
1165 }
1166 }
1167 skip_hl:
1168 if (((ev->b & BM_ACT) == B_MOVE || (ev->b & BM_ACT) == B_UP) && (ev->b & BM_BUTT) == B_LEFT) { /* stop highlighting */
1169 fd->f_data->start_highlight_x = -1;
1170 fd->f_data->start_highlight_y = -1;
1171 }
1172
1173 #ifdef JS
1174 /* process onmouseover/onmouseout handlers */
1175 if (previous_link!=fd->vs->current_link)
1176 {
1177 struct link* lnk=NULL;
1178
1179 if (previous_link>=0&&previous_link<fd->f_data->nlinks)lnk=&(fd->f_data->links[previous_link]);
1180 if (lnk&&lnk->js_event&&lnk->js_event->out_code)
1181 jsint_execute_code(fd,lnk->js_event->out_code,strlen(cast_const_char lnk->js_event->out_code),-1,-1,-1, NULL);
1182 lnk=NULL;
1183 if (fd->vs->current_link>=0&&fd->vs->current_link<fd->f_data->nlinks)lnk=&(fd->f_data->links[fd->vs->current_link]);
1184 if (lnk&&lnk->js_event&&lnk->js_event->over_code)
1185 jsint_execute_code(fd,lnk->js_event->over_code,strlen(cast_const_char lnk->js_event->over_code),-1,-1,-1, NULL);
1186 }
1187 #endif
1188
1189 if ((ev->b & BM_ACT) == B_DOWN && (ev->b & BM_BUTT) == B_RIGHT && fd->vs->current_link == -1) goto scrll;
1190 break;
1191 case EV_KBD:
1192 if (ses->locked_link && fd->vs->current_link >= 0 && fd->vs->current_link < fd->f_data->nlinks && (fd->f_data->links[fd->vs->current_link].type == L_FIELD || fd->f_data->links[fd->vs->current_link].type == L_AREA)) {
1193 if (field_op(ses, fd, &fd->f_data->links[fd->vs->current_link], ev)) {
1194 if (fd->f_data->locked_on) {
1195 print_all_textarea = 1;
1196 draw_one_object(fd, fd->f_data->locked_on);
1197 print_all_textarea = 0;
1198 return 2;
1199 }
1200 return 1;
1201 }
1202 if (ev->x == KBD_ENTER && !(ev->y & KBD_PASTING)) {
1203 return enter(ses, fd, 0);
1204 }
1205 }
1206 if (ev->y & KBD_PASTING)
1207 return 0;
1208 if (ev->x == KBD_ENTER && fd->f_data->opt.plain == 2) {
1209 ses->ds.porn_enable ^= 1;
1210 html_interpret_recursive(ses->screen);
1211 return 1;
1212 }
1213 if (ev->x == KBD_RIGHT || ev->x == KBD_ENTER) {
1214 struct link *l;
1215 if (fd->vs->current_link >= 0 && fd->vs->current_link < fd->f_data->nlinks) {
1216 l = &fd->f_data->links[fd->vs->current_link];
1217 set_window_ptr(ses->win, fd->xp + l->r.x1 - fd->vs->view_posx, fd->yp + l->r.y1 - fd->vs->view_pos);
1218 } else {
1219 set_window_ptr(ses->win, fd->xp, fd->yp);
1220 }
1221 return enter(ses, fd, 0);
1222 }
1223 if (ev->x == '*') {
1224 ses->ds.display_images ^= 1;
1225 html_interpret_recursive(ses->screen);
1226 return 1;
1227 }
1228 if (ev->x == KBD_PAGE_DOWN || (ev->x == ' ' && !(ev->y & KBD_ALT)) || (upcase(ev->x) == 'F' && ev->y & KBD_CTRL)) {
1229 unset_link(fd);
1230 return scroll_v(fd, vertical_page_jump(fd));
1231 }
1232 if (ev->x == KBD_PAGE_UP || (upcase(ev->x) == 'B' && !(ev->y & KBD_ALT))) {
1233 unset_link(fd);
1234 return scroll_v(fd, -vertical_page_jump(fd));
1235 }
1236 if (ev->x == KBD_DEL || (upcase(ev->x) == 'N' && ev->y & KBD_CTRL) || (ev->x == 'l' && !(ev->y & (KBD_CTRL | KBD_ALT)))) {
1237 return scroll_v(fd, 32);
1238 }
1239 if (ev->x == KBD_INS || (upcase(ev->x) == 'P' && ev->y & KBD_CTRL) || (ev->x == 'p' && !(ev->y & (KBD_CTRL | KBD_ALT)))) {
1240 return scroll_v(fd, -32);
1241 }
1242 if (ev->x == KBD_DOWN) {
1243 return g_next_link(fd, 1, 1);
1244 }
1245 if (ev->x == KBD_UP) {
1246 return g_next_link(fd, -1, 1);
1247 }
1248 if (ev->x == 'H' && !(ev->y & (KBD_CTRL | KBD_ALT))) {
1249 unset_link(fd);
1250 return g_next_link(fd, 1, 0);
1251 }
1252 if (ev->x == 'L' && !(ev->y & (KBD_CTRL | KBD_ALT))) {
1253 unset_link(fd);
1254 return g_next_link(fd, -1, 0);
1255 }
1256 if (ev->x == '[') {
1257 return scroll_h(fd, -64);
1258 }
1259 if (ev->x == ']') {
1260 return scroll_h(fd, 64);
1261 }
1262 if (ev->x == KBD_HOME || (upcase(ev->x) == 'A' && ev->y & KBD_CTRL)) {
1263 fd->vs->view_pos = 0;
1264 fd->vs->orig_view_pos = fd->vs->view_pos;
1265 unset_link(fd);
1266 return 3;
1267 }
1268 if (ev->x == KBD_END || (upcase(ev->x) == 'E' && ev->y & KBD_CTRL)) {
1269 fd->vs->view_pos = fd->f_data->y;
1270 fd->vs->orig_view_pos = fd->vs->view_pos;
1271 unset_link(fd);
1272 return 3;
1273 }
1274 if ((upcase(ev->x) == 'F' && !(ev->y & (KBD_ALT | KBD_CTRL))) || ev->x == KBD_FRONT) {
1275 set_frame(ses, fd, 0);
1276 return 2;
1277 }
1278 if (ev->x == '#') {
1279 ses->ds.images ^= 1;
1280 html_interpret_recursive(fd);
1281 ses->ds.images ^= 1;
1282 return 1;
1283 }
1284 if (ev->x == 'i' && !(ev->y & KBD_ALT)) {
1285 if (!F || fd->f_data->opt.plain != 2) frm_view_image(ses, fd);
1286 return 2;
1287 }
1288 if (ev->x == 'I' && !(ev->y & KBD_ALT)) {
1289 if (!anonymous) frm_download_image(ses, fd);
1290 return 2;
1291 }
1292 if (upcase(ev->x) == 'D' && !(ev->y & KBD_ALT)) {
1293 if (!anonymous) frm_download(ses, fd);
1294 return 2;
1295 }
1296 if (ev->x == '/' || (ev->x == KBD_FIND && !(ev->y & (KBD_SHIFT | KBD_CTRL | KBD_ALT)))) {
1297 search_dlg(ses, fd, 0);
1298 return 2;
1299 }
1300 if (ev->x == '?' || (ev->x == KBD_FIND && ev->y & (KBD_SHIFT | KBD_CTRL | KBD_ALT))) {
1301 search_back_dlg(ses, fd, 0);
1302 return 2;
1303 }
1304 if ((ev->x == 'n' && !(ev->y & KBD_ALT)) || ev->x == KBD_REDO) {
1305 find_next(ses, fd, 0);
1306 return 2;
1307 }
1308 if ((ev->x == 'N' && !(ev->y & KBD_ALT)) || ev->x == KBD_UNDO) {
1309 find_next_back(ses, fd, 0);
1310 return 2;
1311 }
1312 if (ev->x == KBD_MENU) {
1313 if (fd->vs->current_link >= 0 && fd->vs->current_link < fd->f_data->nlinks) {
1314 ses->win->xp = fd->f_data->links[fd->vs->current_link].r.x1 + fd->xp - fd->vs->view_posx;
1315 ses->win->yp = fd->f_data->links[fd->vs->current_link].r.y2 + fd->yp - fd->vs->view_pos;
1316 link_menu(ses->term, NULL, ses);
1317 }
1318 }
1319 break;
1320 }
1321 return 0;
1322 }
1323
draw_title(struct f_data_c * f)1324 void draw_title(struct f_data_c *f)
1325 {
1326 int b, z, w;
1327 struct graphics_device *dev = f->ses->term->dev;
1328 unsigned char *title = stracpy(!drv->set_title && f->f_data && f->f_data->title && f->f_data->title[0] ? f->f_data->title : NULL);
1329 if (!title) {
1330 if (f->rq && f->rq->url)
1331 title = display_url(f->ses->term, f->rq->url, 1);
1332 else
1333 title = stracpy((unsigned char *)"");
1334 }
1335 w = g_text_width(bfu_style_bw, title);
1336 z = 0;
1337 g_print_text(dev, 0, 0, !proxies.only_proxies ? bfu_style_bw : bfu_style_wb, cast_uchar " " G_LEFT_ARROW " ", &z);
1338 f->ses->back_size = z;
1339 b = (dev->size.x2 - w) - 16;
1340 if (b < z) b = z;
1341 drv->fill_area(dev, z, 0, b, G_BFU_FONT_SIZE, !proxies.only_proxies ? bfu_bg_color : bfu_fg_color);
1342 g_print_text(dev, b, 0, !proxies.only_proxies ? bfu_style_bw : bfu_style_wb, title, &b);
1343 drv->fill_area(dev, b, 0, dev->size.x2, G_BFU_FONT_SIZE, !proxies.only_proxies ? bfu_bg_color : bfu_fg_color);
1344 mem_free(title);
1345 }
1346
1347 static struct f_data *srch_f_data;
1348
get_searched_sub(struct g_object * p,struct g_object * c)1349 static void get_searched_sub(struct g_object *p, struct g_object *c)
1350 {
1351 if (c->draw == g_text_draw && !g_text_no_search(srch_f_data, get_struct(c, struct g_object_text, goti.go))) {
1352 struct g_object_text *t = get_struct(c, struct g_object_text, goti.go);
1353 int pos = srch_f_data->srch_string_size;
1354 t->srch_pos = pos;
1355 add_to_str(&srch_f_data->srch_string, &srch_f_data->srch_string_size, t->text);
1356 }
1357 if (c->get_list) c->get_list(c, get_searched_sub);
1358 if (c->draw == g_line_draw) {
1359 if (srch_f_data->srch_string_size && srch_f_data->srch_string[srch_f_data->srch_string_size - 1] != ' ')
1360 add_chr_to_str(&srch_f_data->srch_string, &srch_f_data->srch_string_size, ' ');
1361 }
1362 }
1363
g_get_search_data(struct f_data * f)1364 static void g_get_search_data(struct f_data *f)
1365 {
1366 int i;
1367 srch_f_data = f;
1368 if (f->srch_string) return;
1369 f->srch_string = init_str();
1370 f->srch_string_size = 0;
1371 if (f->root && f->root->get_list) f->root->get_list(f->root, get_searched_sub);
1372 while (f->srch_string_size && f->srch_string[f->srch_string_size - 1] == ' ') {
1373 f->srch_string[--f->srch_string_size] = 0;
1374 }
1375 for (i = 0; i < f->srch_string_size; i++) if (f->srch_string[i] == 1) f->srch_string[i] = ' ';
1376 }
1377
1378 struct f_data *fnd_f;
1379 static struct g_object_text *fnd_obj;
1380 static int fnd_x, fnd_y;
1381 static int fnd_obj_dist;
1382
1383 /*
1384 #define dist(a,b) (a<b?b-a:a-b)
1385 */
1386
dist_to_rect(int x,int y,int x1,int y1,int x2,int y2)1387 static inline int dist_to_rect(int x, int y, int x1, int y1, int x2, int y2)
1388 {
1389 int w;
1390 if (x < x1) w = x1 - x;
1391 else if (x > x2) w = x - x2;
1392 else w = 0;
1393 if (y < y1) w += y1 - y;
1394 else if (y > y2) w += y - y2;
1395 return w;
1396 }
1397
find_nearest_sub(struct g_object * p,struct g_object * c)1398 static void find_nearest_sub(struct g_object *p, struct g_object *c)
1399 {
1400 int tx, ty, a;
1401
1402 if (!fnd_obj_dist) return;
1403
1404 get_object_pos(c, &tx, &ty);
1405
1406 a = dist_to_rect(fnd_x, fnd_y, tx, ty, tx+c->xw, ty+c->yw);
1407
1408 if (a >= fnd_obj_dist) return;
1409
1410 if (c->draw == g_text_draw && !g_text_no_search(fnd_f, get_struct(c, struct g_object_text, goti.go))) {
1411
1412 fnd_obj = get_struct(c, struct g_object_text, goti.go);
1413 fnd_obj_dist = a;
1414 }
1415 if (c->get_list == g_area_get_list) {
1416 struct g_object_area *ar = get_struct(c, struct g_object_area, go);
1417 struct g_object_line **ln;
1418 int idx, i, dist;
1419 if (!ar->n_lines) return;
1420 ln = g_find_line(ar->lines, ar->n_lines, fnd_y - ty);
1421 if (!ln) {
1422 if (fnd_y < ty) ln = &ar->lines[0];
1423 else ln = &ar->lines[ar->n_lines - 1];
1424 }
1425 idx = (int)(ln - &ar->lines[0]);
1426 for (i = idx; i < ar->n_lines; i++) {
1427 dist = dist_to_rect(0, fnd_y, 0, ty + ar->lines[i]->go.y, 0, ty + ar->lines[i]->go.y + ar->lines[i]->go.yw);
1428 if (dist >= fnd_obj_dist) break;
1429 find_nearest_sub(NULL, &ar->lines[i]->go);
1430 }
1431 for (i = idx - 1; i >= 0; i--) {
1432 dist = dist_to_rect(0, fnd_y, 0, ty + ar->lines[i]->go.y, 0, ty + ar->lines[i]->go.y + ar->lines[i]->go.yw);
1433 if (dist >= fnd_obj_dist) break;
1434 find_nearest_sub(NULL, &ar->lines[i]->go);
1435 }
1436 return;
1437 }
1438 if (c->get_list) {
1439 c->get_list(c, find_nearest_sub);
1440 }
1441 }
1442
g_find_nearest_object(struct f_data * f,int x,int y)1443 static struct g_object_text * g_find_nearest_object(struct f_data *f, int x, int y)
1444 {
1445 fnd_f = f;
1446 fnd_obj = NULL;
1447 fnd_x = x;
1448 fnd_y = y;
1449 fnd_obj_dist = MAXINT;
1450
1451 if (f->root) find_nearest_sub(NULL, f->root);
1452 return fnd_obj;
1453 }
1454
1455 static unsigned char *search_word;
1456
1457 static int find_refline;
1458 static int find_direction;
1459
1460 static int find_opt_yy;
1461 static int find_opt_y;
1462 static int find_opt_yw;
1463 static int find_opt_x;
1464 static int find_opt_xw;
1465 static struct f_data *find_opt_f_data;
1466
find_next_sub(struct g_object * p,struct g_object * c)1467 static void find_next_sub(struct g_object *p, struct g_object *c)
1468 {
1469 if (c->draw == g_text_draw && !g_text_no_search(find_opt_f_data, get_struct(c, struct g_object_text, goti.go))) {
1470 struct g_object_text *t = get_struct(c, struct g_object_text, goti.go);
1471 int start = t->srch_pos;
1472 int end = t->srch_pos + (int)strlen(cast_const_char t->text);
1473 int found;
1474 BIN_SEARCH(n_highlight_positions, B_EQUAL, B_ABOVE, *, found);
1475 if (found != -1) {
1476 int x, y, yy;
1477 get_object_pos(c, &x, &y);
1478 y += t->goti.go.yw / 2;
1479 yy = y;
1480 if (yy < find_refline) yy += MAXINT / 2;
1481 if (find_direction < 0) yy = MAXINT - yy;
1482 if (find_opt_yy == -1 || yy > find_opt_yy) {
1483 int sx, ex;
1484 unsigned char *tt;
1485 while (found > 0) {
1486 found--;
1487 if (B_EQUAL(found, *)) continue;
1488 found++;
1489 break;
1490 }
1491 find_opt_yy = yy;
1492 find_opt_y = y;
1493 find_opt_yw = t->style->height;
1494 find_opt_x = x;
1495 find_opt_xw = t->goti.go.xw;
1496 if (highlight_positions[found] < start) sx = 0;
1497 else sx = highlight_positions[found] - start;
1498 if (highlight_positions[found] + highlight_lengths[found] > end) ex = end - start;
1499 else ex = highlight_positions[found] + highlight_lengths[found] - start;
1500
1501 tt = memacpy(t->text, sx);
1502 find_opt_x += g_text_width(t->style, tt);
1503 mem_free(tt);
1504 tt = memacpy(t->text + sx, ex - sx);
1505 find_opt_xw = g_text_width(t->style, tt);
1506 mem_free(tt);
1507 }
1508 }
1509 }
1510 if (c->get_list) c->get_list(c, find_next_sub);
1511 }
1512
g_find_next_str(struct f_data * f)1513 static void g_find_next_str(struct f_data *f)
1514 {
1515 find_opt_yy = -1;
1516 find_opt_f_data = f;
1517 if (f->root && f->root->get_list) f->root->get_list(f->root, find_next_sub);
1518 }
1519
g_find_next(struct f_data_c * f,int a)1520 void g_find_next(struct f_data_c *f, int a)
1521 {
1522 g_get_search_data(f->f_data);
1523 g_get_search(f->f_data, f->ses->search_word);
1524 search_word = f->ses->search_word;
1525 if (!f->f_data->n_search_positions) msg_box(f->ses->term, NULL, TEXT_(T_SEARCH), AL_CENTER, TEXT_(T_SEARCH_STRING_NOT_FOUND), MSG_BOX_END, NULL, 1, TEXT_(T_CANCEL), msg_box_null, B_ENTER | B_ESC);
1526
1527 highlight_positions = f->f_data->search_positions;
1528 highlight_lengths = f->f_data->search_lengths;
1529 n_highlight_positions = f->f_data->n_search_positions;
1530
1531 if ((!a && f->ses->search_direction == -1) ||
1532 (a && f->ses->search_direction == 1)) find_refline = f->vs->view_pos;
1533 else find_refline = f->vs->view_pos + f->yw - f->hsb * G_SCROLL_BAR_WIDTH;
1534 find_direction = -f->ses->search_direction;
1535
1536 g_find_next_str(f->f_data);
1537
1538 highlight_positions = NULL;
1539 highlight_lengths = NULL;
1540 n_highlight_positions = 0;
1541
1542 if (find_opt_yy == -1) goto d;
1543 if (!a || find_opt_y < f->vs->view_pos || find_opt_y + find_opt_yw >= f->vs->view_pos + f->yw - f->hsb * G_SCROLL_BAR_WIDTH) {
1544 f->vs->view_pos = find_opt_y - (f->yw - f->hsb * G_SCROLL_BAR_WIDTH) / 2;
1545 f->vs->orig_view_pos = f->vs->view_pos;
1546 }
1547 if (find_opt_x < f->vs->view_posx || find_opt_x + find_opt_xw >= f->vs->view_posx + f->xw - f->vsb * G_SCROLL_BAR_WIDTH) {
1548 f->vs->view_posx = find_opt_x + find_opt_xw / 2 - (f->xw - f->vsb * G_SCROLL_BAR_WIDTH) / 2;
1549 f->vs->orig_view_posx = f->vs->view_posx;
1550 }
1551
1552 d:draw_fd(f);
1553 }
1554
init_grview(void)1555 void init_grview(void)
1556 {
1557 #ifdef DEBUG
1558 int i, w = g_text_width(bfu_style_wb_mono, cast_uchar " ");
1559 for (i = 32; i < 128; i++) {
1560 unsigned char a[2];
1561 a[0] = (unsigned char)i, a[1] = 0;
1562 if (g_text_width(bfu_style_wb_mono, a) != w) internal_error("Monospaced font is not monospaced (error at char %d, width %d, wanted width %d)", i, (int)g_text_width(bfu_style_wb_mono, a), w);
1563 }
1564 #endif
1565 scroll_bar_frame_color = dip_get_color_sRGB(G_SCROLL_BAR_FRAME_COLOR);
1566 scroll_bar_area_color = dip_get_color_sRGB(G_SCROLL_BAR_AREA_COLOR);
1567 scroll_bar_bar_color = dip_get_color_sRGB(G_SCROLL_BAR_BAR_COLOR);
1568 }
1569
1570 #endif
1571