1 /* $Id: display.c,v 1.71 2010/07/18 14:10:09 htrb Exp $ */
2 #include <signal.h>
3 #include "fm.h"
4
5 /* *INDENT-OFF* */
6 #ifdef USE_COLOR
7
8 #define EFFECT_ANCHOR_START effect_anchor_start()
9 #define EFFECT_ANCHOR_END effect_anchor_end()
10 #define EFFECT_IMAGE_START effect_image_start()
11 #define EFFECT_IMAGE_END effect_image_end()
12 #define EFFECT_FORM_START effect_form_start()
13 #define EFFECT_FORM_END effect_form_end()
14 #define EFFECT_ACTIVE_START effect_active_start()
15 #define EFFECT_ACTIVE_END effect_active_end()
16 #define EFFECT_VISITED_START effect_visited_start()
17 #define EFFECT_VISITED_END effect_visited_end()
18 #define EFFECT_MARK_START effect_mark_start()
19 #define EFFECT_MARK_END effect_mark_end()
20
21 /*-
22 * color:
23 * 0 black
24 * 1 red
25 * 2 green
26 * 3 yellow
27 * 4 blue
28 * 5 magenta
29 * 6 cyan
30 * 7 white
31 */
32
33 #define EFFECT_ANCHOR_START_C setfcolor(anchor_color)
34 #define EFFECT_IMAGE_START_C setfcolor(image_color)
35 #define EFFECT_FORM_START_C setfcolor(form_color)
36 #define EFFECT_ACTIVE_START_C (setfcolor(active_color), underline())
37 #define EFFECT_VISITED_START_C setfcolor(visited_color)
38 #ifdef USE_BG_COLOR
39 #define EFFECT_MARK_START_C setbcolor(mark_color)
40 #else
41 #define EFFECT_MARK_START_C standout()
42 #endif
43
44 #define EFFECT_IMAGE_END_C setfcolor(basic_color)
45 #define EFFECT_ANCHOR_END_C setfcolor(basic_color)
46 #define EFFECT_FORM_END_C setfcolor(basic_color)
47 #define EFFECT_ACTIVE_END_C (setfcolor(basic_color), underlineend())
48 #define EFFECT_VISITED_END_C setfcolor(basic_color)
49 #ifdef USE_BG_COLOR
50 #define EFFECT_MARK_END_C setbcolor(bg_color)
51 #else
52 #define EFFECT_MARK_END_C standend()
53 #endif
54
55 #define EFFECT_ANCHOR_START_M underline()
56 #define EFFECT_ANCHOR_END_M underlineend()
57 #define EFFECT_IMAGE_START_M standout()
58 #define EFFECT_IMAGE_END_M standend()
59 #define EFFECT_FORM_START_M standout()
60 #define EFFECT_FORM_END_M standend()
61 #define EFFECT_ACTIVE_START_NC underline()
62 #define EFFECT_ACTIVE_END_NC underlineend()
63 #define EFFECT_ACTIVE_START_M bold()
64 #define EFFECT_ACTIVE_END_M boldend()
65 #define EFFECT_VISITED_START_M /**/
66 #define EFFECT_VISITED_END_M /**/
67 #define EFFECT_MARK_START_M standout()
68 #define EFFECT_MARK_END_M standend()
69 #define define_effect(name_start,name_end,color_start,color_end,mono_start,mono_end) \
70 static void name_start { if (useColor) { color_start; } else { mono_start; }}\
71 static void name_end { if (useColor) { color_end; } else { mono_end; }}
72
define_effect(EFFECT_ANCHOR_START,EFFECT_ANCHOR_END,EFFECT_ANCHOR_START_C,EFFECT_ANCHOR_END_C,EFFECT_ANCHOR_START_M,EFFECT_ANCHOR_END_M)73 define_effect(EFFECT_ANCHOR_START, EFFECT_ANCHOR_END, EFFECT_ANCHOR_START_C,
74 EFFECT_ANCHOR_END_C, EFFECT_ANCHOR_START_M, EFFECT_ANCHOR_END_M)
75 define_effect(EFFECT_IMAGE_START, EFFECT_IMAGE_END, EFFECT_IMAGE_START_C,
76 EFFECT_IMAGE_END_C, EFFECT_IMAGE_START_M, EFFECT_IMAGE_END_M)
77 define_effect(EFFECT_FORM_START, EFFECT_FORM_END, EFFECT_FORM_START_C,
78 EFFECT_FORM_END_C, EFFECT_FORM_START_M, EFFECT_FORM_END_M)
79 define_effect(EFFECT_MARK_START, EFFECT_MARK_END, EFFECT_MARK_START_C,
80 EFFECT_MARK_END_C, EFFECT_MARK_START_M, EFFECT_MARK_END_M)
81
82 /*****************/
83 static void
84 EFFECT_ACTIVE_START
85 {
86 if (useColor) {
87 if (useActiveColor) {
88 #ifdef __EMX__
89 if(!getenv("WINDOWID"))
90 setfcolor(active_color);
91 else
92 #endif
93 {
94 EFFECT_ACTIVE_START_C;
95 }
96 } else {
97 EFFECT_ACTIVE_START_NC;
98 }
99 } else {
100 EFFECT_ACTIVE_START_M;
101 }
102 }
103
104 static void
105 EFFECT_ACTIVE_END
106 {
107 if (useColor) {
108 if (useActiveColor) {
109 EFFECT_ACTIVE_END_C;
110 } else {
111 EFFECT_ACTIVE_END_NC;
112 }
113 } else {
114 EFFECT_ACTIVE_END_M;
115 }
116 }
117
118 static void
119 EFFECT_VISITED_START
120 {
121 if (useVisitedColor) {
122 if (useColor) {
123 EFFECT_VISITED_START_C;
124 } else {
125 EFFECT_VISITED_START_M;
126 }
127 }
128 }
129
130 static void
131 EFFECT_VISITED_END
132 {
133 if (useVisitedColor) {
134 if (useColor) {
135 EFFECT_VISITED_END_C;
136 } else {
137 EFFECT_VISITED_END_M;
138 }
139 }
140 }
141
142 #else /* not USE_COLOR */
143
144 #define EFFECT_ANCHOR_START underline()
145 #define EFFECT_ANCHOR_END underlineend()
146 #define EFFECT_IMAGE_START standout()
147 #define EFFECT_IMAGE_END standend()
148 #define EFFECT_FORM_START standout()
149 #define EFFECT_FORM_END standend()
150 #define EFFECT_ACTIVE_START bold()
151 #define EFFECT_ACTIVE_END boldend()
152 #define EFFECT_VISITED_START /**/
153 #define EFFECT_VISITED_END /**/
154 #define EFFECT_MARK_START standout()
155 #define EFFECT_MARK_END standend()
156 #endif /* not USE_COLOR */
157 /* *INDENT-ON* */
158
159 void
fmTerm(void)160 fmTerm(void)
161 {
162 if (fmInitialized) {
163 move(LASTLINE, 0);
164 clrtoeolx();
165 refresh();
166 #ifdef USE_IMAGE
167 if (activeImage)
168 loadImage(NULL, IMG_FLAG_STOP);
169 #endif
170 #ifdef USE_MOUSE
171 if (use_mouse)
172 mouse_end();
173 #endif /* USE_MOUSE */
174 reset_tty();
175 fmInitialized = FALSE;
176 }
177 }
178
179
180 /*
181 * Initialize routine.
182 */
183 void
fmInit(void)184 fmInit(void)
185 {
186 if (!fmInitialized) {
187 initscr();
188 term_raw();
189 term_noecho();
190 #ifdef USE_IMAGE
191 if (displayImage)
192 initImage();
193 #endif
194 }
195 fmInitialized = TRUE;
196 }
197
198 /*
199 * Display some lines.
200 */
201 static Line *cline = NULL;
202 static int ccolumn = -1;
203
204 static int ulmode = 0, somode = 0, bomode = 0;
205 static int anch_mode = 0, emph_mode = 0, imag_mode = 0, form_mode = 0,
206 active_mode = 0, visited_mode = 0, mark_mode = 0, graph_mode = 0;
207 #ifdef USE_ANSI_COLOR
208 static Linecolor color_mode = 0;
209 #endif
210
211 #ifdef USE_BUFINFO
212 static Buffer *save_current_buf = NULL;
213 #endif
214
215 static char *delayed_msg = NULL;
216
217 static void drawAnchorCursor(Buffer *buf);
218 #define redrawBuffer(buf) redrawNLine(buf, LASTLINE)
219 static void redrawNLine(Buffer *buf, int n);
220 static Line *redrawLine(Buffer *buf, Line *l, int i);
221 #ifdef USE_IMAGE
222 static int image_touch = 0;
223 static int draw_image_flag = FALSE;
224 static Line *redrawLineImage(Buffer *buf, Line *l, int i);
225 #endif
226 static int redrawLineRegion(Buffer *buf, Line *l, int i, int bpos, int epos);
227 static void do_effects(Lineprop m);
228 #ifdef USE_ANSI_COLOR
229 static void do_color(Linecolor c);
230 #endif
231
232 static Str
make_lastline_link(Buffer * buf,char * title,char * url)233 make_lastline_link(Buffer *buf, char *title, char *url)
234 {
235 Str s = NULL, u;
236 #ifdef USE_M17N
237 Lineprop *pr;
238 #endif
239 ParsedURL pu;
240 char *p;
241 int l = COLS - 1, i;
242
243 if (title && *title) {
244 s = Strnew_m_charp("[", title, "]", NULL);
245 for (p = s->ptr; *p; p++) {
246 if (IS_CNTRL(*p) || IS_SPACE(*p))
247 *p = ' ';
248 }
249 if (url)
250 Strcat_charp(s, " ");
251 l -= get_Str_strwidth(s);
252 if (l <= 0)
253 return s;
254 }
255 if (!url)
256 return s;
257 parseURL2(url, &pu, baseURL(buf));
258 u = parsedURL2Str(&pu);
259 if (DecodeURL)
260 u = Strnew_charp(url_decode2(u->ptr, buf));
261 #ifdef USE_M17N
262 u = checkType(u, &pr, NULL);
263 #endif
264 if (l <= 4 || l >= get_Str_strwidth(u)) {
265 if (!s)
266 return u;
267 Strcat(s, u);
268 return s;
269 }
270 if (!s)
271 s = Strnew_size(COLS);
272 i = (l - 2) / 2;
273 #ifdef USE_M17N
274 while (i && pr[i] & PC_WCHAR2)
275 i--;
276 #endif
277 Strcat_charp_n(s, u->ptr, i);
278 Strcat_charp(s, "..");
279 i = get_Str_strwidth(u) - (COLS - 1 - get_Str_strwidth(s));
280 #ifdef USE_M17N
281 while (i < u->length && pr[i] & PC_WCHAR2)
282 i++;
283 #endif
284 Strcat_charp(s, &u->ptr[i]);
285 return s;
286 }
287
288 static Str
make_lastline_message(Buffer * buf)289 make_lastline_message(Buffer *buf)
290 {
291 Str msg, s = NULL;
292 int sl = 0;
293
294 if (displayLink) {
295 #ifdef USE_IMAGE
296 MapArea *a = retrieveCurrentMapArea(buf);
297 if (a)
298 s = make_lastline_link(buf, a->alt, a->url);
299 else
300 #endif
301 {
302 Anchor *a = retrieveCurrentAnchor(buf);
303 char *p = NULL;
304 if (a && a->title && *a->title)
305 p = a->title;
306 else {
307 Anchor *a_img = retrieveCurrentImg(buf);
308 if (a_img && a_img->title && *a_img->title)
309 p = a_img->title;
310 }
311 if (p || a)
312 s = make_lastline_link(buf, p, a ? a->url : NULL);
313 }
314 if (s) {
315 sl = get_Str_strwidth(s);
316 if (sl >= COLS - 3)
317 return s;
318 }
319 }
320
321 #ifdef USE_MOUSE
322 if (use_mouse && mouse_action.lastline_str)
323 msg = Strnew_charp(mouse_action.lastline_str);
324 else
325 #endif /* not USE_MOUSE */
326 msg = Strnew();
327 if (displayLineInfo && buf->currentLine != NULL && buf->lastLine != NULL) {
328 int cl = buf->currentLine->real_linenumber;
329 int ll = buf->lastLine->real_linenumber;
330 int r = (int)((double)cl * 100.0 / (double)(ll ? ll : 1) + 0.5);
331 Strcat(msg, Sprintf("%d/%d (%d%%)", cl, ll, r));
332 }
333 else
334 /* FIXME: gettextize? */
335 Strcat_charp(msg, "Viewing");
336 #ifdef USE_SSL
337 if (buf->ssl_certificate)
338 Strcat_charp(msg, "[SSL]");
339 #endif
340 Strcat_charp(msg, " <");
341 Strcat_charp(msg, buf->buffername);
342
343 if (s) {
344 int l = COLS - 3 - sl;
345 if (get_Str_strwidth(msg) > l) {
346 #ifdef USE_M17N
347 char *p;
348 for (p = msg->ptr; *p; p += get_mclen(p)) {
349 l -= get_mcwidth(p);
350 if (l < 0)
351 break;
352 }
353 l = p - msg->ptr;
354 #endif
355 Strtruncate(msg, l);
356 }
357 Strcat_charp(msg, "> ");
358 Strcat(msg, s);
359 }
360 else {
361 Strcat_charp(msg, ">");
362 }
363 return msg;
364 }
365
366 void
displayBuffer(Buffer * buf,int mode)367 displayBuffer(Buffer *buf, int mode)
368 {
369 Str msg;
370 int ny = 0;
371
372 if (!buf)
373 return;
374 if (buf->topLine == NULL && readBufferCache(buf) == 0) { /* clear_buffer */
375 mode = B_FORCE_REDRAW;
376 }
377
378 if (buf->width == 0)
379 buf->width = INIT_BUFFER_WIDTH;
380 if (buf->height == 0)
381 buf->height = LASTLINE + 1;
382 if ((buf->width != INIT_BUFFER_WIDTH &&
383 (is_html_type(buf->type) || FoldLine))
384 || buf->need_reshape) {
385 buf->need_reshape = TRUE;
386 reshapeBuffer(buf);
387 }
388 if (showLineNum) {
389 if (buf->lastLine && buf->lastLine->real_linenumber > 0)
390 buf->rootX = (int)(log(buf->lastLine->real_linenumber + 0.1)
391 / log(10)) + 2;
392 if (buf->rootX < 5)
393 buf->rootX = 5;
394 if (buf->rootX > COLS)
395 buf->rootX = COLS;
396 }
397 else
398 buf->rootX = 0;
399 buf->COLS = COLS - buf->rootX;
400 if (nTab > 1
401 #ifdef USE_MOUSE
402 || mouse_action.menu_str
403 #endif
404 ) {
405 if (mode == B_FORCE_REDRAW || mode == B_REDRAW_IMAGE)
406 calcTabPos();
407 ny = LastTab->y + 2;
408 if (ny > LASTLINE)
409 ny = LASTLINE;
410 }
411 if (buf->rootY != ny || buf->LINES != LASTLINE - ny) {
412 buf->rootY = ny;
413 buf->LINES = LASTLINE - ny;
414 arrangeCursor(buf);
415 mode = B_REDRAW_IMAGE;
416 }
417 if (mode == B_FORCE_REDRAW || mode == B_SCROLL || mode == B_REDRAW_IMAGE ||
418 cline != buf->topLine || ccolumn != buf->currentColumn) {
419 #ifdef USE_RAW_SCROLL
420 if (
421 #ifdef USE_IMAGE
422 !(activeImage && displayImage && draw_image_flag) &&
423 #endif
424 mode == B_SCROLL && cline && buf->currentColumn == ccolumn) {
425 int n = buf->topLine->linenumber - cline->linenumber;
426 if (n > 0 && n < buf->LINES) {
427 move(LASTLINE, 0);
428 clrtoeolx();
429 refresh();
430 scroll(n);
431 }
432 else if (n < 0 && n > -buf->LINES) {
433 #if 0 /* defined(__CYGWIN__) */
434 move(LASTLINE + n + 1, 0);
435 clrtoeolx();
436 refresh();
437 #endif /* defined(__CYGWIN__) */
438 rscroll(-n);
439 }
440 redrawNLine(buf, n);
441 }
442 else
443 #endif
444 {
445 #ifdef USE_IMAGE
446 if (activeImage &&
447 (mode == B_REDRAW_IMAGE ||
448 cline != buf->topLine || ccolumn != buf->currentColumn)) {
449 if (draw_image_flag)
450 clear();
451 clearImage();
452 loadImage(buf, IMG_FLAG_STOP);
453 image_touch++;
454 draw_image_flag = FALSE;
455 }
456 #endif
457 redrawBuffer(buf);
458 }
459 cline = buf->topLine;
460 ccolumn = buf->currentColumn;
461 }
462 if (buf->topLine == NULL)
463 buf->topLine = buf->firstLine;
464
465 #ifdef USE_IMAGE
466 if (buf->need_reshape) {
467 displayBuffer(buf, B_FORCE_REDRAW);
468 return;
469 }
470 #endif
471
472 drawAnchorCursor(buf);
473
474 msg = make_lastline_message(buf);
475 if (buf->firstLine == NULL) {
476 /* FIXME: gettextize? */
477 Strcat_charp(msg, "\tNo Line");
478 }
479 if (delayed_msg != NULL) {
480 disp_message(delayed_msg, FALSE);
481 delayed_msg = NULL;
482 refresh();
483 }
484 standout();
485 message(msg->ptr, buf->cursorX + buf->rootX, buf->cursorY + buf->rootY);
486 standend();
487 term_title(conv_to_system(buf->buffername));
488 refresh();
489 #ifdef USE_IMAGE
490 if (activeImage && displayImage && buf->img && buf->image_loaded) {
491 drawImage();
492 }
493 #endif
494 #ifdef USE_BUFINFO
495 if (buf != save_current_buf) {
496 saveBufferInfo();
497 save_current_buf = buf;
498 }
499 #endif
500 if (mode == B_FORCE_REDRAW && (buf->check_url & CHK_URL) ) {
501 chkURLBuffer(buf);
502 displayBuffer(buf, B_NORMAL);
503 }
504 }
505
506 static void
drawAnchorCursor0(Buffer * buf,AnchorList * al,int hseq,int prevhseq,int tline,int eline,int active)507 drawAnchorCursor0(Buffer *buf, AnchorList *al, int hseq, int prevhseq,
508 int tline, int eline, int active)
509 {
510 int i, j;
511 Line *l;
512 Anchor *an;
513
514 l = buf->topLine;
515 for (j = 0; j < al->nanchor; j++) {
516 an = &al->anchors[j];
517 if (an->start.line < tline)
518 continue;
519 if (an->start.line >= eline)
520 return;
521 for (;; l = l->next) {
522 if (l == NULL)
523 return;
524 if (l->linenumber == an->start.line)
525 break;
526 }
527 if (hseq >= 0 && an->hseq == hseq) {
528 int start_pos = an->start.pos;
529 int end_pos = an->end.pos;
530 for (i = an->start.pos; i < an->end.pos; i++) {
531 if (enable_inline_image && (l->propBuf[i] & PE_IMAGE)) {
532 if (start_pos == i)
533 start_pos = i + 1;
534 else if (end_pos == an->end.pos)
535 end_pos = i - 1;
536 }
537 if (l->propBuf[i] & (PE_IMAGE | PE_ANCHOR | PE_FORM)) {
538 if (active)
539 l->propBuf[i] |= PE_ACTIVE;
540 else
541 l->propBuf[i] &= ~PE_ACTIVE;
542 }
543 }
544 if (active && start_pos < end_pos)
545 redrawLineRegion(buf, l, l->linenumber - tline + buf->rootY,
546 start_pos, end_pos);
547 }
548 else if (prevhseq >= 0 && an->hseq == prevhseq) {
549 if (active)
550 redrawLineRegion(buf, l, l->linenumber - tline + buf->rootY,
551 an->start.pos, an->end.pos);
552 }
553 }
554 }
555
556 static void
drawAnchorCursor(Buffer * buf)557 drawAnchorCursor(Buffer *buf)
558 {
559 Anchor *an;
560 int hseq, prevhseq;
561 int tline, eline;
562
563 if (!buf->firstLine || !buf->hmarklist)
564 return;
565 if (!buf->href && !buf->formitem)
566 return;
567
568 an = retrieveCurrentAnchor(buf);
569 if (!an)
570 an = retrieveCurrentMap(buf);
571 if (an)
572 hseq = an->hseq;
573 else
574 hseq = -1;
575 tline = buf->topLine->linenumber;
576 eline = tline + buf->LINES;
577 prevhseq = buf->hmarklist->prevhseq;
578
579 if (buf->href) {
580 drawAnchorCursor0(buf, buf->href, hseq, prevhseq, tline, eline, 1);
581 drawAnchorCursor0(buf, buf->href, hseq, -1, tline, eline, 0);
582 }
583 if (buf->formitem) {
584 drawAnchorCursor0(buf, buf->formitem, hseq, prevhseq, tline, eline, 1);
585 drawAnchorCursor0(buf, buf->formitem, hseq, -1, tline, eline, 0);
586 }
587 buf->hmarklist->prevhseq = hseq;
588 }
589
590 static void
redrawNLine(Buffer * buf,int n)591 redrawNLine(Buffer *buf, int n)
592 {
593 Line *l;
594 int i;
595
596 #ifdef USE_COLOR
597 if (useColor) {
598 EFFECT_ANCHOR_END_C;
599 #ifdef USE_BG_COLOR
600 setbcolor(bg_color);
601 #endif /* USE_BG_COLOR */
602 }
603 #endif /* USE_COLOR */
604 if (nTab > 1
605 #ifdef USE_MOUSE
606 || mouse_action.menu_str
607 #endif
608 ) {
609 TabBuffer *t;
610 int l;
611
612 move(0, 0);
613 #ifdef USE_MOUSE
614 if (mouse_action.menu_str)
615 addstr(mouse_action.menu_str);
616 #endif
617 clrtoeolx();
618 for (t = FirstTab; t; t = t->nextTab) {
619 move(t->y, t->x1);
620 if (t == CurrentTab)
621 bold();
622 addch('[');
623 l = t->x2 - t->x1 - 1 - get_strwidth(t->currentBuffer->buffername);
624 if (l < 0)
625 l = 0;
626 if (l / 2 > 0)
627 addnstr_sup(" ", l / 2);
628 if (t == CurrentTab)
629 EFFECT_ACTIVE_START;
630 addnstr(t->currentBuffer->buffername, t->x2 - t->x1 - l);
631 if (t == CurrentTab)
632 EFFECT_ACTIVE_END;
633 if ((l + 1) / 2 > 0)
634 addnstr_sup(" ", (l + 1) / 2);
635 move(t->y, t->x2);
636 addch(']');
637 if (t == CurrentTab)
638 boldend();
639 }
640 #if 0
641 move(0, COLS - 2);
642 addstr(" x");
643 #endif
644 move(LastTab->y + 1, 0);
645 for (i = 0; i < COLS; i++)
646 addch('~');
647 }
648 for (i = 0, l = buf->topLine; i < buf->LINES; i++, l = l->next) {
649 if (i >= buf->LINES - n || i < -n)
650 l = redrawLine(buf, l, i + buf->rootY);
651 if (l == NULL)
652 break;
653 }
654 if (n > 0) {
655 move(i + buf->rootY, 0);
656 clrtobotx();
657 }
658
659 #ifdef USE_IMAGE
660 if (!(activeImage && displayImage && buf->img))
661 return;
662 move(buf->cursorY + buf->rootY, buf->cursorX + buf->rootX);
663 for (i = 0, l = buf->topLine; i < buf->LINES && l; i++, l = l->next) {
664 if (i >= buf->LINES - n || i < -n)
665 redrawLineImage(buf, l, i + buf->rootY);
666 }
667 getAllImage(buf);
668 #endif
669 }
670
671 static Line *
redrawLine(Buffer * buf,Line * l,int i)672 redrawLine(Buffer *buf, Line *l, int i)
673 {
674 int j, pos, rcol, ncol, delta = 1;
675 int column = buf->currentColumn;
676 char *p;
677 Lineprop *pr;
678 #ifdef USE_ANSI_COLOR
679 Linecolor *pc;
680 #endif
681 #ifdef USE_COLOR
682 Anchor *a;
683 ParsedURL url;
684 int k, vpos = -1;
685 #endif
686
687 if (l == NULL) {
688 if (buf->pagerSource) {
689 l = getNextPage(buf, buf->LINES + buf->rootY - i);
690 if (l == NULL)
691 return NULL;
692 }
693 else
694 return NULL;
695 }
696 move(i, 0);
697 if (showLineNum) {
698 char tmp[16];
699 if (!buf->rootX) {
700 if (buf->lastLine->real_linenumber > 0)
701 buf->rootX = (int)(log(buf->lastLine->real_linenumber + 0.1)
702 / log(10)) + 2;
703 if (buf->rootX < 5)
704 buf->rootX = 5;
705 if (buf->rootX > COLS)
706 buf->rootX = COLS;
707 buf->COLS = COLS - buf->rootX;
708 }
709 if (l->real_linenumber && !l->bpos)
710 sprintf(tmp, "%*ld:", buf->rootX - 1, l->real_linenumber);
711 else
712 sprintf(tmp, "%*s ", buf->rootX - 1, "");
713 addstr(tmp);
714 }
715 move(i, buf->rootX);
716 if (l->width < 0)
717 l->width = COLPOS(l, l->len);
718 if (l->len == 0 || l->width - 1 < column) {
719 clrtoeolx();
720 return l;
721 }
722 /* need_clrtoeol(); */
723 pos = columnPos(l, column);
724 p = &(l->lineBuf[pos]);
725 pr = &(l->propBuf[pos]);
726 #ifdef USE_ANSI_COLOR
727 if (useColor && l->colorBuf)
728 pc = &(l->colorBuf[pos]);
729 else
730 pc = NULL;
731 #endif
732 rcol = COLPOS(l, pos);
733
734 for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j += delta) {
735 #ifdef USE_COLOR
736 if (useVisitedColor && vpos <= pos + j && !(pr[j] & PE_VISITED)) {
737 a = retrieveAnchor(buf->href, l->linenumber, pos + j);
738 if (a) {
739 parseURL2(a->url, &url, baseURL(buf));
740 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) {
741 for (k = a->start.pos; k < a->end.pos; k++)
742 pr[k - pos] |= PE_VISITED;
743 }
744 vpos = a->end.pos;
745 }
746 }
747 #endif
748 #ifdef USE_M17N
749 delta = wtf_len((wc_uchar *) & p[j]);
750 #endif
751 ncol = COLPOS(l, pos + j + delta);
752 if (ncol - column > buf->COLS)
753 break;
754 #ifdef USE_ANSI_COLOR
755 if (pc)
756 do_color(pc[j]);
757 #endif
758 if (rcol < column) {
759 for (rcol = column; rcol < ncol; rcol++)
760 addChar(' ', 0);
761 continue;
762 }
763 if (p[j] == '\t') {
764 for (; rcol < ncol; rcol++)
765 addChar(' ', 0);
766 }
767 else {
768 #ifdef USE_M17N
769 addMChar(&p[j], pr[j], delta);
770 #else
771 addChar(p[j], pr[j]);
772 #endif
773 }
774 rcol = ncol;
775 }
776 if (somode) {
777 somode = FALSE;
778 standend();
779 }
780 if (ulmode) {
781 ulmode = FALSE;
782 underlineend();
783 }
784 if (bomode) {
785 bomode = FALSE;
786 boldend();
787 }
788 if (emph_mode) {
789 emph_mode = FALSE;
790 boldend();
791 }
792
793 if (anch_mode) {
794 anch_mode = FALSE;
795 EFFECT_ANCHOR_END;
796 }
797 if (imag_mode) {
798 imag_mode = FALSE;
799 EFFECT_IMAGE_END;
800 }
801 if (form_mode) {
802 form_mode = FALSE;
803 EFFECT_FORM_END;
804 }
805 if (visited_mode) {
806 visited_mode = FALSE;
807 EFFECT_VISITED_END;
808 }
809 if (active_mode) {
810 active_mode = FALSE;
811 EFFECT_ACTIVE_END;
812 }
813 if (mark_mode) {
814 mark_mode = FALSE;
815 EFFECT_MARK_END;
816 }
817 if (graph_mode) {
818 graph_mode = FALSE;
819 graphend();
820 }
821 #ifdef USE_ANSI_COLOR
822 if (color_mode)
823 do_color(0);
824 #endif
825 if (rcol - column < buf->COLS)
826 clrtoeolx();
827 return l;
828 }
829
830 #ifdef USE_IMAGE
831 static Line *
redrawLineImage(Buffer * buf,Line * l,int i)832 redrawLineImage(Buffer *buf, Line *l, int i)
833 {
834 int j, pos, rcol;
835 int column = buf->currentColumn;
836 Anchor *a;
837 int x, y, sx, sy, w, h;
838
839 if (l == NULL)
840 return NULL;
841 if (l->width < 0)
842 l->width = COLPOS(l, l->len);
843 if (l->len == 0 || l->width - 1 < column)
844 return l;
845 pos = columnPos(l, column);
846 rcol = COLPOS(l, pos);
847 for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j++) {
848 if (rcol - column < 0) {
849 rcol = COLPOS(l, pos + j + 1);
850 continue;
851 }
852 a = retrieveAnchor(buf->img, l->linenumber, pos + j);
853 if (a && a->image && a->image->touch < image_touch) {
854 Image *image = a->image;
855 ImageCache *cache;
856
857 cache = image->cache = getImage(image, baseURL(buf),
858 buf->image_flag);
859 if (cache) {
860 if ((image->width < 0 && cache->width > 0) ||
861 (image->height < 0 && cache->height > 0)) {
862 image->width = cache->width;
863 image->height = cache->height;
864 buf->need_reshape = TRUE;
865 }
866 x = (int)((rcol - column + buf->rootX) * pixel_per_char);
867 y = (int)(i * pixel_per_line);
868 sx = (int)((rcol - COLPOS(l, a->start.pos)) * pixel_per_char);
869 sy = (int)((l->linenumber - image->y) * pixel_per_line);
870 if (! enable_inline_image) {
871 if (sx == 0 && x + image->xoffset >= 0)
872 x += image->xoffset;
873 else
874 sx -= image->xoffset;
875 if (sy == 0 && y + image->yoffset >= 0)
876 y += image->yoffset;
877 else
878 sy -= image->yoffset;
879 }
880 if (image->width > 0)
881 w = image->width - sx;
882 else
883 w = (int)(8 * pixel_per_char - sx);
884 if (image->height > 0)
885 h = image->height - sy;
886 else
887 h = (int)(pixel_per_line - sy);
888 if (w > (int)((buf->rootX + buf->COLS) * pixel_per_char - x))
889 w = (int)((buf->rootX + buf->COLS) * pixel_per_char - x);
890 if (h > (int)(LASTLINE * pixel_per_line - y))
891 h = (int)(LASTLINE * pixel_per_line - y);
892 addImage(cache, x, y, sx, sy, w, h);
893 image->touch = image_touch;
894 draw_image_flag = TRUE;
895 }
896 }
897 rcol = COLPOS(l, pos + j + 1);
898 }
899 return l;
900 }
901 #endif
902
903 static int
redrawLineRegion(Buffer * buf,Line * l,int i,int bpos,int epos)904 redrawLineRegion(Buffer *buf, Line *l, int i, int bpos, int epos)
905 {
906 int j, pos, rcol, ncol, delta = 1;
907 int column = buf->currentColumn;
908 char *p;
909 Lineprop *pr;
910 #ifdef USE_ANSI_COLOR
911 Linecolor *pc;
912 #endif
913 int bcol, ecol;
914 #ifdef USE_COLOR
915 Anchor *a;
916 ParsedURL url;
917 int k, vpos = -1;
918 #endif
919
920 if (l == NULL)
921 return 0;
922 pos = columnPos(l, column);
923 p = &(l->lineBuf[pos]);
924 pr = &(l->propBuf[pos]);
925 #ifdef USE_ANSI_COLOR
926 if (useColor && l->colorBuf)
927 pc = &(l->colorBuf[pos]);
928 else
929 pc = NULL;
930 #endif
931 rcol = COLPOS(l, pos);
932 bcol = bpos - pos;
933 ecol = epos - pos;
934
935 for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j += delta) {
936 #ifdef USE_COLOR
937 if (useVisitedColor && vpos <= pos + j && !(pr[j] & PE_VISITED)) {
938 a = retrieveAnchor(buf->href, l->linenumber, pos + j);
939 if (a) {
940 parseURL2(a->url, &url, baseURL(buf));
941 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) {
942 for (k = a->start.pos; k < a->end.pos; k++)
943 pr[k - pos] |= PE_VISITED;
944 }
945 vpos = a->end.pos;
946 }
947 }
948 #endif
949 #ifdef USE_M17N
950 delta = wtf_len((wc_uchar *) & p[j]);
951 #endif
952 ncol = COLPOS(l, pos + j + delta);
953 if (ncol - column > buf->COLS)
954 break;
955 #ifdef USE_ANSI_COLOR
956 if (pc)
957 do_color(pc[j]);
958 #endif
959 if (j >= bcol && j < ecol) {
960 if (rcol < column) {
961 move(i, buf->rootX);
962 for (rcol = column; rcol < ncol; rcol++)
963 addChar(' ', 0);
964 continue;
965 }
966 move(i, rcol - column + buf->rootX);
967 if (p[j] == '\t') {
968 for (; rcol < ncol; rcol++)
969 addChar(' ', 0);
970 }
971 else
972 #ifdef USE_M17N
973 addMChar(&p[j], pr[j], delta);
974 #else
975 addChar(p[j], pr[j]);
976 #endif
977 }
978 rcol = ncol;
979 }
980 if (somode) {
981 somode = FALSE;
982 standend();
983 }
984 if (ulmode) {
985 ulmode = FALSE;
986 underlineend();
987 }
988 if (bomode) {
989 bomode = FALSE;
990 boldend();
991 }
992 if (emph_mode) {
993 emph_mode = FALSE;
994 boldend();
995 }
996
997 if (anch_mode) {
998 anch_mode = FALSE;
999 EFFECT_ANCHOR_END;
1000 }
1001 if (imag_mode) {
1002 imag_mode = FALSE;
1003 EFFECT_IMAGE_END;
1004 }
1005 if (form_mode) {
1006 form_mode = FALSE;
1007 EFFECT_FORM_END;
1008 }
1009 if (visited_mode) {
1010 visited_mode = FALSE;
1011 EFFECT_VISITED_END;
1012 }
1013 if (active_mode) {
1014 active_mode = FALSE;
1015 EFFECT_ACTIVE_END;
1016 }
1017 if (mark_mode) {
1018 mark_mode = FALSE;
1019 EFFECT_MARK_END;
1020 }
1021 if (graph_mode) {
1022 graph_mode = FALSE;
1023 graphend();
1024 }
1025 #ifdef USE_ANSI_COLOR
1026 if (color_mode)
1027 do_color(0);
1028 #endif
1029 return rcol - column;
1030 }
1031
1032 #define do_effect1(effect,modeflag,action_start,action_end) \
1033 if (m & effect) { \
1034 if (!modeflag) { \
1035 action_start; \
1036 modeflag = TRUE; \
1037 } \
1038 }
1039
1040 #define do_effect2(effect,modeflag,action_start,action_end) \
1041 if (modeflag) { \
1042 action_end; \
1043 modeflag = FALSE; \
1044 }
1045
1046 static void
do_effects(Lineprop m)1047 do_effects(Lineprop m)
1048 {
1049 /* effect end */
1050 do_effect2(PE_UNDER, ulmode, underline(), underlineend());
1051 do_effect2(PE_STAND, somode, standout(), standend());
1052 do_effect2(PE_BOLD, bomode, bold(), boldend());
1053 do_effect2(PE_EMPH, emph_mode, bold(), boldend());
1054 do_effect2(PE_ANCHOR, anch_mode, EFFECT_ANCHOR_START, EFFECT_ANCHOR_END);
1055 do_effect2(PE_IMAGE, imag_mode, EFFECT_IMAGE_START, EFFECT_IMAGE_END);
1056 do_effect2(PE_FORM, form_mode, EFFECT_FORM_START, EFFECT_FORM_END);
1057 do_effect2(PE_VISITED, visited_mode, EFFECT_VISITED_START,
1058 EFFECT_VISITED_END);
1059 do_effect2(PE_ACTIVE, active_mode, EFFECT_ACTIVE_START, EFFECT_ACTIVE_END);
1060 do_effect2(PE_MARK, mark_mode, EFFECT_MARK_START, EFFECT_MARK_END);
1061 if (graph_mode) {
1062 graphend();
1063 graph_mode = FALSE;
1064 }
1065
1066 /* effect start */
1067 do_effect1(PE_UNDER, ulmode, underline(), underlineend());
1068 do_effect1(PE_STAND, somode, standout(), standend());
1069 do_effect1(PE_BOLD, bomode, bold(), boldend());
1070 do_effect1(PE_EMPH, emph_mode, bold(), boldend());
1071 do_effect1(PE_ANCHOR, anch_mode, EFFECT_ANCHOR_START, EFFECT_ANCHOR_END);
1072 do_effect1(PE_IMAGE, imag_mode, EFFECT_IMAGE_START, EFFECT_IMAGE_END);
1073 do_effect1(PE_FORM, form_mode, EFFECT_FORM_START, EFFECT_FORM_END);
1074 do_effect1(PE_VISITED, visited_mode, EFFECT_VISITED_START,
1075 EFFECT_VISITED_END);
1076 do_effect1(PE_ACTIVE, active_mode, EFFECT_ACTIVE_START, EFFECT_ACTIVE_END);
1077 do_effect1(PE_MARK, mark_mode, EFFECT_MARK_START, EFFECT_MARK_END);
1078 }
1079
1080 #ifdef USE_ANSI_COLOR
1081 static void
do_color(Linecolor c)1082 do_color(Linecolor c)
1083 {
1084 if (c & 0x8)
1085 setfcolor(c & 0x7);
1086 else if (color_mode & 0x8)
1087 setfcolor(basic_color);
1088 #ifdef USE_BG_COLOR
1089 if (c & 0x80)
1090 setbcolor((c >> 4) & 0x7);
1091 else if (color_mode & 0x80)
1092 setbcolor(bg_color);
1093 #endif
1094 color_mode = c;
1095 }
1096 #endif
1097
1098 #ifdef USE_M17N
1099 void
addChar(char c,Lineprop mode)1100 addChar(char c, Lineprop mode)
1101 {
1102 addMChar(&c, mode, 1);
1103 }
1104
1105 void
addMChar(char * p,Lineprop mode,size_t len)1106 addMChar(char *p, Lineprop mode, size_t len)
1107 #else
1108 void
1109 addChar(char c, Lineprop mode)
1110 #endif
1111 {
1112 Lineprop m = CharEffect(mode);
1113 #ifdef USE_M17N
1114 char c = *p;
1115
1116 if (mode & PC_WCHAR2)
1117 return;
1118 #endif
1119 do_effects(m);
1120 if (mode & PC_SYMBOL) {
1121 char **symbol;
1122 #ifdef USE_M17N
1123 int w = (mode & PC_KANJI) ? 2 : 1;
1124
1125 c = ((char)wtf_get_code((wc_uchar *) p) & 0x7f) - SYMBOL_BASE;
1126 #else
1127 c -= SYMBOL_BASE;
1128 #endif
1129 if (graph_ok() && c < N_GRAPH_SYMBOL) {
1130 if (!graph_mode) {
1131 graphstart();
1132 graph_mode = TRUE;
1133 }
1134 #ifdef USE_M17N
1135 if (w == 2 && WcOption.use_wide)
1136 addstr(graph2_symbol[(unsigned char)c % N_GRAPH_SYMBOL]);
1137 else
1138 #endif
1139 addch(*graph_symbol[(unsigned char)c % N_GRAPH_SYMBOL]);
1140 }
1141 else {
1142 #ifdef USE_M17N
1143 symbol = get_symbol(DisplayCharset, &w);
1144 addstr(symbol[(unsigned char)c % N_SYMBOL]);
1145 #else
1146 symbol = get_symbol();
1147 addch(*symbol[(unsigned char)c % N_SYMBOL]);
1148 #endif
1149 }
1150 }
1151 else if (mode & PC_CTRL) {
1152 switch (c) {
1153 case '\t':
1154 addch(c);
1155 break;
1156 case '\n':
1157 addch(' ');
1158 break;
1159 case '\r':
1160 break;
1161 case DEL_CODE:
1162 addstr("^?");
1163 break;
1164 default:
1165 addch('^');
1166 addch(c + '@');
1167 break;
1168 }
1169 }
1170 #ifdef USE_M17N
1171 else if (mode & PC_UNKNOWN) {
1172 char buf[5];
1173 sprintf(buf, "[%.2X]",
1174 (unsigned char)wtf_get_code((wc_uchar *) p) | 0x80);
1175 addstr(buf);
1176 }
1177 else
1178 addmch(p, len);
1179 #else
1180 else if (0x80 <= (unsigned char)c && (unsigned char)c <= NBSP_CODE)
1181 addch(' ');
1182 else
1183 addch(c);
1184 #endif
1185 }
1186
1187 static GeneralList *message_list = NULL;
1188
1189 void
record_err_message(char * s)1190 record_err_message(char *s)
1191 {
1192 if (fmInitialized) {
1193 if (!message_list)
1194 message_list = newGeneralList();
1195 if (message_list->nitem >= LINES)
1196 popValue(message_list);
1197 pushValue(message_list, allocStr(s, -1));
1198 }
1199 }
1200
1201 /*
1202 * List of error messages
1203 */
1204 Buffer *
message_list_panel(void)1205 message_list_panel(void)
1206 {
1207 Str tmp = Strnew_size(LINES * COLS);
1208 ListItem *p;
1209
1210 /* FIXME: gettextize? */
1211 Strcat_charp(tmp,
1212 "<html><head><title>List of error messages</title></head><body>"
1213 "<h1>List of error messages</h1><table cellpadding=0>\n");
1214 if (message_list)
1215 for (p = message_list->last; p; p = p->prev)
1216 Strcat_m_charp(tmp, "<tr><td><pre>", html_quote(p->ptr),
1217 "</pre></td></tr>\n", NULL);
1218 else
1219 Strcat_charp(tmp, "<tr><td>(no message recorded)</td></tr>\n");
1220 Strcat_charp(tmp, "</table></body></html>");
1221 return loadHTMLString(tmp);
1222 }
1223
1224 void
message(char * s,int return_x,int return_y)1225 message(char *s, int return_x, int return_y)
1226 {
1227 if (!fmInitialized)
1228 return;
1229 move(LASTLINE, 0);
1230 addnstr(s, COLS - 1);
1231 clrtoeolx();
1232 move(return_y, return_x);
1233 }
1234
1235 void
disp_err_message(char * s,int redraw_current)1236 disp_err_message(char *s, int redraw_current)
1237 {
1238 record_err_message(s);
1239 disp_message(s, redraw_current);
1240 }
1241
1242 void
disp_message_nsec(char * s,int redraw_current,int sec,int purge,int mouse)1243 disp_message_nsec(char *s, int redraw_current, int sec, int purge, int mouse)
1244 {
1245 if (QuietMessage)
1246 return;
1247 if (!fmInitialized) {
1248 fprintf(stderr, "%s\n", conv_to_system(s));
1249 return;
1250 }
1251 if (CurrentTab != NULL && Currentbuf != NULL)
1252 message(s, Currentbuf->cursorX + Currentbuf->rootX,
1253 Currentbuf->cursorY + Currentbuf->rootY);
1254 else
1255 message(s, LASTLINE, 0);
1256 refresh();
1257 #ifdef USE_MOUSE
1258 if (mouse && use_mouse)
1259 mouse_active();
1260 #endif
1261 sleep_till_anykey(sec, purge);
1262 #ifdef USE_MOUSE
1263 if (mouse && use_mouse)
1264 mouse_inactive();
1265 #endif
1266 if (CurrentTab != NULL && Currentbuf != NULL && redraw_current)
1267 displayBuffer(Currentbuf, B_NORMAL);
1268 }
1269
1270 void
disp_message(char * s,int redraw_current)1271 disp_message(char *s, int redraw_current)
1272 {
1273 disp_message_nsec(s, redraw_current, 10, FALSE, TRUE);
1274 }
1275 #ifdef USE_MOUSE
1276 void
disp_message_nomouse(char * s,int redraw_current)1277 disp_message_nomouse(char *s, int redraw_current)
1278 {
1279 disp_message_nsec(s, redraw_current, 10, FALSE, FALSE);
1280 }
1281 #endif
1282
1283 void
set_delayed_message(char * s)1284 set_delayed_message(char *s)
1285 {
1286 delayed_msg = allocStr(s, -1);
1287 }
1288
1289 void
cursorUp0(Buffer * buf,int n)1290 cursorUp0(Buffer *buf, int n)
1291 {
1292 if (buf->cursorY > 0)
1293 cursorUpDown(buf, -1);
1294 else {
1295 buf->topLine = lineSkip(buf, buf->topLine, -n, FALSE);
1296 if (buf->currentLine->prev != NULL)
1297 buf->currentLine = buf->currentLine->prev;
1298 arrangeLine(buf);
1299 }
1300 }
1301
1302 void
cursorUp(Buffer * buf,int n)1303 cursorUp(Buffer *buf, int n)
1304 {
1305 Line *l = buf->currentLine;
1306 if (buf->firstLine == NULL)
1307 return;
1308 while (buf->currentLine->prev && buf->currentLine->bpos)
1309 cursorUp0(buf, n);
1310 if (buf->currentLine == buf->firstLine) {
1311 gotoLine(buf, l->linenumber);
1312 arrangeLine(buf);
1313 return;
1314 }
1315 cursorUp0(buf, n);
1316 while (buf->currentLine->prev && buf->currentLine->bpos &&
1317 buf->currentLine->bwidth >= buf->currentColumn + buf->visualpos)
1318 cursorUp0(buf, n);
1319 }
1320
1321 void
cursorDown0(Buffer * buf,int n)1322 cursorDown0(Buffer *buf, int n)
1323 {
1324 if (buf->cursorY < buf->LINES - 1)
1325 cursorUpDown(buf, 1);
1326 else {
1327 buf->topLine = lineSkip(buf, buf->topLine, n, FALSE);
1328 if (buf->currentLine->next != NULL)
1329 buf->currentLine = buf->currentLine->next;
1330 arrangeLine(buf);
1331 }
1332 }
1333
1334 void
cursorDown(Buffer * buf,int n)1335 cursorDown(Buffer *buf, int n)
1336 {
1337 Line *l = buf->currentLine;
1338 if (buf->firstLine == NULL)
1339 return;
1340 while (buf->currentLine->next && buf->currentLine->next->bpos)
1341 cursorDown0(buf, n);
1342 if (buf->currentLine == buf->lastLine) {
1343 gotoLine(buf, l->linenumber);
1344 arrangeLine(buf);
1345 return;
1346 }
1347 cursorDown0(buf, n);
1348 while (buf->currentLine->next && buf->currentLine->next->bpos &&
1349 buf->currentLine->bwidth + buf->currentLine->width <
1350 buf->currentColumn + buf->visualpos)
1351 cursorDown0(buf, n);
1352 }
1353
1354 void
cursorUpDown(Buffer * buf,int n)1355 cursorUpDown(Buffer *buf, int n)
1356 {
1357 Line *cl = buf->currentLine;
1358
1359 if (buf->firstLine == NULL)
1360 return;
1361 if ((buf->currentLine = currentLineSkip(buf, cl, n, FALSE)) == cl)
1362 return;
1363 arrangeLine(buf);
1364 }
1365
1366 void
cursorRight(Buffer * buf,int n)1367 cursorRight(Buffer *buf, int n)
1368 {
1369 int i, delta = 1, cpos, vpos2;
1370 Line *l = buf->currentLine;
1371 Lineprop *p;
1372
1373 if (buf->firstLine == NULL)
1374 return;
1375 if (buf->pos == l->len && !(l->next && l->next->bpos))
1376 return;
1377 i = buf->pos;
1378 p = l->propBuf;
1379 #ifdef USE_M17N
1380 while (i + delta < l->len && p[i + delta] & PC_WCHAR2)
1381 delta++;
1382 #endif
1383 if (i + delta < l->len) {
1384 buf->pos = i + delta;
1385 }
1386 else if (l->len == 0) {
1387 buf->pos = 0;
1388 }
1389 else if (l->next && l->next->bpos) {
1390 cursorDown0(buf, 1);
1391 buf->pos = 0;
1392 arrangeCursor(buf);
1393 return;
1394 }
1395 else {
1396 buf->pos = l->len - 1;
1397 #ifdef USE_M17N
1398 while (buf->pos && p[buf->pos] & PC_WCHAR2)
1399 buf->pos--;
1400 #endif
1401 }
1402 cpos = COLPOS(l, buf->pos);
1403 buf->visualpos = l->bwidth + cpos - buf->currentColumn;
1404 delta = 1;
1405 #ifdef USE_M17N
1406 while (buf->pos + delta < l->len && p[buf->pos + delta] & PC_WCHAR2)
1407 delta++;
1408 #endif
1409 vpos2 = COLPOS(l, buf->pos + delta) - buf->currentColumn - 1;
1410 if (vpos2 >= buf->COLS && n) {
1411 columnSkip(buf, n + (vpos2 - buf->COLS) - (vpos2 - buf->COLS) % n);
1412 buf->visualpos = l->bwidth + cpos - buf->currentColumn;
1413 }
1414 buf->cursorX = buf->visualpos - l->bwidth;
1415 }
1416
1417 void
cursorLeft(Buffer * buf,int n)1418 cursorLeft(Buffer *buf, int n)
1419 {
1420 int i, delta = 1, cpos;
1421 Line *l = buf->currentLine;
1422 Lineprop *p;
1423
1424 if (buf->firstLine == NULL)
1425 return;
1426 i = buf->pos;
1427 p = l->propBuf;
1428 #ifdef USE_M17N
1429 while (i - delta > 0 && p[i - delta] & PC_WCHAR2)
1430 delta++;
1431 #endif
1432 if (i >= delta)
1433 buf->pos = i - delta;
1434 else if (l->prev && l->bpos) {
1435 cursorUp0(buf, -1);
1436 buf->pos = buf->currentLine->len - 1;
1437 arrangeCursor(buf);
1438 return;
1439 }
1440 else
1441 buf->pos = 0;
1442 cpos = COLPOS(l, buf->pos);
1443 buf->visualpos = l->bwidth + cpos - buf->currentColumn;
1444 if (buf->visualpos - l->bwidth < 0 && n) {
1445 columnSkip(buf,
1446 -n + buf->visualpos - l->bwidth - (buf->visualpos -
1447 l->bwidth) % n);
1448 buf->visualpos = l->bwidth + cpos - buf->currentColumn;
1449 }
1450 buf->cursorX = buf->visualpos - l->bwidth;
1451 }
1452
1453 void
cursorHome(Buffer * buf)1454 cursorHome(Buffer *buf)
1455 {
1456 buf->visualpos = 0;
1457 buf->cursorX = buf->cursorY = 0;
1458 }
1459
1460
1461 /*
1462 * Arrange line,column and cursor position according to current line and
1463 * current position.
1464 */
1465 void
arrangeCursor(Buffer * buf)1466 arrangeCursor(Buffer *buf)
1467 {
1468 int col, col2, pos;
1469 int delta = 1;
1470 if (buf == NULL || buf->currentLine == NULL)
1471 return;
1472 /* Arrange line */
1473 if (buf->currentLine->linenumber - buf->topLine->linenumber >= buf->LINES
1474 || buf->currentLine->linenumber < buf->topLine->linenumber) {
1475 /*
1476 * buf->topLine = buf->currentLine;
1477 */
1478 buf->topLine = lineSkip(buf, buf->currentLine, 0, FALSE);
1479 }
1480 /* Arrange column */
1481 while (buf->pos < 0 && buf->currentLine->prev && buf->currentLine->bpos) {
1482 pos = buf->pos + buf->currentLine->prev->len;
1483 cursorUp0(buf, 1);
1484 buf->pos = pos;
1485 }
1486 while (buf->pos >= buf->currentLine->len && buf->currentLine->next &&
1487 buf->currentLine->next->bpos) {
1488 pos = buf->pos - buf->currentLine->len;
1489 cursorDown0(buf, 1);
1490 buf->pos = pos;
1491 }
1492 if (buf->currentLine->len == 0 || buf->pos < 0)
1493 buf->pos = 0;
1494 else if (buf->pos >= buf->currentLine->len)
1495 buf->pos = buf->currentLine->len - 1;
1496 #ifdef USE_M17N
1497 while (buf->pos > 0 && buf->currentLine->propBuf[buf->pos] & PC_WCHAR2)
1498 buf->pos--;
1499 #endif
1500 col = COLPOS(buf->currentLine, buf->pos);
1501 #ifdef USE_M17N
1502 while (buf->pos + delta < buf->currentLine->len &&
1503 buf->currentLine->propBuf[buf->pos + delta] & PC_WCHAR2)
1504 delta++;
1505 #endif
1506 col2 = COLPOS(buf->currentLine, buf->pos + delta);
1507 if (col < buf->currentColumn || col2 > buf->COLS + buf->currentColumn) {
1508 buf->currentColumn = 0;
1509 if (col2 > buf->COLS)
1510 columnSkip(buf, col);
1511 }
1512 /* Arrange cursor */
1513 buf->cursorY = buf->currentLine->linenumber - buf->topLine->linenumber;
1514 buf->visualpos = buf->currentLine->bwidth +
1515 COLPOS(buf->currentLine, buf->pos) - buf->currentColumn;
1516 buf->cursorX = buf->visualpos - buf->currentLine->bwidth;
1517 #ifdef DISPLAY_DEBUG
1518 fprintf(stderr,
1519 "arrangeCursor: column=%d, cursorX=%d, visualpos=%d, pos=%d, len=%d\n",
1520 buf->currentColumn, buf->cursorX, buf->visualpos, buf->pos,
1521 buf->currentLine->len);
1522 #endif
1523 }
1524
1525 void
arrangeLine(Buffer * buf)1526 arrangeLine(Buffer *buf)
1527 {
1528 int i, cpos;
1529
1530 if (buf->firstLine == NULL)
1531 return;
1532 buf->cursorY = buf->currentLine->linenumber - buf->topLine->linenumber;
1533 i = columnPos(buf->currentLine, buf->currentColumn + buf->visualpos
1534 - buf->currentLine->bwidth);
1535 cpos = COLPOS(buf->currentLine, i) - buf->currentColumn;
1536 if (cpos >= 0) {
1537 buf->cursorX = cpos;
1538 buf->pos = i;
1539 }
1540 else if (buf->currentLine->len > i) {
1541 buf->cursorX = 0;
1542 buf->pos = i + 1;
1543 }
1544 else {
1545 buf->cursorX = 0;
1546 buf->pos = 0;
1547 }
1548 #ifdef DISPLAY_DEBUG
1549 fprintf(stderr,
1550 "arrangeLine: column=%d, cursorX=%d, visualpos=%d, pos=%d, len=%d\n",
1551 buf->currentColumn, buf->cursorX, buf->visualpos, buf->pos,
1552 buf->currentLine->len);
1553 #endif
1554 }
1555
1556 void
cursorXY(Buffer * buf,int x,int y)1557 cursorXY(Buffer *buf, int x, int y)
1558 {
1559 int oldX;
1560
1561 cursorUpDown(buf, y - buf->cursorY);
1562
1563 if (buf->cursorX > x) {
1564 while (buf->cursorX > x)
1565 cursorLeft(buf, buf->COLS / 2);
1566 }
1567 else if (buf->cursorX < x) {
1568 while (buf->cursorX < x) {
1569 oldX = buf->cursorX;
1570
1571 cursorRight(buf, buf->COLS / 2);
1572
1573 if (oldX == buf->cursorX)
1574 break;
1575 }
1576 if (buf->cursorX > x)
1577 cursorLeft(buf, buf->COLS / 2);
1578 }
1579 }
1580
1581 void
restorePosition(Buffer * buf,Buffer * orig)1582 restorePosition(Buffer *buf, Buffer *orig)
1583 {
1584 buf->topLine = lineSkip(buf, buf->firstLine, TOP_LINENUMBER(orig) - 1,
1585 FALSE);
1586 gotoLine(buf, CUR_LINENUMBER(orig));
1587 buf->pos = orig->pos;
1588 if (buf->currentLine && orig->currentLine)
1589 buf->pos += orig->currentLine->bpos - buf->currentLine->bpos;
1590 buf->currentColumn = orig->currentColumn;
1591 arrangeCursor(buf);
1592 }
1593
1594 /* Local Variables: */
1595 /* c-basic-offset: 4 */
1596 /* tab-width: 8 */
1597 /* End: */
1598