sim.c (24541B)
1 #include <stdio.h> 2 #include <stdarg.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include "sim.h" 7 8 #define MINSIZE 16 9 #define MAXEMPTY 256 10 #define UTFMAX 6 11 #define FILECOUNT 8 12 #define LENGTH(a) (sizeof(a)/sizeof(a[0])) 13 #define RED(a) CSI "31m" a CSI "0m" 14 #define GREEN(a) CSI "32m" a CSI "0m" 15 16 typedef long Posn; 17 typedef ulong Rune; 18 19 enum { 20 Up = 1, 21 Down, 22 Left, 23 Right, 24 HalfUp, 25 HalfDown, 26 Top, 27 Bottom, 28 Letter, 29 Word, 30 EndWord, 31 PrevWord, 32 Till, 33 Line, 34 StartLine, 35 EndLine, 36 Insert, 37 Delete, 38 Change, 39 Ctrl = -0x60, 40 Esc = 0x1b, 41 Del = 0x7f 42 }; 43 44 typedef struct { 45 Posn p0, p1; 46 } Address; 47 48 typedef struct { 49 Rune *s; 50 ulong n; /*number of filled characters*/ 51 ulong size; 52 } String; 53 54 typedef struct Buffer Buffer; 55 56 struct Buffer { 57 String is; 58 String ds; 59 uint c; 60 uint arg; 61 uint count; 62 Posn p0; 63 Buffer* next; 64 Buffer* prev; 65 }; 66 67 typedef struct { 68 String s; 69 String name; 70 Address dot; 71 Buffer* b; /*buffer ll*/ 72 Buffer* bd; /*disk buffer pointer*/ 73 } File; 74 75 typedef struct { 76 uchar key; 77 void (*func)(int); 78 int value; 79 } Key; 80 81 typedef struct { 82 Address* a; 83 ushort cur; 84 ushort n; 85 ushort size; 86 } Frame; 87 88 static Rune* Strchr(Rune *s, Rune r); 89 static String Strn(Rune *r, ulong n); 90 static Rune* Strnstr(Rune *s1, Rune *s2, ulong n); 91 static String Utf(char* s); 92 static void blind_reader(Frame* fr, Posn p0); 93 static void blind_writer(ushort line, ushort offset, ushort top, ushort bot); 94 static void buf_add( 95 String* is, String* ds, uint c, uint arg, uint count 96 ); 97 static void buf_free(Buffer* p); 98 static int c2r(Rune *r, uchar c, uchar *seq); 99 static void change(int arg); 100 static void count(int arg); 101 static void curmov(ushort x, ushort y); 102 static uint curpos(void); 103 static void delete(int arg); 104 static void dot(int arg); 105 static void redo(int arg); 106 static void escape(int c); 107 static uchar getc2(void); 108 static Rune getr(void); 109 static void init(void); 110 static void input(String* s, uint line, char* prefix); 111 static void insert(int arg); 112 static int isword(uchar c); 113 static void file_close(int arg); 114 static void file_init(File* f); 115 static void file_load(File* f); 116 static void file_open(int arg); 117 static void file_save(int arg); 118 static void fr_add(Frame* fr, Address a); 119 static void fr_calc(void); 120 static void fr_close(Frame* fr); 121 static void fr_init(Frame* fr); 122 static void fr_insert(Frame* p, Frame q, ushort n); 123 static void fr_insure(Frame* fr, ushort n); 124 static void fr_update(void); 125 static void fr_zero(Frame*); 126 static void gmove(int arg); 127 static void msg(uint line, char* fmt, ...); 128 static void paste(int arg); 129 static void pline(int arg); 130 static uchar r2u(char *s, Rune r); 131 static uint runesiz(Rune c, ulong wx); 132 static void search(int arg); 133 static int selection(int arg); 134 static ulong str2u(char** buf, String s); 135 static void str_init(String* p); 136 static void str_close(String* p); 137 static void str_dup(String* p, String q); 138 static void str_zero(String* p); 139 static void str_insure(String* p, ulong n); 140 static void str_addr(String* p, Rune r); 141 static void str_adds(String* p, String q); 142 static void str_delr(String* p); 143 static void str_insert(String* p, String q, Posn p0); 144 static void str_delete(String* p, Posn p0, Posn p1); 145 static void u2str(String *s, char *u); 146 static void undo(int arg); 147 static void move(int); 148 static void quit(int); 149 static void yank(int arg); 150 151 static Frame frame[FILECOUNT], *fr = frame; 152 static File file[FILECOUNT], *f = file; 153 static String istr, srch; 154 static Window w; 155 static uint counter; 156 static char *ctrune[0x20] = { 157 "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", 158 "bs" , "\\t", "\\n", "vt" , "ff" , "cr" , "so" , "si", 159 "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", 160 "can", "em" , "sub", "esc", "fs" , "gs" , "rs" , "us" 161 }; 162 163 #include "config.h" 164 165 extern void 166 die(char* fmt, ...) 167 { 168 static char *s; 169 va_list ap; 170 uint i; 171 172 win_end(); 173 va_start(ap, fmt); 174 vfprintf(stderr, fmt, ap); 175 va_end(ap); 176 if (fmt[0] && fmt[strlen(fmt) - 1] == ':') 177 perror(NULL); 178 else 179 fputc('\n', stderr); 180 for (i = 0; i < FILECOUNT; ++i) { 181 f = file + i; 182 if (!f->s.n) 183 continue; 184 str_adds(&f->name, Utf(".swap")); 185 file_save(i); 186 str2u(&s, f->name); 187 fprintf(stderr, "file saved to %s\n", s); 188 } 189 abort(); 190 } 191 192 extern void* 193 emalloc(ulong n) 194 { 195 void* p; 196 197 p = malloc(n); 198 if (!p) 199 die("malloc:"); 200 memset(p, 0, n); 201 return p; 202 } 203 204 extern void* 205 erealloc(void* p, ulong n) 206 { 207 p = realloc(p, n); 208 if (!p) 209 die("realloc:"); 210 return p; 211 } 212 213 extern void 214 resize(void) 215 { 216 Window wt; 217 218 win_query(&wt); 219 if (wt.wx != w.wx || wt.wy != w.wy) { 220 w.wx = wt.wx; 221 w.wy = wt.wy; 222 fr_zero(fr); 223 fr_update(); 224 } 225 } 226 227 static Rune* 228 Strchr(Rune *s, Rune r) 229 { 230 for (;*s != '\0'; ++s) 231 if (*s == r) 232 return s; 233 return NULL; 234 } 235 236 static String 237 Strn(Rune *r, ulong n) 238 { 239 static String s; 240 ulong l; 241 242 l = (n + 1) * sizeof(*s.s); 243 s.s = erealloc(s.s, l); 244 s.n = n; 245 memcpy(s.s, r, l); 246 s.s[s.n] = '\0'; 247 return s; 248 } 249 250 static Rune* 251 Strnstr(Rune *s1, Rune *s2, ulong n) 252 { 253 n *= sizeof(*s2); 254 do { 255 s1 = Strchr(s1, s2[0]); 256 if (s1 != NULL && !memcmp(s1, s2, n)) 257 return s1; 258 } while (s1++ != NULL); 259 return NULL; 260 } 261 262 static String 263 Utf(char* s) 264 { 265 static String t; 266 267 u2str(&t, s); 268 return t; 269 } 270 271 static void 272 blind_reader(Frame* fr, Posn p0) 273 { 274 Address a; 275 uint wx; 276 277 a.p0 = a.p1 = p0; 278 do { 279 for (wx = 0; wx < w.wx && a.p1 < f->s.n;) { 280 if (f->s.s[a.p1] == '\n') 281 break; 282 wx += runesiz(f->s.s[a.p1], wx); 283 if (wx < w.wx) 284 ++a.p1; 285 if (wx >= w.wx) { 286 if (f->s.s[a.p1] == '\t') 287 ++a.p1; 288 if (f->s.s[a.p1 + 1] == '\n') 289 ++a.p1; 290 } 291 } 292 fr_add(fr, a); 293 a.p0 = ++a.p1; 294 } while (a.p1 <= f->s.n && f->s.s[a.p1 - 1] != '\n'); 295 } 296 297 static void 298 blind_writer(ushort line, ushort offset, ushort top, ushort bot) 299 { 300 static char *s; 301 Posn i, o; 302 ulong n; 303 304 i = o = 0; 305 if (offset >= top) 306 i = offset - top + 1; 307 if (fr->n - offset > bot) 308 o = offset + bot - 1; 309 else if (fr->n) 310 o = fr->n - 1; 311 curmov(0, offset > line ? 0 : line - offset); 312 i = fr->a[i].p0; 313 o = fr->a[o].p1; 314 n = str2u(&s, Strn(f->s.s + i, o - i)); 315 fwrite(s, n, 1, stdout); 316 } 317 318 static void 319 buf_add(String* is, String* ds, uint c, uint arg, uint count) 320 { 321 if (f->b->next) 322 buf_free(f->b->next); 323 f->b->next = emalloc(sizeof(*f->b->next)); 324 f->b->next->prev = f->b; 325 f->b = f->b->next; 326 if (is != NULL) 327 str_insert(&f->b->is, *is, 0); 328 if (ds != NULL) 329 str_insert(&f->b->ds, *ds, 0); 330 f->b->c = c; 331 f->b->arg = arg; 332 f->b->count = count; 333 f->b->p0 = f->dot.p0; 334 fr_zero(fr); 335 } 336 337 static void 338 buf_free(Buffer* p) 339 { 340 if (p->next != NULL) 341 buf_free(p->next); 342 str_close(&p->is); 343 str_close(&p->ds); 344 free(p); 345 } 346 347 static int 348 c2r(Rune *r, uchar c, uchar *seq) 349 { 350 if (*seq != 0) { 351 if ((c & 0xc0) != 0x80) { 352 *seq = 0; 353 return -1; 354 } 355 *r = (*r << 6) | (c & 0x3f); 356 --*seq; 357 return 0; 358 } 359 if ((c & 0x80) == 0) { 360 *r = c & 0x7f; 361 *seq = 0; 362 } else if ((c & 0xe0) == 0xc0) { 363 *r = c & 0x1f; 364 *seq = 1; 365 } else if ((c & 0xf0) == 0xe0) { 366 *r = c & 0x0f; 367 *seq = 2; 368 } else if ((c & 0xf8) == 0xf0) { 369 *r = c & 0x07; 370 *seq = 3; 371 } else if ((c & 0xfc) == 0xf8) { 372 *r = c & 0x03; 373 *seq = 4; 374 } else if ((c & 0xfe) == 0xfc) { 375 *r = c & 0x01; 376 *seq = 5; 377 } else { 378 *r = c; 379 *seq = 0; 380 } 381 return 0; 382 } 383 384 static void 385 change(int arg) 386 { 387 String s; 388 Address *a; 389 uint count; 390 391 if (!arg) 392 arg = getr(); 393 switch (arg) { 394 case 'x': arg = Letter; break; 395 case 'c': arg = Line; break; 396 case 'G': arg = Bottom; break; 397 case 'g': arg = Top; break; 398 case 'w': arg = Word; break; 399 case 't': arg = Till; break; 400 } 401 count = counter; 402 arg = selection(arg); 403 if (arg == Word || arg == Letter || arg > 0x7f) 404 ++f->dot.p1; 405 str_init(&s); 406 a = &f->dot; 407 if (a->p0 != a->p1) { 408 str_adds(&s, Strn(f->s.s + a->p0, a->p1 - a->p0)); 409 str_delete(&f->s, a->p0, a->p1); 410 a->p1 = a->p0; 411 } 412 fr_zero(fr); 413 insert(0); 414 if (s.n) 415 str_insert(&f->b->ds, s, 0); 416 f->b->c = Change; 417 f->b->arg = arg; 418 f->b->count = count; 419 str_close(&s); 420 fr_update(); 421 } 422 423 static void 424 count(int arg) 425 { 426 if (!counter && !arg) { 427 move(StartLine); 428 return; 429 } 430 counter *= 10; 431 counter += arg; 432 } 433 434 static void 435 curmov(ushort x, ushort y) 436 { 437 printf(CSI "%hu;%huH", y, x); 438 } 439 440 static uint 441 curpos(void) 442 { 443 ulong i, wx; 444 445 wx = 0; 446 for (i = fr->a[fr->cur].p0; i < f->dot.p1; ++i) 447 wx += runesiz(f->s.s[i], wx); 448 return wx; 449 } 450 451 static void 452 delete(int arg) 453 { 454 String s; 455 Address *a; 456 uint count; 457 458 if (!f->s.n) 459 return; 460 if (!arg) { 461 switch (arg = getr()) { 462 case 'x': arg = Letter; break; 463 case 'd': arg = Line; break; 464 case 'G': arg = Bottom; break; 465 case 'g': arg = Top; break; 466 case 'w': arg = Word; break; 467 case 't': arg = Till; break; 468 default: 469 return; 470 } 471 } 472 count = counter; 473 if ((arg = selection(arg)) < 0) 474 return; 475 str_init(&s); 476 a = &f->dot; 477 str_adds(&s, Strn(f->s.s + a->p0, a->p1 + 1 - a->p0)); 478 str_dup(&istr, s); 479 buf_add(NULL, &s, Delete, arg, count); 480 str_delete(&f->s, a->p0, a->p1 + 1); 481 str_close(&s); 482 if (a->p0 == f->s.n && a->p0) 483 --a->p0; 484 a->p1 = a->p0; 485 fr_update(); 486 } 487 488 static void 489 dot(int arg) 490 { 491 String ds; 492 Address *a; 493 494 if (f->b->prev == NULL) 495 return; 496 a = &f->dot; 497 arg = f->b->arg; 498 counter = f->b->count; 499 switch (f->b->c) { 500 case Insert: 501 if (arg == Down) 502 move(EndLine); 503 else 504 move(arg); 505 str_insert(&f->s, f->b->is, a->p0); 506 buf_add(&f->b->is, NULL, Insert, arg, counter); 507 break; 508 case Delete: 509 delete(arg); 510 break; 511 case Change: 512 str_init(&ds); 513 if (f->b->ds.n) { 514 selection(arg); 515 if (arg == Word || arg == Letter || arg > 0x7f) 516 ++a->p1; 517 str_adds(&ds 518 , Strn(f->s.s + a->p0, a->p1 - a->p0) 519 ); 520 str_delete(&f->s, a->p0, a->p1); 521 } 522 if (f->b->is.n) 523 str_insert(&f->s, f->b->is, f->dot.p0); 524 buf_add(&f->b->is, &ds, Change, arg, f->b->count); 525 str_close(&ds); 526 f->dot.p1 = f->dot.p0; 527 break; 528 } 529 fr_update(); 530 } 531 532 static void 533 redo(int arg) 534 { 535 if (f->b->next == NULL) 536 return; 537 if (arg) { 538 for (;f->b->next != NULL;) 539 redo(0); 540 return; 541 } 542 f->b = f->b->next; 543 if (f->b->ds.n) 544 str_delete(&f->s, f->b->p0, f->b->p0 + f->b->ds.n); 545 if (f->b->is.n) 546 str_insert(&f->s, f->b->is, f->b->p0); 547 f->dot.p0 = f->dot.p1 = f->b->p0; 548 fr_zero(fr); 549 fr_update(); 550 } 551 552 static void 553 escape(int c) 554 { 555 counter = 0; 556 c = getc2() - 0x30; 557 if (c > 0 && c <= 8) { 558 --c; 559 f = &file[c]; 560 fr = &frame[c]; 561 return; 562 } 563 ungetc(c + 0x30, stdin); 564 } 565 566 static uchar 567 getc2(void) 568 { 569 uchar c; 570 571 get: 572 c = getchar(); 573 if (c == (uchar)EOF) { 574 if (!feof(stdin)) 575 goto get; 576 exit(0); 577 } 578 return c; 579 } 580 581 static Rune 582 getr(void) 583 { 584 Rune r; 585 uchar c, seq; 586 587 r = 0; 588 seq = 0; 589 do { 590 c = getc2(); 591 if (c2r(&r, c, &seq) == -1) { 592 seq = 0; 593 ungetc(c, stdin); 594 } 595 } while (seq != 0); 596 return r; 597 } 598 599 static void 600 input(String* s, uint line, char* prefix) 601 { 602 static char *t; 603 Rune r; 604 605 for (;;) { 606 str2u(&t, *s); 607 msg(line, "%s%s", prefix, t); 608 switch (r = getr()) { 609 case Esc: 610 str_zero(s); 611 case '\n': 612 return; 613 case Del: 614 str_delr(s); 615 break; 616 default: 617 str_addr(s, r); 618 } 619 } 620 s->s[s->n] = '\0'; 621 } 622 623 static int 624 isword(uchar c) 625 { 626 switch (c) { 627 case ' ': case '\t': case '\n': case '.': 628 case '(': case ')': case '{': case '}': 629 case '[': case ']': case ':': case ';': 630 case ',': case '<': case '>': case '#': 631 case '*': case '+': case '-': case '!': 632 case '%': case '\\': case '/': case '"': 633 case '=': 634 return 0; 635 } 636 return 1; 637 } 638 639 static void 640 insert(int arg) 641 { 642 String s, c; 643 644 if (f->s.s[f->s.n - 1] != '\n') 645 str_addr(&f->s, '\n'); 646 str_init(&s), str_init(&c); 647 str_addr(&c, '\0'); 648 switch (arg) { 649 case StartLine: 650 case EndLine: 651 case Right: 652 move(arg); 653 break; 654 case Down: 655 move(EndLine); 656 str_addr(&s, '\n'); 657 str_insert(&f->s, s, f->dot.p0); 658 ++f->dot.p1; 659 break; 660 } 661 for (;;) { 662 fr_update(); 663 switch (c.s[0] = getr()) { 664 case Esc: 665 goto endmode; 666 case Del: 667 if (f->dot.p1 != f->dot.p0) { 668 str_delr(&s); 669 str_delete(&f->s, f->dot.p1 - 1, f->dot.p1); 670 --f->dot.p1; 671 } 672 break; 673 default: 674 str_addr(&s, c.s[0]); 675 str_insert(&f->s, c, f->dot.p1); 676 } 677 f->dot.p1 = f->dot.p0 + s.n; 678 } 679 endmode: 680 str_dup(&istr, s); 681 for (counter ? --counter : 0; counter; --counter) { 682 str_insert(&istr, s, istr.n); 683 str_insert(&f->s, s, f->dot.p0); 684 } 685 buf_add(&istr, NULL, Insert, arg, counter); 686 str_close(&s), str_close(&c); 687 f->dot.p0 = f->dot.p1; 688 if (f->dot.p1 >= f->s.n) 689 move(Left); 690 } 691 692 static void 693 init(void) 694 { 695 uint i; 696 697 for (i = 0; i < FILECOUNT; ++i) { 698 file_init(&file[i]); 699 fr_init(&frame[i]); 700 } 701 str_init(&srch); 702 str_init(&istr); 703 win_init(&w); 704 } 705 706 static void 707 file_close(int arg) 708 { 709 static char *s; 710 711 if (arg != -1) 712 f = &file[arg]; 713 if (f->bd != f->b) { 714 str2u(&s, f->name); 715 msg(w.wy / 2, RED("Save %s?") " [y/n]" 716 , f->name.n ? s : "-unnamed-" 717 ); 718 if (getr() == 'y') 719 file_save(arg); 720 } 721 str_close(&f->s); 722 str_close(&f->name); 723 for (;f->b->prev != NULL; f->b = f->b->prev); 724 buf_free(f->b); 725 file_init(f); 726 fr_zero(fr); 727 } 728 729 static void 730 file_init(File* f) 731 { 732 str_init(&f->s); 733 str_init(&f->name); 734 f->dot.p0 = 0; 735 f->dot.p1 = 0; 736 f->b = emalloc(sizeof(*f->b)); 737 f->bd = f->b; 738 } 739 740 static void 741 file_load(File* f) 742 { 743 FILE *disk; 744 ulong n; 745 char *s; 746 747 s = NULL; 748 str2u(&s, f->name); 749 disk = fopen(s, "r"); 750 if (disk == NULL) 751 return; 752 s = NULL; 753 n = 0; 754 do { 755 s = erealloc(s, n + 4096); 756 n += fread(s + n, 1, 4096, disk); 757 } while (!feof(disk)); 758 s[n] = '\0'; 759 u2str(&f->s, s); 760 free(s); 761 } 762 763 static void 764 file_open(int arg) 765 { 766 file_close(-1); 767 input(&f->name, w.wy / 2, GREEN("$ ")); 768 file_load(f); 769 } 770 771 static void 772 file_save(int arg) 773 { 774 static char *s; 775 FILE *disk; 776 ulong n; 777 778 if (arg != -1) 779 f = &file[arg]; 780 if (!f->name.n) { 781 input(&f->name, w.wy / 2, "File name: "); 782 if (!f->name.n) 783 return; 784 } 785 str2u(&s, f->name); 786 disk = fopen(s, "w"); 787 n = str2u(&s, f->s); 788 fwrite(s, n, 1, disk); 789 fclose(disk); 790 f->bd = f->b; 791 } 792 793 static void 794 fr_add(Frame* fr, Address a) 795 { 796 fr_insure(fr, ++fr->n); 797 fr->a[fr->n - 1] = a; 798 } 799 800 static void 801 fr_calc(void) 802 { 803 Frame fr0; 804 Posn p0; 805 806 for (;f->dot.p1 < fr->a[fr->cur].p0 && fr->cur; --fr->cur); 807 for (;f->dot.p1 > fr->a[fr->cur].p1 && fr->cur + 1 < fr->n 808 ; ++fr->cur 809 ); 810 if (!fr->n 811 || f->dot.p1 != f->dot.p0 812 || f->dot.p1 < fr->a[0].p0 813 || f->dot.p1 > fr->a[fr->n - 1].p1 814 || (fr->cur < w.wy && fr->a[0].p0) 815 || (fr->cur + w.wy > fr->n 816 && fr->a[fr->n - 1].p1 + 1 < f->s.n 817 ) 818 ) { 819 /*dot + bottom addresses*/ 820 fr_zero(fr); 821 for (p0 = f->dot.p1; p0 && f->s.s[p0 - 1] != '\n'; --p0); 822 for (;p0 < f->s.n && fr->n < w.wy * 2;) { 823 blind_reader(fr, p0); 824 p0 = fr->a[fr->n - 1].p1 + 1; 825 } 826 /*top addresses*/ 827 for (fr_init(&fr0) 828 ; fr->a[0].p0 && fr->cur < w.wy 829 ; fr->cur += fr0.n 830 ) { 831 for (p0 = fr->a[0].p0 - 1 832 ; p0 && f->s.s[p0 - 1] != '\n' 833 ; --p0 834 ); 835 blind_reader(&fr0, p0); 836 fr_insert(fr, fr0, 0); 837 fr_zero(&fr0); 838 } 839 fr_close(&fr0); 840 for (; f->dot.p1 > fr->a[fr->cur].p1 && fr->cur < fr->n 841 ; ++fr->cur 842 ); 843 } 844 } 845 846 static void 847 fr_close(Frame* fr) 848 { 849 free(fr->a); 850 } 851 852 static void 853 fr_init(Frame* fr) 854 { 855 fr->a = emalloc(32 * sizeof(*fr->a)); 856 fr->cur = 0; 857 fr->n = 0; 858 fr->size = 32; 859 fr->a[fr->cur].p0 = 0; 860 fr->a[fr->cur].p1 = 0; 861 } 862 863 static void 864 fr_insert(Frame* p, Frame q, ushort n) 865 { 866 fr_insure(p, p->n + q.n); 867 memmove(p->a + n + q.n, p->a + n, (p->n - n) * sizeof(*p->a)); 868 memmove(p->a + n, q.a, q.n * sizeof(*p->a)); 869 p->n += q.n; 870 } 871 872 static void 873 fr_insure(Frame* fr, ushort n) 874 { 875 if (n > fr->size) { 876 fr->size += n + 32; 877 fr->a = erealloc(fr->a, fr->size * sizeof(*fr->a)); 878 } 879 } 880 881 static void 882 fr_update(void) 883 { 884 static char stat[128], u[UTFMAX + 1]; 885 static char *fname, *urune; 886 Rune rune; 887 uint half; 888 889 half = w.wy / 2; 890 if (f->s.n) { 891 fr_calc(); 892 printf(ED); 893 blind_writer(half, fr->cur, half, half + (w.wy % 2)); 894 } else 895 printf(ED); 896 str2u(&fname, f->name.n ? f->name : Utf("-unnamed-")); 897 rune = f->s.s[f->dot.p1]; 898 if (rune < 0x20) 899 urune = ctrune[rune]; 900 else if (rune == 0x7f) 901 urune = "del"; 902 else { 903 r2u(u, rune); 904 urune = u; 905 } 906 snprintf(stat, w.wx, STATUS); /*i dont care. TODO: care*/ 907 msg(w.wy, "%s", stat); 908 curmov(curpos() + 1, half); 909 } 910 911 static void 912 fr_zero(Frame* fr) 913 { 914 fr->n = 0; 915 fr->cur = 0; 916 fr->a[fr->cur].p0 = 0; 917 fr->a[fr->cur].p1 = 0; 918 } 919 920 static void 921 move(int arg) 922 { 923 switch (arg) { 924 case Left: 925 if (f->dot.p1) 926 --f->dot.p1; 927 break; 928 case Right: 929 if (f->dot.p1 + 1 < f->s.n) 930 ++f->dot.p1; 931 break; 932 case Up: 933 if (fr->cur) 934 f->dot.p1 = fr->a[fr->cur - 1].p0; 935 else 936 f->dot.p1 = 0; 937 break; 938 case Down: 939 if (!fr->a[fr->cur].p1) 940 return; 941 if (fr->cur < fr->n - 1) 942 f->dot.p1 = fr->a[fr->cur + 1].p0; 943 else 944 f->dot.p1 = fr->a[fr->cur].p1 - 1; 945 break; 946 case HalfUp: 947 if (fr->cur < w.wy/2) 948 f->dot.p1 = 0; 949 else 950 f->dot.p1 = fr->a[fr->cur - w.wy/2].p0; 951 break; 952 case HalfDown: 953 if (!f->s.n) 954 break; 955 if (fr->n - fr->cur <= w.wy/2) { 956 if (fr->a[fr->n - 1].p1 <= f->s.n) 957 f->dot.p1 = fr->a[fr->n - 1].p0; 958 else 959 f->dot.p1 = f->s.n; 960 } else 961 f->dot.p1 = fr->a[fr->cur + w.wy/2].p0; 962 break; 963 case Top: 964 f->dot.p1 = 0; 965 break; 966 case Bottom: 967 if (f->s.n) 968 f->dot.p1 = f->s.n - 1; 969 break; 970 case StartLine: 971 if (fr->cur) 972 for (;fr->cur > 1 973 && f->s.s[fr->a[fr->cur].p0 - 1] != '\n' 974 ; --fr->cur 975 ); 976 f->dot.p1 = fr->a[fr->cur].p0; 977 break; 978 case EndLine: 979 for (;f->dot.p1 + 1 < f->s.n && f->s.s[f->dot.p1] != '\n' 980 ; ++f->dot.p1 981 ); 982 break; 983 case Word: 984 for (;f->dot.p1 + 1 < f->s.n && isword(f->s.s[f->dot.p1]) 985 ; ++f->dot.p1 986 ); 987 for (;f->dot.p1 + 1 < f->s.n && !isword(f->s.s[f->dot.p1]) 988 ; ++f->dot.p1 989 ); 990 break; 991 case EndWord: 992 move(Right); 993 for (;f->dot.p1 < f->s.n && !isword(f->s.s[f->dot.p1]) 994 ; ++f->dot.p1 995 ); 996 for (;f->dot.p1 < f->s.n && isword(f->s.s[f->dot.p1]) 997 ; ++f->dot.p1 998 ); 999 move(Left); 1000 break; 1001 case PrevWord: 1002 move(Left); 1003 for (;f->dot.p1 > 0 && !isword(f->s.s[f->dot.p1]) 1004 ; --f->dot.p1 1005 ); 1006 for (;f->dot.p1 > 0 && isword(f->s.s[f->dot.p1]) 1007 ; --f->dot.p1 1008 ); 1009 if (f->dot.p1) 1010 move(Right); 1011 break; 1012 }; 1013 f->dot.p0 = f->dot.p1; 1014 fr_calc(); 1015 } 1016 1017 static void 1018 quit(int arg) 1019 { 1020 uint i; 1021 1022 for (i = 0; i < FILECOUNT; ++i) 1023 file_close(i); 1024 win_end(); 1025 exit(arg); 1026 } 1027 1028 static void 1029 gmove(int arg) 1030 { 1031 if (arg == Top) { 1032 move(Top); 1033 for (counter ? --counter : 0; counter; --counter) { 1034 move(EndLine); 1035 move(Right); 1036 } 1037 return; 1038 } 1039 for (!counter ? ++counter : 0; counter; --counter) 1040 move(arg); 1041 } 1042 1043 static void 1044 msg(uint line, char* fmt, ...) 1045 { 1046 va_list ap; 1047 1048 curmov(0, line); 1049 printf(EL); 1050 va_start(ap, fmt); 1051 vprintf(fmt, ap); 1052 va_end(ap); 1053 } 1054 1055 static void 1056 paste(int arg) 1057 { 1058 str_insert(&f->s, istr, f->dot.p0); 1059 buf_add(&istr, NULL, Insert, 0, 1); 1060 } 1061 1062 static void 1063 pline(int arg) 1064 { 1065 ulong i, l, h, t; 1066 1067 l = 1; 1068 t = fr->a[fr->cur].p0; 1069 for (i = 0; i < t; ++i) 1070 if (f->s.s[i] == '\n') 1071 ++l; 1072 h = w.wy / 2; 1073 for (i = 0; i < h; ++i) 1074 if (h - i < l) { 1075 curmov(0, i); 1076 printf("%4lu ", h - i); 1077 } 1078 t = fr->n - fr->cur; 1079 for (i = h + 1; i < w.wy; ++i) 1080 if (i - h < t) { 1081 curmov(0, i); 1082 printf("%4lu ", i - h); 1083 } 1084 curmov(0, h); 1085 printf("%-4lu ", l); 1086 i = getc2(); 1087 if (i != Esc) 1088 ungetc(i, stdin); 1089 } 1090 1091 static uchar 1092 r2u(char *s, Rune r) 1093 { 1094 char* p; 1095 1096 p = s; 1097 if (r < (1 << 7)) { 1098 *p++ = r; 1099 } else if (r < (1 << 11)) { 1100 *p++ = 0xc0 | (r >> 6); 1101 *p++ = 0x80 | (r & 0x3f); 1102 } else if (r < (1 << 16)) { 1103 *p++ = 0xe0 | (r >> 12); 1104 *p++ = 0x80 | ((r >> 6) & 0x3f); 1105 *p++ = 0x80 | (r & 0x3f); 1106 } else if (r < (1 << 21)) { 1107 *p++ = 0xf0 | (r >> 18); 1108 *p++ = 0x80 | ((r >> 12) & 0x3f); 1109 *p++ = 0x80 | ((r >> 6) & 0x3f); 1110 *p++ = 0x80 | (r & 0x3f); 1111 } else if (r < (1 << 26)) { 1112 *p++ = 0xf8 | (r >> 24); 1113 *p++ = 0x80 | ((r >> 18) & 0x3f); 1114 *p++ = 0x80 | ((r >> 12) & 0x3f); 1115 *p++ = 0x80 | ((r >> 6) & 0x3f); 1116 *p++ = 0x80 | (r & 0x3f); 1117 } else if (r < (1 << 31)) { 1118 *p++ = 0xfe | (r >> 30); 1119 *p++ = 0x80 | ((r >> 24) & 0x3f); 1120 *p++ = 0x80 | ((r >> 18) & 0x3f); 1121 *p++ = 0x80 | ((r >> 12) & 0x3f); 1122 *p++ = 0x80 | ((r >> 6) & 0x3f); 1123 *p++ = 0x80 | (r & 0x3f); 1124 } 1125 *p = '\0'; 1126 return p - s; 1127 } 1128 1129 static uint 1130 runesiz(Rune c, ulong wx) 1131 { 1132 if (c == '\n') 1133 die("runesiz(): newline."); 1134 return (c == '\t') ? w.t - (wx % w.t) : 1; 1135 } 1136 1137 static void 1138 search(int arg) 1139 { 1140 Posn pos; 1141 Rune *r; 1142 1143 f->s.s[f->s.n] = 0; 1144 if (arg == '/' || arg == '?') { 1145 str_zero(&srch); 1146 input(&srch, w.wy, "/"); 1147 for (pos = 0; pos < srch.n; ++pos) 1148 if (srch.s[pos] == '^') 1149 srch.s[pos] = '\n'; 1150 } 1151 if (arg == '/' || arg == 'n') { 1152 move(Right); 1153 r = Strnstr(f->s.s + f->dot.p0, srch.s, srch.n); 1154 if (r == NULL) { 1155 move(Left); 1156 return; 1157 } 1158 } else { 1159 pos = f->dot.p1; 1160 if (srch.s[0] == '\n' && srch.s[1] != '\n') 1161 move(Left); 1162 for (;;) { 1163 for (;move(Left), f->dot.p1 1164 && f->s.s[f->dot.p1] != srch.s[0] 1165 ; 1166 ); 1167 if (!memcmp(f->s.s + f->dot.p1 1168 , srch.s , srch.n * sizeof(*srch.s) 1169 )) 1170 break; 1171 if (!f->dot.p1) { 1172 f->dot.p0 = f->dot.p1 = pos; 1173 return; 1174 } 1175 } 1176 r = f->s.s + f->dot.p1; 1177 } 1178 f->dot.p0 = f->dot.p1 = r - f->s.s; 1179 if (srch.s[0] == '\n' && srch.s[1] != '\n') 1180 move(Right); 1181 fr_update(); 1182 } 1183 1184 static int 1185 selection(int arg) 1186 { 1187 Posn p0; 1188 1189 if (!counter) 1190 ++counter; 1191 if (arg > 0x7f) { 1192 arg -= 0x7f; 1193 goto till; 1194 } 1195 p0 = f->dot.p1 = f->dot.p0; 1196 switch (arg) { 1197 case Letter: 1198 p0 = f->dot.p0; 1199 for (;counter > 1; --counter) 1200 move(Right); 1201 break; 1202 case Line: 1203 move(StartLine); 1204 p0 = f->dot.p0; 1205 for (;counter; --counter) { 1206 move(EndLine); 1207 move(Right); 1208 } 1209 if (f->dot.p1 + 1 < f->s.n) 1210 move(Left); 1211 break; 1212 case Bottom: 1213 move(StartLine); 1214 move(Left); 1215 p0 = f->dot.p0; 1216 move(Bottom); 1217 break; 1218 case Top: 1219 p0 = 0; 1220 move(EndLine); 1221 break; 1222 case Word: 1223 p0 = f->dot.p0; 1224 for (;counter; --counter) 1225 move(EndWord); 1226 break; 1227 case Till: 1228 arg = getr(); 1229 if (arg == Esc) 1230 return 0; 1231 till: 1232 p0 = f->dot.p0; 1233 for (;counter && f->dot.p1 + 1 < f->s.n; --counter) 1234 for (++f->dot.p1 1235 ; f->dot.p1 + 1 < f->s.n 1236 && f->s.s[f->dot.p1 + 1] != arg 1237 ; ++f->dot.p1 1238 ); 1239 if (f->s.s[f->dot.p1 + 1] != arg) { 1240 f->dot.p1 = f->dot.p0; 1241 return -1; 1242 } 1243 arg += 0x7f; 1244 break; 1245 } 1246 f->dot.p0 = p0; 1247 counter = 0; 1248 return arg; 1249 } 1250 1251 static ulong 1252 str2u(char** u, String s) 1253 { 1254 ulong i, n; 1255 1256 n = 0; 1257 *u = erealloc(*u, (s.n + 1) * UTFMAX); 1258 for (i = 0; i < s.n; ++i) 1259 n += r2u(*u + n, s.s[i]); 1260 (*u)[n] = '\0'; 1261 return n; 1262 } 1263 1264 static void 1265 str_init(String* p) 1266 { 1267 p->s = emalloc(MINSIZE * sizeof(*p->s)); 1268 p->n = 0; 1269 p->size = MINSIZE; 1270 p->s[p->n] = '\0'; 1271 } 1272 1273 static void 1274 str_close(String* p) 1275 { 1276 free(p->s); 1277 } 1278 1279 static void 1280 str_dup(String* p, String q) 1281 { 1282 str_zero(p); 1283 str_adds(p, q); 1284 } 1285 1286 static void 1287 str_zero(String* p) 1288 { 1289 if (p->size > MAXEMPTY) { 1290 p->s = erealloc(p->s, MAXEMPTY * sizeof(*p->s)); 1291 p->size = MAXEMPTY; 1292 } 1293 p->n = 0; 1294 memset(p->s, 0, p->size * sizeof(*p->s)); 1295 } 1296 1297 static void 1298 str_insure(String* p, ulong n) 1299 { 1300 if (p->size < n + 1) { 1301 p->size = n + MAXEMPTY; 1302 p->s = erealloc(p->s, p->size * sizeof(*p->s)); 1303 } 1304 } 1305 1306 static void 1307 str_addr(String* p, Rune r) 1308 { 1309 str_insure(p, p->n + 1); 1310 p->s[p->n++] = r; 1311 p->s[p->n] = '\0'; 1312 } 1313 1314 static void 1315 str_adds(String *p, String q) 1316 { 1317 str_insure(p, p->n + q.n); 1318 memcpy(p->s + p->n, q.s, q.n * sizeof(*q.s)); 1319 p->n += q.n; 1320 p->s[p->n] = '\0'; 1321 } 1322 1323 static void 1324 str_delr(String* p) 1325 { 1326 if (p->n) 1327 p->s[--p->n] = '\0'; 1328 } 1329 1330 static void 1331 str_insert(String* p, String q, Posn p0) 1332 { 1333 str_insure(p, p->n + q.n); 1334 memmove(p->s + p0 + q.n, p->s + p0 1335 , (p->n - p0) * sizeof(*p->s) 1336 ); 1337 memmove(p->s + p0, q.s, q.n * sizeof(*q.s)); 1338 p->n += q.n; 1339 p->s[p->n] = '\0'; 1340 } 1341 1342 static void 1343 str_delete(String* p, Posn p0, Posn p1) 1344 { 1345 memmove(p->s + p0, p->s + p1, (p->n - p1) * sizeof(*p->s)); 1346 p->n -= p1 - p0; 1347 p->s[p->n] = '\0'; 1348 } 1349 1350 static void 1351 u2str(String *s, char *u) 1352 { 1353 Rune r; 1354 uchar seq; 1355 1356 str_zero(s); 1357 for (seq = 0; *u != '\0'; ++u) { 1358 if (c2r(&r, *u, &seq) == -1) 1359 --u; 1360 else if (seq == 0) 1361 str_addr(s, r); 1362 } 1363 } 1364 1365 static void 1366 undo(int arg) 1367 { 1368 if (f->b->prev == NULL) 1369 return; 1370 if (arg) { 1371 for (;f->b->prev != NULL;) 1372 undo(0); 1373 return; 1374 } 1375 if (f->b->is.n) 1376 str_delete(&f->s, f->b->p0, f->b->p0 + f->b->is.n); 1377 if (f->b->ds.n) 1378 str_insert(&f->s, f->b->ds, f->b->p0); 1379 f->dot.p0 = f->dot.p1 = f->b->p0; 1380 f->b = f->b->prev; 1381 fr_zero(fr); 1382 fr_update(); 1383 } 1384 1385 static void 1386 yank(int arg) 1387 { 1388 Address a; 1389 1390 if (!f->s.n) 1391 return; 1392 if (!arg) { 1393 switch (arg = getr()) { 1394 case 'y': arg = Line; break; 1395 case 'G': arg = Bottom; break; 1396 case 'g': arg = Top; break; 1397 case 'w': arg = Word; break; 1398 case 't': arg = Till; break; 1399 default: 1400 return; 1401 } 1402 } 1403 if ((arg = selection(arg)) < 0) 1404 return; 1405 a = f->dot; 1406 str_dup(&istr, Strn(f->s.s + a.p0, a.p1 + 1 - a.p0)); 1407 } 1408 1409 int 1410 main(int argc, char* argv[]) 1411 { 1412 uint i; 1413 uchar c; 1414 1415 init(); 1416 if (argv[1]) { 1417 str_adds(&f->name, Utf(argv[1])); 1418 file_load(f); 1419 } 1420 for (;;) { 1421 fr_update(); 1422 c = getr(); 1423 for (i = 0; i < LENGTH(keys); ++i) { 1424 if (keys[i].key == c) { 1425 keys[i].func(keys[i].value); 1426 break; 1427 } 1428 } 1429 } 1430 }