display.c (36786B)
1 /* $Id$ */ 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 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 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 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 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_unquote_conv(u->ptr, buf->document_charset)); 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 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 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) { 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 } 501 502 static void 503 drawAnchorCursor0(Buffer *buf, AnchorList *al, int hseq, int prevhseq, 504 int tline, int eline, int active) 505 { 506 int i, j; 507 Line *l; 508 Anchor *an; 509 510 l = buf->topLine; 511 for (j = 0; j < al->nanchor; j++) { 512 an = &al->anchors[j]; 513 if (an->start.line < tline) 514 continue; 515 if (an->start.line >= eline) 516 return; 517 for (;; l = l->next) { 518 if (l == NULL) 519 return; 520 if (l->linenumber == an->start.line) 521 break; 522 } 523 if (hseq >= 0 && an->hseq == hseq) { 524 for (i = an->start.pos; i < an->end.pos; i++) { 525 if (l->propBuf[i] & (PE_IMAGE | PE_ANCHOR | PE_FORM)) { 526 if (active) 527 l->propBuf[i] |= PE_ACTIVE; 528 else 529 l->propBuf[i] &= ~PE_ACTIVE; 530 } 531 } 532 if (active) 533 redrawLineRegion(buf, l, l->linenumber - tline + buf->rootY, 534 an->start.pos, an->end.pos); 535 } 536 else if (prevhseq >= 0 && an->hseq == prevhseq) { 537 if (active) 538 redrawLineRegion(buf, l, l->linenumber - tline + buf->rootY, 539 an->start.pos, an->end.pos); 540 } 541 } 542 } 543 544 static void 545 drawAnchorCursor(Buffer *buf) 546 { 547 Anchor *an; 548 int hseq, prevhseq; 549 int tline, eline; 550 551 if (!buf->firstLine || !buf->hmarklist) 552 return; 553 if (!buf->href && !buf->formitem) 554 return; 555 556 an = retrieveCurrentAnchor(buf); 557 if (!an) 558 an = retrieveCurrentMap(buf); 559 if (an) 560 hseq = an->hseq; 561 else 562 hseq = -1; 563 tline = buf->topLine->linenumber; 564 eline = tline + buf->LINES; 565 prevhseq = buf->hmarklist->prevhseq; 566 567 if (buf->href) { 568 drawAnchorCursor0(buf, buf->href, hseq, prevhseq, tline, eline, 1); 569 drawAnchorCursor0(buf, buf->href, hseq, -1, tline, eline, 0); 570 } 571 if (buf->formitem) { 572 drawAnchorCursor0(buf, buf->formitem, hseq, prevhseq, tline, eline, 1); 573 drawAnchorCursor0(buf, buf->formitem, hseq, -1, tline, eline, 0); 574 } 575 buf->hmarklist->prevhseq = hseq; 576 } 577 578 static void 579 redrawNLine(Buffer *buf, int n) 580 { 581 Line *l; 582 int i; 583 584 #ifdef USE_COLOR 585 if (useColor) { 586 EFFECT_ANCHOR_END_C; 587 #ifdef USE_BG_COLOR 588 setbcolor(bg_color); 589 #endif /* USE_BG_COLOR */ 590 } 591 #endif /* USE_COLOR */ 592 if (nTab > 1 593 #ifdef USE_MOUSE 594 || mouse_action.menu_str 595 #endif 596 ) { 597 TabBuffer *t; 598 int l; 599 600 move(0, 0); 601 #ifdef USE_MOUSE 602 if (mouse_action.menu_str) 603 addstr(mouse_action.menu_str); 604 #endif 605 clrtoeolx(); 606 for (t = FirstTab; t; t = t->nextTab) { 607 move(t->y, t->x1); 608 if (t == CurrentTab) 609 bold(); 610 addch('['); 611 l = t->x2 - t->x1 - 1 - get_strwidth(t->currentBuffer->buffername); 612 if (l < 0) 613 l = 0; 614 if (l / 2 > 0) 615 addnstr_sup(" ", l / 2); 616 if (t == CurrentTab) 617 EFFECT_ACTIVE_START; 618 addnstr(t->currentBuffer->buffername, t->x2 - t->x1 - l); 619 if (t == CurrentTab) 620 EFFECT_ACTIVE_END; 621 if ((l + 1) / 2 > 0) 622 addnstr_sup(" ", (l + 1) / 2); 623 move(t->y, t->x2); 624 addch(']'); 625 if (t == CurrentTab) 626 boldend(); 627 } 628 #if 0 629 move(0, COLS - 2); 630 addstr(" x"); 631 #endif 632 move(LastTab->y + 1, 0); 633 for (i = 0; i < COLS; i++) 634 addch('~'); 635 } 636 for (i = 0, l = buf->topLine; i < buf->LINES; i++, l = l->next) { 637 if (i >= buf->LINES - n || i < -n) 638 l = redrawLine(buf, l, i + buf->rootY); 639 if (l == NULL) 640 break; 641 } 642 if (n > 0) { 643 move(i + buf->rootY, 0); 644 clrtobotx(); 645 } 646 647 #ifdef USE_IMAGE 648 if (!(activeImage && displayImage && buf->img)) 649 return; 650 move(buf->cursorY + buf->rootY, buf->cursorX + buf->rootX); 651 for (i = 0, l = buf->topLine; i < buf->LINES && l; i++, l = l->next) { 652 if (i >= buf->LINES - n || i < -n) 653 redrawLineImage(buf, l, i + buf->rootY); 654 } 655 getAllImage(buf); 656 #endif 657 } 658 659 static Line * 660 redrawLine(Buffer *buf, Line *l, int i) 661 { 662 int j, pos, rcol, ncol, delta = 1; 663 int column = buf->currentColumn; 664 char *p; 665 Lineprop *pr; 666 #ifdef USE_ANSI_COLOR 667 Linecolor *pc; 668 #endif 669 #ifdef USE_COLOR 670 Anchor *a; 671 ParsedURL url; 672 int k, vpos = -1; 673 #endif 674 675 if (l == NULL) { 676 if (buf->pagerSource) { 677 l = getNextPage(buf, buf->LINES + buf->rootY - i); 678 if (l == NULL) 679 return NULL; 680 } 681 else 682 return NULL; 683 } 684 move(i, 0); 685 if (showLineNum) { 686 char tmp[16]; 687 if (!buf->rootX) { 688 if (buf->lastLine->real_linenumber > 0) 689 buf->rootX = (int)(log(buf->lastLine->real_linenumber + 0.1) 690 / log(10)) + 2; 691 if (buf->rootX < 5) 692 buf->rootX = 5; 693 if (buf->rootX > COLS) 694 buf->rootX = COLS; 695 buf->COLS = COLS - buf->rootX; 696 } 697 if (l->real_linenumber && !l->bpos) 698 sprintf(tmp, "%*ld:", buf->rootX - 1, l->real_linenumber); 699 else 700 sprintf(tmp, "%*s ", buf->rootX - 1, ""); 701 addstr(tmp); 702 } 703 move(i, buf->rootX); 704 if (l->width < 0) 705 l->width = COLPOS(l, l->len); 706 if (l->len == 0 || l->width - 1 < column) { 707 clrtoeolx(); 708 return l; 709 } 710 /* need_clrtoeol(); */ 711 pos = columnPos(l, column); 712 p = &(l->lineBuf[pos]); 713 pr = &(l->propBuf[pos]); 714 #ifdef USE_ANSI_COLOR 715 if (useColor && l->colorBuf) 716 pc = &(l->colorBuf[pos]); 717 else 718 pc = NULL; 719 #endif 720 rcol = COLPOS(l, pos); 721 722 for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j += delta) { 723 #ifdef USE_COLOR 724 if (useVisitedColor && vpos <= pos + j && !(pr[j] & PE_VISITED)) { 725 a = retrieveAnchor(buf->href, l->linenumber, pos + j); 726 if (a) { 727 parseURL2(a->url, &url, baseURL(buf)); 728 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { 729 for (k = a->start.pos; k < a->end.pos; k++) 730 pr[k - pos] |= PE_VISITED; 731 } 732 vpos = a->end.pos; 733 } 734 } 735 #endif 736 #ifdef USE_M17N 737 delta = wtf_len((wc_uchar *) & p[j]); 738 #endif 739 ncol = COLPOS(l, pos + j + delta); 740 if (ncol - column > buf->COLS) 741 break; 742 #ifdef USE_ANSI_COLOR 743 if (pc) 744 do_color(pc[j]); 745 #endif 746 if (rcol < column) { 747 for (rcol = column; rcol < ncol; rcol++) 748 addChar(' ', 0); 749 continue; 750 } 751 if (p[j] == '\t') { 752 for (; rcol < ncol; rcol++) 753 addChar(' ', 0); 754 } 755 else { 756 #ifdef USE_M17N 757 addMChar(&p[j], pr[j], delta); 758 #else 759 addChar(p[j], pr[j]); 760 #endif 761 } 762 rcol = ncol; 763 } 764 if (somode) { 765 somode = FALSE; 766 standend(); 767 } 768 if (ulmode) { 769 ulmode = FALSE; 770 underlineend(); 771 } 772 if (bomode) { 773 bomode = FALSE; 774 boldend(); 775 } 776 if (emph_mode) { 777 emph_mode = FALSE; 778 boldend(); 779 } 780 781 if (anch_mode) { 782 anch_mode = FALSE; 783 EFFECT_ANCHOR_END; 784 } 785 if (imag_mode) { 786 imag_mode = FALSE; 787 EFFECT_IMAGE_END; 788 } 789 if (form_mode) { 790 form_mode = FALSE; 791 EFFECT_FORM_END; 792 } 793 if (visited_mode) { 794 visited_mode = FALSE; 795 EFFECT_VISITED_END; 796 } 797 if (active_mode) { 798 active_mode = FALSE; 799 EFFECT_ACTIVE_END; 800 } 801 if (mark_mode) { 802 mark_mode = FALSE; 803 EFFECT_MARK_END; 804 } 805 if (graph_mode) { 806 graph_mode = FALSE; 807 graphend(); 808 } 809 #ifdef USE_ANSI_COLOR 810 if (color_mode) 811 do_color(0); 812 #endif 813 if (rcol - column < buf->COLS) 814 clrtoeolx(); 815 return l; 816 } 817 818 #ifdef USE_IMAGE 819 static Line * 820 redrawLineImage(Buffer *buf, Line *l, int i) 821 { 822 int j, pos, rcol; 823 int column = buf->currentColumn; 824 Anchor *a; 825 int x, y, sx, sy, w, h; 826 827 if (l == NULL) 828 return NULL; 829 if (l->width < 0) 830 l->width = COLPOS(l, l->len); 831 if (l->len == 0 || l->width - 1 < column) 832 return l; 833 pos = columnPos(l, column); 834 rcol = COLPOS(l, pos); 835 for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j++) { 836 if (rcol - column < 0) { 837 rcol = COLPOS(l, pos + j + 1); 838 continue; 839 } 840 a = retrieveAnchor(buf->img, l->linenumber, pos + j); 841 if (a && a->image && a->image->touch < image_touch) { 842 Image *image = a->image; 843 ImageCache *cache; 844 845 cache = image->cache = getImage(image, baseURL(buf), 846 buf->image_flag); 847 if (cache) { 848 if ((image->width < 0 && cache->width > 0) || 849 (image->height < 0 && cache->height > 0)) { 850 image->width = cache->width; 851 image->height = cache->height; 852 buf->need_reshape = TRUE; 853 } 854 x = (int)((rcol - column + buf->rootX) * pixel_per_char); 855 y = (int)(i * pixel_per_line); 856 sx = (int)((rcol - COLPOS(l, a->start.pos)) * pixel_per_char); 857 sy = (int)((l->linenumber - image->y) * pixel_per_line); 858 if (sx == 0 && x + image->xoffset >= 0) 859 x += image->xoffset; 860 else 861 sx -= image->xoffset; 862 if (sy == 0 && y + image->yoffset >= 0) 863 y += image->yoffset; 864 else 865 sy -= image->yoffset; 866 if (image->width > 0) 867 w = image->width - sx; 868 else 869 w = (int)(8 * pixel_per_char - sx); 870 if (image->height > 0) 871 h = image->height - sy; 872 else 873 h = (int)(pixel_per_line - sy); 874 if (w > (int)((buf->rootX + buf->COLS) * pixel_per_char - x)) 875 w = (int)((buf->rootX + buf->COLS) * pixel_per_char - x); 876 if (h > (int)(LASTLINE * pixel_per_line - y)) 877 h = (int)(LASTLINE * pixel_per_line - y); 878 addImage(cache, x, y, sx, sy, w, h); 879 image->touch = image_touch; 880 draw_image_flag = TRUE; 881 } 882 } 883 rcol = COLPOS(l, pos + j + 1); 884 } 885 return l; 886 } 887 #endif 888 889 static int 890 redrawLineRegion(Buffer *buf, Line *l, int i, int bpos, int epos) 891 { 892 int j, pos, rcol, ncol, delta = 1; 893 int column = buf->currentColumn; 894 char *p; 895 Lineprop *pr; 896 #ifdef USE_ANSI_COLOR 897 Linecolor *pc; 898 #endif 899 int bcol, ecol; 900 #ifdef USE_COLOR 901 Anchor *a; 902 ParsedURL url; 903 int k, vpos = -1; 904 #endif 905 906 if (l == NULL) 907 return 0; 908 pos = columnPos(l, column); 909 p = &(l->lineBuf[pos]); 910 pr = &(l->propBuf[pos]); 911 #ifdef USE_ANSI_COLOR 912 if (useColor && l->colorBuf) 913 pc = &(l->colorBuf[pos]); 914 else 915 pc = NULL; 916 #endif 917 rcol = COLPOS(l, pos); 918 bcol = bpos - pos; 919 ecol = epos - pos; 920 921 for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j += delta) { 922 #ifdef USE_COLOR 923 if (useVisitedColor && vpos <= pos + j && !(pr[j] & PE_VISITED)) { 924 a = retrieveAnchor(buf->href, l->linenumber, pos + j); 925 if (a) { 926 parseURL2(a->url, &url, baseURL(buf)); 927 if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) { 928 for (k = a->start.pos; k < a->end.pos; k++) 929 pr[k - pos] |= PE_VISITED; 930 } 931 vpos = a->end.pos; 932 } 933 } 934 #endif 935 #ifdef USE_M17N 936 delta = wtf_len((wc_uchar *) & p[j]); 937 #endif 938 ncol = COLPOS(l, pos + j + delta); 939 if (ncol - column > buf->COLS) 940 break; 941 #ifdef USE_ANSI_COLOR 942 if (pc) 943 do_color(pc[j]); 944 #endif 945 if (j >= bcol && j < ecol) { 946 if (rcol < column) { 947 move(i, buf->rootX); 948 for (rcol = column; rcol < ncol; rcol++) 949 addChar(' ', 0); 950 continue; 951 } 952 move(i, rcol - column + buf->rootX); 953 if (p[j] == '\t') { 954 for (; rcol < ncol; rcol++) 955 addChar(' ', 0); 956 } 957 else 958 #ifdef USE_M17N 959 addMChar(&p[j], pr[j], delta); 960 #else 961 addChar(p[j], pr[j]); 962 #endif 963 } 964 rcol = ncol; 965 } 966 if (somode) { 967 somode = FALSE; 968 standend(); 969 } 970 if (ulmode) { 971 ulmode = FALSE; 972 underlineend(); 973 } 974 if (bomode) { 975 bomode = FALSE; 976 boldend(); 977 } 978 if (emph_mode) { 979 emph_mode = FALSE; 980 boldend(); 981 } 982 983 if (anch_mode) { 984 anch_mode = FALSE; 985 EFFECT_ANCHOR_END; 986 } 987 if (imag_mode) { 988 imag_mode = FALSE; 989 EFFECT_IMAGE_END; 990 } 991 if (form_mode) { 992 form_mode = FALSE; 993 EFFECT_FORM_END; 994 } 995 if (visited_mode) { 996 visited_mode = FALSE; 997 EFFECT_VISITED_END; 998 } 999 if (active_mode) { 1000 active_mode = FALSE; 1001 EFFECT_ACTIVE_END; 1002 } 1003 if (mark_mode) { 1004 mark_mode = FALSE; 1005 EFFECT_MARK_END; 1006 } 1007 if (graph_mode) { 1008 graph_mode = FALSE; 1009 graphend(); 1010 } 1011 #ifdef USE_ANSI_COLOR 1012 if (color_mode) 1013 do_color(0); 1014 #endif 1015 return rcol - column; 1016 } 1017 1018 #define do_effect1(effect,modeflag,action_start,action_end) \ 1019 if (m & effect) { \ 1020 if (!modeflag) { \ 1021 action_start; \ 1022 modeflag = TRUE; \ 1023 } \ 1024 } 1025 1026 #define do_effect2(effect,modeflag,action_start,action_end) \ 1027 if (modeflag) { \ 1028 action_end; \ 1029 modeflag = FALSE; \ 1030 } 1031 1032 static void 1033 do_effects(Lineprop m) 1034 { 1035 /* effect end */ 1036 do_effect2(PE_UNDER, ulmode, underline(), underlineend()); 1037 do_effect2(PE_STAND, somode, standout(), standend()); 1038 do_effect2(PE_BOLD, bomode, bold(), boldend()); 1039 do_effect2(PE_EMPH, emph_mode, bold(), boldend()); 1040 do_effect2(PE_ANCHOR, anch_mode, EFFECT_ANCHOR_START, EFFECT_ANCHOR_END); 1041 do_effect2(PE_IMAGE, imag_mode, EFFECT_IMAGE_START, EFFECT_IMAGE_END); 1042 do_effect2(PE_FORM, form_mode, EFFECT_FORM_START, EFFECT_FORM_END); 1043 do_effect2(PE_VISITED, visited_mode, EFFECT_VISITED_START, 1044 EFFECT_VISITED_END); 1045 do_effect2(PE_ACTIVE, active_mode, EFFECT_ACTIVE_START, EFFECT_ACTIVE_END); 1046 do_effect2(PE_MARK, mark_mode, EFFECT_MARK_START, EFFECT_MARK_END); 1047 if (graph_mode) { 1048 graphend(); 1049 graph_mode = FALSE; 1050 } 1051 1052 /* effect start */ 1053 do_effect1(PE_UNDER, ulmode, underline(), underlineend()); 1054 do_effect1(PE_STAND, somode, standout(), standend()); 1055 do_effect1(PE_BOLD, bomode, bold(), boldend()); 1056 do_effect1(PE_EMPH, emph_mode, bold(), boldend()); 1057 do_effect1(PE_ANCHOR, anch_mode, EFFECT_ANCHOR_START, EFFECT_ANCHOR_END); 1058 do_effect1(PE_IMAGE, imag_mode, EFFECT_IMAGE_START, EFFECT_IMAGE_END); 1059 do_effect1(PE_FORM, form_mode, EFFECT_FORM_START, EFFECT_FORM_END); 1060 do_effect1(PE_VISITED, visited_mode, EFFECT_VISITED_START, 1061 EFFECT_VISITED_END); 1062 do_effect1(PE_ACTIVE, active_mode, EFFECT_ACTIVE_START, EFFECT_ACTIVE_END); 1063 do_effect1(PE_MARK, mark_mode, EFFECT_MARK_START, EFFECT_MARK_END); 1064 } 1065 1066 #ifdef USE_ANSI_COLOR 1067 static void 1068 do_color(Linecolor c) 1069 { 1070 if (c & 0x8) 1071 setfcolor(c & 0x7); 1072 else if (color_mode & 0x8) 1073 setfcolor(basic_color); 1074 #ifdef USE_BG_COLOR 1075 if (c & 0x80) 1076 setbcolor((c >> 4) & 0x7); 1077 else if (color_mode & 0x80) 1078 setbcolor(bg_color); 1079 #endif 1080 color_mode = c; 1081 } 1082 #endif 1083 1084 #ifdef USE_M17N 1085 void 1086 addChar(char c, Lineprop mode) 1087 { 1088 addMChar(&c, mode, 1); 1089 } 1090 1091 void 1092 addMChar(char *p, Lineprop mode, size_t len) 1093 #else 1094 void 1095 addChar(char c, Lineprop mode) 1096 #endif 1097 { 1098 Lineprop m = CharEffect(mode); 1099 #ifdef USE_M17N 1100 char c = *p; 1101 1102 if (mode & PC_WCHAR2) 1103 return; 1104 #endif 1105 do_effects(m); 1106 if (mode & PC_SYMBOL) { 1107 char **symbol; 1108 #ifdef USE_M17N 1109 int w = (mode & PC_KANJI) ? 2 : 1; 1110 1111 c = ((char)wtf_get_code((wc_uchar *) p) & 0x7f) - SYMBOL_BASE; 1112 #else 1113 c -= SYMBOL_BASE; 1114 #endif 1115 if (graph_ok() && c < N_GRAPH_SYMBOL) { 1116 if (!graph_mode) { 1117 graphstart(); 1118 graph_mode = TRUE; 1119 } 1120 #ifdef USE_M17N 1121 if (w == 2 && WcOption.use_wide) 1122 addstr(graph2_symbol[(int)c]); 1123 else 1124 #endif 1125 addch(*graph_symbol[(int)c]); 1126 } 1127 else { 1128 #ifdef USE_M17N 1129 symbol = get_symbol(DisplayCharset, &w); 1130 addstr(symbol[(int)c]); 1131 #else 1132 symbol = get_symbol(); 1133 addch(*symbol[(int)c]); 1134 #endif 1135 } 1136 } 1137 else if (mode & PC_CTRL) { 1138 switch (c) { 1139 case '\t': 1140 addch(c); 1141 break; 1142 case '\n': 1143 addch(' '); 1144 break; 1145 case '\r': 1146 break; 1147 case DEL_CODE: 1148 addstr("^?"); 1149 break; 1150 default: 1151 addch('^'); 1152 addch(c + '@'); 1153 break; 1154 } 1155 } 1156 #ifdef USE_M17N 1157 else if (mode & PC_UNKNOWN) { 1158 char buf[5]; 1159 sprintf(buf, "[%.2X]", 1160 (unsigned char)wtf_get_code((wc_uchar *) p) | 0x80); 1161 addstr(buf); 1162 } 1163 else 1164 addmch(p, len); 1165 #else 1166 else if (0x80 <= (unsigned char)c && (unsigned char)c <= NBSP_CODE) 1167 addch(' '); 1168 else 1169 addch(c); 1170 #endif 1171 } 1172 1173 static GeneralList *message_list = NULL; 1174 1175 void 1176 record_err_message(char *s) 1177 { 1178 if (fmInitialized) { 1179 if (!message_list) 1180 message_list = newGeneralList(); 1181 if (message_list->nitem >= LINES) 1182 popValue(message_list); 1183 pushValue(message_list, allocStr(s, -1)); 1184 } 1185 } 1186 1187 /* 1188 * List of error messages 1189 */ 1190 Buffer * 1191 message_list_panel(void) 1192 { 1193 Str tmp = Strnew_size(LINES * COLS); 1194 ListItem *p; 1195 1196 /* FIXME: gettextize? */ 1197 Strcat_charp(tmp, 1198 "<html><head><title>List of error messages</title></head><body>" 1199 "<h1>List of error messages</h1><table cellpadding=0>\n"); 1200 if (message_list) 1201 for (p = message_list->last; p; p = p->prev) 1202 Strcat_m_charp(tmp, "<tr><td><pre>", html_quote(p->ptr), 1203 "</pre></td></tr>\n", NULL); 1204 else 1205 Strcat_charp(tmp, "<tr><td>(no message recorded)</td></tr>\n"); 1206 Strcat_charp(tmp, "</table></body></html>"); 1207 return loadHTMLString(tmp); 1208 } 1209 1210 void 1211 message(char *s, int return_x, int return_y) 1212 { 1213 if (!fmInitialized) 1214 return; 1215 move(LASTLINE, 0); 1216 addnstr(s, COLS - 1); 1217 clrtoeolx(); 1218 move(return_y, return_x); 1219 } 1220 1221 void 1222 disp_err_message(char *s, int redraw_current) 1223 { 1224 record_err_message(s); 1225 disp_message(s, redraw_current); 1226 } 1227 1228 void 1229 disp_message_nsec(char *s, int redraw_current, int sec, int purge, int mouse) 1230 { 1231 if (QuietMessage) 1232 return; 1233 if (!fmInitialized) { 1234 fprintf(stderr, "%s\n", conv_to_system(s)); 1235 return; 1236 } 1237 if (CurrentTab != NULL && Currentbuf != NULL) 1238 message(s, Currentbuf->cursorX + Currentbuf->rootX, 1239 Currentbuf->cursorY + Currentbuf->rootY); 1240 else 1241 message(s, LASTLINE, 0); 1242 refresh(); 1243 #ifdef USE_MOUSE 1244 if (mouse && use_mouse) 1245 mouse_active(); 1246 #endif 1247 sleep_till_anykey(sec, purge); 1248 #ifdef USE_MOUSE 1249 if (mouse && use_mouse) 1250 mouse_inactive(); 1251 #endif 1252 if (CurrentTab != NULL && Currentbuf != NULL && redraw_current) 1253 displayBuffer(Currentbuf, B_NORMAL); 1254 } 1255 1256 void 1257 disp_message(char *s, int redraw_current) 1258 { 1259 disp_message_nsec(s, redraw_current, 10, FALSE, TRUE); 1260 } 1261 #ifdef USE_MOUSE 1262 void 1263 disp_message_nomouse(char *s, int redraw_current) 1264 { 1265 disp_message_nsec(s, redraw_current, 10, FALSE, FALSE); 1266 } 1267 #endif 1268 1269 void 1270 set_delayed_message(char *s) 1271 { 1272 delayed_msg = allocStr(s, -1); 1273 } 1274 1275 void 1276 cursorUp0(Buffer *buf, int n) 1277 { 1278 if (buf->cursorY > 0) 1279 cursorUpDown(buf, -1); 1280 else { 1281 buf->topLine = lineSkip(buf, buf->topLine, -n, FALSE); 1282 if (buf->currentLine->prev != NULL) 1283 buf->currentLine = buf->currentLine->prev; 1284 arrangeLine(buf); 1285 } 1286 } 1287 1288 void 1289 cursorUp(Buffer *buf, int n) 1290 { 1291 Line *l = buf->currentLine; 1292 if (buf->firstLine == NULL) 1293 return; 1294 while (buf->currentLine->prev && buf->currentLine->bpos) 1295 cursorUp0(buf, n); 1296 if (buf->currentLine == buf->firstLine) { 1297 gotoLine(buf, l->linenumber); 1298 arrangeLine(buf); 1299 return; 1300 } 1301 cursorUp0(buf, n); 1302 while (buf->currentLine->prev && buf->currentLine->bpos && 1303 buf->currentLine->bwidth >= buf->currentColumn + buf->visualpos) 1304 cursorUp0(buf, n); 1305 } 1306 1307 void 1308 cursorDown0(Buffer *buf, int n) 1309 { 1310 if (buf->cursorY < buf->LINES - 1) 1311 cursorUpDown(buf, 1); 1312 else { 1313 buf->topLine = lineSkip(buf, buf->topLine, n, FALSE); 1314 if (buf->currentLine->next != NULL) 1315 buf->currentLine = buf->currentLine->next; 1316 arrangeLine(buf); 1317 } 1318 } 1319 1320 void 1321 cursorDown(Buffer *buf, int n) 1322 { 1323 Line *l = buf->currentLine; 1324 if (buf->firstLine == NULL) 1325 return; 1326 while (buf->currentLine->next && buf->currentLine->next->bpos) 1327 cursorDown0(buf, n); 1328 if (buf->currentLine == buf->lastLine) { 1329 gotoLine(buf, l->linenumber); 1330 arrangeLine(buf); 1331 return; 1332 } 1333 cursorDown0(buf, n); 1334 while (buf->currentLine->next && buf->currentLine->next->bpos && 1335 buf->currentLine->bwidth + buf->currentLine->width < 1336 buf->currentColumn + buf->visualpos) 1337 cursorDown0(buf, n); 1338 } 1339 1340 void 1341 cursorUpDown(Buffer *buf, int n) 1342 { 1343 Line *cl = buf->currentLine; 1344 1345 if (buf->firstLine == NULL) 1346 return; 1347 if ((buf->currentLine = currentLineSkip(buf, cl, n, FALSE)) == cl) 1348 return; 1349 arrangeLine(buf); 1350 } 1351 1352 void 1353 cursorRight(Buffer *buf, int n) 1354 { 1355 int i, delta = 1, cpos, vpos2; 1356 Line *l = buf->currentLine; 1357 Lineprop *p; 1358 1359 if (buf->firstLine == NULL) 1360 return; 1361 if (buf->pos == l->len && !(l->next && l->next->bpos)) 1362 return; 1363 i = buf->pos; 1364 p = l->propBuf; 1365 #ifdef USE_M17N 1366 while (i + delta < l->len && p[i + delta] & PC_WCHAR2) 1367 delta++; 1368 #endif 1369 if (i + delta < l->len) { 1370 buf->pos = i + delta; 1371 } 1372 else if (l->len == 0) { 1373 buf->pos = 0; 1374 } 1375 else if (l->next && l->next->bpos) { 1376 cursorDown0(buf, 1); 1377 buf->pos = 0; 1378 arrangeCursor(buf); 1379 return; 1380 } 1381 else { 1382 buf->pos = l->len - 1; 1383 #ifdef USE_M17N 1384 while (buf->pos && p[buf->pos] & PC_WCHAR2) 1385 buf->pos--; 1386 #endif 1387 } 1388 cpos = COLPOS(l, buf->pos); 1389 buf->visualpos = l->bwidth + cpos - buf->currentColumn; 1390 delta = 1; 1391 #ifdef USE_M17N 1392 while (buf->pos + delta < l->len && p[buf->pos + delta] & PC_WCHAR2) 1393 delta++; 1394 #endif 1395 vpos2 = COLPOS(l, buf->pos + delta) - buf->currentColumn - 1; 1396 if (vpos2 >= buf->COLS && n) { 1397 columnSkip(buf, n + (vpos2 - buf->COLS) - (vpos2 - buf->COLS) % n); 1398 buf->visualpos = l->bwidth + cpos - buf->currentColumn; 1399 } 1400 buf->cursorX = buf->visualpos - l->bwidth; 1401 } 1402 1403 void 1404 cursorLeft(Buffer *buf, int n) 1405 { 1406 int i, delta = 1, cpos; 1407 Line *l = buf->currentLine; 1408 Lineprop *p; 1409 1410 if (buf->firstLine == NULL) 1411 return; 1412 i = buf->pos; 1413 p = l->propBuf; 1414 #ifdef USE_M17N 1415 while (i - delta > 0 && p[i - delta] & PC_WCHAR2) 1416 delta++; 1417 #endif 1418 if (i >= delta) 1419 buf->pos = i - delta; 1420 else if (l->prev && l->bpos) { 1421 cursorUp0(buf, -1); 1422 buf->pos = buf->currentLine->len - 1; 1423 arrangeCursor(buf); 1424 return; 1425 } 1426 else 1427 buf->pos = 0; 1428 cpos = COLPOS(l, buf->pos); 1429 buf->visualpos = l->bwidth + cpos - buf->currentColumn; 1430 if (buf->visualpos - l->bwidth < 0 && n) { 1431 columnSkip(buf, 1432 -n + buf->visualpos - l->bwidth - (buf->visualpos - 1433 l->bwidth) % n); 1434 buf->visualpos = l->bwidth + cpos - buf->currentColumn; 1435 } 1436 buf->cursorX = buf->visualpos - l->bwidth; 1437 } 1438 1439 void 1440 cursorHome(Buffer *buf) 1441 { 1442 buf->visualpos = 0; 1443 buf->cursorX = buf->cursorY = 0; 1444 } 1445 1446 1447 /* 1448 * Arrange line,column and cursor position according to current line and 1449 * current position. 1450 */ 1451 void 1452 arrangeCursor(Buffer *buf) 1453 { 1454 int col, col2, pos; 1455 int delta = 1; 1456 if (buf == NULL || buf->currentLine == NULL) 1457 return; 1458 /* Arrange line */ 1459 if (buf->currentLine->linenumber - buf->topLine->linenumber >= buf->LINES 1460 || buf->currentLine->linenumber < buf->topLine->linenumber) { 1461 /* 1462 * buf->topLine = buf->currentLine; 1463 */ 1464 buf->topLine = lineSkip(buf, buf->currentLine, 0, FALSE); 1465 } 1466 /* Arrange column */ 1467 while (buf->pos < 0 && buf->currentLine->prev && buf->currentLine->bpos) { 1468 pos = buf->pos + buf->currentLine->prev->len; 1469 cursorUp0(buf, 1); 1470 buf->pos = pos; 1471 } 1472 while (buf->pos >= buf->currentLine->len && buf->currentLine->next && 1473 buf->currentLine->next->bpos) { 1474 pos = buf->pos - buf->currentLine->len; 1475 cursorDown0(buf, 1); 1476 buf->pos = pos; 1477 } 1478 if (buf->currentLine->len == 0 || buf->pos < 0) 1479 buf->pos = 0; 1480 else if (buf->pos >= buf->currentLine->len) 1481 buf->pos = buf->currentLine->len - 1; 1482 #ifdef USE_M17N 1483 while (buf->pos > 0 && buf->currentLine->propBuf[buf->pos] & PC_WCHAR2) 1484 buf->pos--; 1485 #endif 1486 col = COLPOS(buf->currentLine, buf->pos); 1487 #ifdef USE_M17N 1488 while (buf->pos + delta < buf->currentLine->len && 1489 buf->currentLine->propBuf[buf->pos + delta] & PC_WCHAR2) 1490 delta++; 1491 #endif 1492 col2 = COLPOS(buf->currentLine, buf->pos + delta); 1493 if (col < buf->currentColumn || col2 > buf->COLS + buf->currentColumn) { 1494 buf->currentColumn = 0; 1495 if (col2 > buf->COLS) 1496 columnSkip(buf, col); 1497 } 1498 /* Arrange cursor */ 1499 buf->cursorY = buf->currentLine->linenumber - buf->topLine->linenumber; 1500 buf->visualpos = buf->currentLine->bwidth + 1501 COLPOS(buf->currentLine, buf->pos) - buf->currentColumn; 1502 buf->cursorX = buf->visualpos - buf->currentLine->bwidth; 1503 #ifdef DISPLAY_DEBUG 1504 fprintf(stderr, 1505 "arrangeCursor: column=%d, cursorX=%d, visualpos=%d, pos=%d, len=%d\n", 1506 buf->currentColumn, buf->cursorX, buf->visualpos, buf->pos, 1507 buf->currentLine->len); 1508 #endif 1509 } 1510 1511 void 1512 arrangeLine(Buffer *buf) 1513 { 1514 int i, cpos; 1515 1516 if (buf->firstLine == NULL) 1517 return; 1518 buf->cursorY = buf->currentLine->linenumber - buf->topLine->linenumber; 1519 i = columnPos(buf->currentLine, buf->currentColumn + buf->visualpos 1520 - buf->currentLine->bwidth); 1521 cpos = COLPOS(buf->currentLine, i) - buf->currentColumn; 1522 if (cpos >= 0) { 1523 buf->cursorX = cpos; 1524 buf->pos = i; 1525 } 1526 else if (buf->currentLine->len > i) { 1527 buf->cursorX = 0; 1528 buf->pos = i + 1; 1529 } 1530 else { 1531 buf->cursorX = 0; 1532 buf->pos = 0; 1533 } 1534 #ifdef DISPLAY_DEBUG 1535 fprintf(stderr, 1536 "arrangeLine: column=%d, cursorX=%d, visualpos=%d, pos=%d, len=%d\n", 1537 buf->currentColumn, buf->cursorX, buf->visualpos, buf->pos, 1538 buf->currentLine->len); 1539 #endif 1540 } 1541 1542 void 1543 cursorXY(Buffer *buf, int x, int y) 1544 { 1545 int oldX; 1546 1547 cursorUpDown(buf, y - buf->cursorY); 1548 1549 if (buf->cursorX > x) { 1550 while (buf->cursorX > x) 1551 cursorLeft(buf, buf->COLS / 2); 1552 } 1553 else if (buf->cursorX < x) { 1554 while (buf->cursorX < x) { 1555 oldX = buf->cursorX; 1556 1557 cursorRight(buf, buf->COLS / 2); 1558 1559 if (oldX == buf->cursorX) 1560 break; 1561 } 1562 if (buf->cursorX > x) 1563 cursorLeft(buf, buf->COLS / 2); 1564 } 1565 } 1566 1567 void 1568 restorePosition(Buffer *buf, Buffer *orig) 1569 { 1570 buf->topLine = lineSkip(buf, buf->firstLine, TOP_LINENUMBER(orig) - 1, 1571 FALSE); 1572 gotoLine(buf, CUR_LINENUMBER(orig)); 1573 buf->pos = orig->pos; 1574 if (buf->currentLine && orig->currentLine) 1575 buf->pos += orig->currentLine->bpos - buf->currentLine->bpos; 1576 buf->currentColumn = orig->currentColumn; 1577 arrangeCursor(buf); 1578 } 1579 1580 /* Local Variables: */ 1581 /* c-basic-offset: 4 */ 1582 /* tab-width: 8 */ 1583 /* End: */