1 /*-------------------------------------------------------*/
2 /* edit.c       ( NTHU CS MapleBBS Ver 2.36 )            */
3 /*-------------------------------------------------------*/
4 /* target : simple ANSI/Chinese editor                   */
5 /* create : 1995/03/29                                   */
6 /* update : 2009/12/18                 Dopin: �屼���Ϊ� */
7 /*-------------------------------------------------------*/
8 
9 #include <stdlib.h>
10 #include <sys/param.h>
11 #include "bbs.h"
12 
13 #define KEEP_EDITING    -2
14 #define SCR_WIDTH       80
15 #define BACKUP_LIMIT    100
16 
17 textline *firstline = NULL;
18 textline *lastline = NULL;
19 textline *currline = NULL;
20 textline *blockline = NULL;
21 textline *top_of_win = NULL;
22 textline *deleted_lines = NULL;
23 
24 extern int KEY_ESC_arg;
25 extern int local_article;
26 
27 char line[WRAPMARGIN + 2];
28 int currpnt, currln, totaln;
29 int curr_window_line;
30 int redraw_everything;
31 int insert_character;
32 int my_ansimode;
33 int raw_mode;
34 int edit_margin;
35 int phone_mode;
36 int blockln  = -1;
37 int blockpnt;
38 int prevln = -1;
39 int prevpnt;
40 int modified;
41 int indent_mode  = 1;
42 int insert_c = ' ';
43 struct stat st0;
44 char reset_color[4] = "";
45 char* FPath;
46 
47 char fp_bak[] = "bak";
48 char *my_edit_mode[2] =
49 {"���N", "���J"};
50 
51 char save_title[STRLEN];
52 
53 /* ----------------------------------------------------- */
54 /* �O����޲z�P�s��B�z                                  */
55 /* ----------------------------------------------------- */
56 
indigestion(i)57 static void indigestion(i)
58 {
59   fprintf(stderr, "�Y������ %d\n", i);
60 }
61 
62 /* ----------------------------------------------------- */
63 /* Thor: ansi �y���ഫ  for color �s��Ҧ�               */
64 /* ----------------------------------------------------- */
65 
ansi2n(int ansix,textline * line)66 static int ansi2n(int ansix, textline * line)
67 {
68   register char *data, *tmp;
69   register char ch;
70 
71   data = tmp = line->data;
72 
73   while(*tmp) {
74     if (*tmp == KEY_ESC)
75     {
76       while((ch = *tmp) && !isalpha(ch))
77         tmp++;
78       if (ch)
79         tmp++;
80       continue;
81     }
82     if (ansix <= 0) break;
83     tmp++;
84     ansix--;
85   }
86   return tmp - data;
87 }
88 
n2ansi(int nx,textline * line)89 static int n2ansi(int nx, textline * line)
90 {
91   register ansix = 0;
92   register char *tmp,*nxp;
93   register char ch;
94 
95   tmp = nxp = line->data;
96   nxp += nx;
97 
98   while(*tmp){
99     if (*tmp == KEY_ESC)
100     {
101       while((ch = *tmp) && !isalpha(ch))
102         tmp++;
103       if (ch)
104         tmp++;
105       continue;
106     }
107     if (tmp >= nxp) break;
108     tmp++;
109     ansix++;
110   }
111   return ansix;
112 }
113 
114 /* ----------------------------------------------------- */
115 /* �ù��B�z�G���U�T���B��ܽs�褺�e                      */
116 /* ----------------------------------------------------- */
117 
edit_msg(void)118 static void edit_msg(void)
119 {
120   static char *edit_mode[2] = {"���N", "���J"};
121   register int n = currpnt;
122 
123   if (my_ansimode)                      /* Thor: �@ ansi �s�� */
124     n = n2ansi(n, currline);
125   n++;
126   move(b_lines, 0);
127   clrtoeol();
128   prints("\033[%sm  �s��峹  \033[31;47m  (Ctrl-G)\033[30m �u�W���U����  \033[31m(^X,^Q)\033[30m �ɮ׳B�z ��%s�x%c%c%c%c�� %3d:%3d  \033[m",
129     (modified == -1) ? "34;46" : "37;44",
130     edit_mode[insert_character],
131     my_ansimode ? 'A' : 'a', indent_mode ? 'I' : 'i',
132     phone_mode ? 'P' : 'p', raw_mode ? 'R' : 'r',
133     currln + 1, n);
134 }
135 
back_line(pos,num)136 static textline * back_line(pos, num)
137   register textline *pos;
138   int num;
139 {
140   while (num-- > 0)
141   {
142     register textline *item;
143 
144     if (pos && (item = pos->prev))
145     {
146       pos = item;
147       currln--;
148     }
149   }
150   return pos;
151 }
152 
153 
forward_line(pos,num)154 static textline *forward_line(pos, num)
155   register textline *pos;
156   int num;
157 {
158   while (num-- > 0)
159   {
160     register textline *item;
161 
162     if (pos && (item = pos->next))
163     {
164       pos = item;
165       currln++;
166     }
167   }
168   return pos;
169 }
170 
getlineno()171 static int getlineno()
172 {
173   int cnt = 0;
174   textline *p = currline;
175 
176   while (p && (p != top_of_win))
177   {
178     cnt++;
179     p = p->prev;
180   }
181   return cnt;
182 }
183 
killsp(s)184 static char *killsp(s)
185   char *s;
186 {
187   while (*s == ' ')
188     s++;
189   return s;
190 }
191 
alloc_line()192 static textline *alloc_line()
193 {
194   extern void *malloc();
195   register textline *p;
196 
197   if (p = (textline *) malloc(sizeof(textline)))
198   {
199     memset(p, 0, sizeof(textline));
200     return p;
201   }
202 
203   indigestion(13);
204   abort_bbs();
205 }
206 
207 /* ----------------------------------------------------- */
208 /* append p after line in list. keeps up with last line  */
209 /* ----------------------------------------------------- */
210 
append(p,line)211 static void append(p, line)
212   register textline *p, *line;
213 {
214   register textline *n;
215 
216   if (p->next = n = line->next)
217     n->prev = p;
218   else
219     lastline = p;
220   line->next = p;
221   p->prev = line;
222 }
223 
224 
225 /* ----------------------------------------------------- */
226 /* delete_line deletes 'line' from the list,             */
227 /* and maintains the lastline, and firstline pointers.   */
228 /* ----------------------------------------------------- */
229 
delete_line(line)230 static void delete_line(line)
231   register textline *line;
232 {
233   register textline *p = line->prev;
234   register textline *n = line->next;
235 
236   if (!p && !n)
237   {
238     line->data[0] = line->len = 0;
239     return;
240   }
241   if (n)
242     n->prev = p;
243   else
244     lastline = p;
245   if (p)
246     p->next = n;
247   else
248     firstline = n;
249   strcat(line->data, "\n");
250   line->prev = deleted_lines;
251   deleted_lines = line;
252   totaln--;
253   modified = -2;
254 }
255 
256 /* woju */
257 
undelete_line()258 undelete_line()
259 {
260    textline* p = deleted_lines;
261 
262    textline* currline0 = currline;
263    textline* top_of_win0 = top_of_win;
264    int currpnt0 = currpnt;
265    int currln0 = currln;
266    int curr_window_line0 = curr_window_line;
267    int indent_mode0 = indent_mode;
268 
269 
270    if (!deleted_lines)
271       return 0;
272 
273    indent_mode = 0;
274    insert_string(deleted_lines->data);
275    indent_mode = indent_mode0;
276    deleted_lines = deleted_lines->prev;
277    free(p);
278 
279    currline = currline0;
280    top_of_win = top_of_win0;
281    currpnt = currpnt0;
282    currln = currln0;
283    curr_window_line = curr_window_line0;
284    modified = -2;
285 }
286 
indent_spcs()287 int indent_spcs()
288 {
289    textline* p;
290    int spcs;
291 
292    if (!indent_mode)
293       return 0;
294 
295    for (p = currline; p; p = p->prev) {
296       for (spcs = 0; p->data[spcs] == ' '; ++spcs)
297          ;
298       if (p->data[spcs])
299          return spcs;
300    }
301    return 0;
302 }
303 
304 /* ----------------------------------------------------- */
305 /* split 'line' right before the character pos           */
306 /* ----------------------------------------------------- */
307 
split(line,pos)308 static void split(line, pos)
309   register textline *line;
310   register int pos;
311 {
312   if (pos <= line->len)
313   {
314     register textline *p = alloc_line();
315     register char *ptr;
316     int spcs = indent_spcs();
317 
318     totaln++;
319 
320     p->len = line->len - pos + spcs;
321     line->len = pos;
322 
323     memset(p->data, ' ', spcs);
324     p->data[spcs] = 0;
325     strcat(p->data, (ptr = line->data + pos));
326     ptr[0] = '\0';
327     append(p, line);
328     if (line == currline && pos <= currpnt)
329     {
330       currline = p;
331       if (pos == currpnt)
332          currpnt = spcs;
333       else
334          currpnt -= pos;
335       curr_window_line++;
336       currln++;
337     }
338     redraw_everything = YEA;
339     modified = -2;
340   }
341 }
342 
343 /* ----------------------------------------------------- */
344 /* 1) lines were joined and one was deleted              */
345 /* 2) lines could not be joined                          */
346 /* 3) next line is empty                                 */
347 /* returns false if:                                     */
348 /* 1) Some of the joined line wrapped                    */
349 /* ----------------------------------------------------- */
350 
join(line)351 static int join(line)
352   register textline *line;
353 {
354   register textline *n;
355   register int ovfl;
356 
357   if (!(n = line->next))
358     return YEA;
359   if (!*killsp(n->data))
360     return YEA;
361 
362   modified = -2;
363   ovfl = line->len + n->len - WRAPMARGIN;
364   if (ovfl < 0)
365   {
366     strcat(line->data, n->data);
367     line->len += n->len;
368     delete_line(n);
369     return YEA;
370   }
371   else
372   {
373     register char *s;
374 
375     s = n->data + n->len - ovfl - 1;
376     while (s != n->data && *s == ' ')
377       s--;
378     while (s != n->data && *s != ' ')
379       s--;
380     if (s == n->data)
381       return YEA;
382     split(n, (s - n->data) + 1);
383     if (line->len + n->len >= WRAPMARGIN)
384     {
385       indigestion(0);
386       return YEA;
387     }
388     join(line);
389     n = line->next;
390     ovfl = n->len - 1;
391     if (ovfl >= 0 && ovfl < WRAPMARGIN - 2)
392     {
393       s = &(n->data[ovfl]);
394       if (*s != ' ')
395       {
396         strcpy(s, " ");
397         n->len++;
398       }
399     }
400     return NA;
401   }
402 }
403 
insert_char(ch)404 static void insert_char(ch)
405   register int ch;
406 {
407   register textline *p = currline;
408   register int i = p->len;
409   register char *s;
410   int wordwrap = YEA;
411 
412   if (currpnt > i)
413   {
414     indigestion(1);
415     return;
416   }
417   if (currpnt < i && !insert_character)
418   {
419     p->data[currpnt++] = ch;
420     if (my_ansimode) /* Thor: ansi �s��, �i�Hoverwrite, ���\�� ansi code */
421        currpnt = ansi2n(n2ansi(currpnt, p),p);
422   }
423   else
424   {
425     while (i >= currpnt)
426     {
427       p->data[i + 1] = p->data[i];
428       i--;
429     }
430     p->data[currpnt++] = ch;
431     i = ++(p->len);
432   }
433   if (i < WRAPMARGIN)
434     return;
435   split(p, WRAPMARGIN / 2);
436 }
437 
insert_string(str)438 insert_string(str)
439   char *str;
440 {
441   int ch;
442 
443   while (ch = *str++)
444   {
445 
446 #ifdef BIT8
447     if (isprint2(ch) || ch == '')
448 #else
449     if (isprint(ch))
450 #endif
451 
452     {
453       insert_char(ch);
454     }
455     else if (ch == '\t')
456     {
457       do
458       {
459         insert_char(' ');
460       } while (currpnt & 0x7);
461     }
462     else if (ch == '\n')
463       split(currline, currpnt);
464   }
465 }
466 
delete_char()467 static void delete_char()
468 {
469   register int len;
470 
471   if (len = currline->len)
472   {
473     register int i;
474     register char *s;
475 
476     if (currpnt >= len)
477     {
478       indigestion(1);
479       return;
480     }
481     for (i = currpnt, s = currline->data + i; i != len; i++, s++)
482       s[0] = s[1];
483     currline->len--;
484   }
485 }
486 
load_file(fp)487 static void load_file(fp)
488   FILE *fp;
489 {
490   int indent_mode0 = indent_mode;
491 
492   indent_mode = 0;
493   while (fgets(line, WRAPMARGIN + 2, fp))
494     insert_string(line);
495   fclose(fp);
496   indent_mode = indent_mode0;
497 }
498 
499 
500 /* ----------------------------------------------------- */
501 /* �Ȧs��                                                */
502 /* ----------------------------------------------------- */
503 
ask_tmpbuf()504 static char *ask_tmpbuf()
505 {
506   static char fp_buf[10] = "buf.0";
507   static char msg[] = "�п�ܼȦs�� (0-9)[0]: ";
508 
509   msg[19] = fp_buf[4];
510   do
511   {
512     if (!getdata(3, 0, msg, fp_buf + 4, 4, DOECHO))
513       fp_buf[4] = msg[19];
514   } while (fp_buf[4] < '0' || fp_buf[4] > '9');
515   return fp_buf;
516 }
517 
read_tmpbuf(int n)518 static void read_tmpbuf(int n)
519 {
520   FILE *fp;
521   char fp_tmpbuf[80];
522   char tmpfname[] = "buf.0";
523   char *tmpf;
524   char ans[4] = "y";
525 
526   if (0 <= n && n <= 9) {
527      tmpfname[4] = '0' + n;
528      tmpf = tmpfname;
529   }
530   else {
531      tmpf = ask_tmpbuf();
532      n = tmpf[4] - '0';
533   }
534 
535   setuserfile(fp_tmpbuf, tmpf);
536 
537 /* woju */
538   if (n != 0 && n != 5 && more(fp_tmpbuf, NA) != -1)
539      getdata(b_lines - 1, 0, "�T�wŪ�J��(Y/N)?[Y]",  ans, 4, LCECHO);
540   if (*ans != 'n' && (fp = fopen(fp_tmpbuf, "r")))
541   {
542     modified = -2;
543     prevln = currln;
544     prevpnt = currpnt;
545     load_file(fp);
546     while (curr_window_line >= b_lines)
547     {
548       curr_window_line--;
549       top_of_win = top_of_win->next;
550     }
551   }
552 }
553 
write_tmpbuf()554 static void write_tmpbuf()
555 {
556   FILE *fp;
557   char fp_tmpbuf[80], ans[4];
558   textline *p;
559 
560   setuserfile(fp_tmpbuf, ask_tmpbuf());
561   if (dashf(fp_tmpbuf))
562   {
563     more(fp_tmpbuf, NA);
564     getdata(b_lines - 1, 0, "�Ȧs�ɤw����� (A)���[ (W)�мg (Q)�����H[A] ",
565       ans, 4, LCECHO);
566 
567     if (ans[0] == 'q')
568       return;
569   }
570 
571   fp = fopen(fp_tmpbuf, (ans[0] == 'w' ? "w" : "a+"));
572   for (p = firstline; p; p = p->next)
573   {
574     if (p->next || p->data[0])
575       fprintf(fp, "%s\n", p->data);
576   }
577   fclose(fp);
578 }
579 
erase_tmpbuf()580 static void erase_tmpbuf()
581 {
582   char fp_tmpbuf[80];
583   char ans[4] = "n";
584 
585   setuserfile(fp_tmpbuf, ask_tmpbuf());
586 /* woju */
587   if (more(fp_tmpbuf, NA) != -1)
588      getdata(b_lines - 1, 0, "�T�w�R����(Y/N)?[N]",  ans, 4, LCECHO);
589   if (*ans == 'y')
590      unlink(fp_tmpbuf);
591 }
592 
593 /* ----------------------------------------------------- */
594 /* �ɮ׳B�z�GŪ�ɡB�s�ɡB���D�Bñ�W��                    */
595 /* ----------------------------------------------------- */
596 
read_file(fpath)597 static void read_file(fpath)
598   char *fpath;
599 {
600   FILE *fp;
601 
602   if ((fp = fopen(fpath, "r")) == NULL)
603     return;
604   load_file(fp);
605 }
606 
write_file(fpath,saveheader)607 static int write_file(fpath, saveheader)
608   char *fpath;
609   int saveheader;
610 {
611   FILE *fp;
612   textline *p, *v;
613   char ans[TTLEN], *msg;
614   int aborted = 0;
615 
616   if (!saveheader) {
617      stand_title("�ɮ׳B�z");
618      getdata(1, 0, "[S]�x�s (A)��� (E)�~�� (R/W/D)Ū�g�R�Ȧs�ɡH", ans, 4, LCECHO);
619   }
620   else
621      *ans = 's';
622 
623   switch (ans[0])
624   {
625   case 'a':
626     outs("�峹 �S�� �s�J");
627     aborted = -1;
628     break;
629 
630   case 'r':
631     read_tmpbuf(-1);
632 
633   case 'e':
634     return KEEP_EDITING;
635 
636   case 'w':
637     write_tmpbuf();
638     return KEEP_EDITING;
639 
640   case 'd':
641     erase_tmpbuf();
642     return KEEP_EDITING;
643 
644   case 'S':
645      saveheader = YEA;
646   case 's':
647     local_article = 0;
648     break;
649   }
650 
651   if (!aborted) {
652      struct stat st;
653 
654      if (stat(FPath, &st) != -1 && st.st_mtime != st0.st_mtime) {
655         char buf[200];
656 
657         sprintf(buf, "�g�Jĵ�i: %s �w�Q�䥦�{����ʹL", FPath);
658         stand_title(buf);
659         getdata(1, 0, "�T�w�x�s(Y/N)�H[N]", ans, 4, LCECHO);
660         if (*ans != 'y')
661            return KEEP_EDITING;
662      }
663      if ((fp = fopen(fpath, "w")) == NULL) {
664         stand_title("�g�J����: ��g��Ȧs��");
665         write_tmpbuf();
666         return KEEP_EDITING;
667      }
668   }
669 
670   for (p = firstline; p; p = v)
671   {
672     v = p->next;
673     if (!aborted)
674     {
675       strncpy(line, p->data, WRAPMARGIN - 1);
676       if (v || line[0])
677       {
678         trim(line);
679         fprintf(fp, "%s\n", line);
680       }
681     }
682     if (!saveheader)
683        free(p);
684   }
685   if (!saveheader)
686      currline = NULL;
687 
688   if (!aborted) {
689      fclose(fp);
690      stat(FPath, &st0);
691      modified = -1;
692   }
693 
694   return saveheader ? KEEP_EDITING : aborted;
695 }
696 
edit_outs(text)697 edit_outs(text)
698   char *text;
699 {
700   register int column = 0;
701   register char ch;
702 
703   while ((ch = *text++) && (++column < SCR_WIDTH))
704   {
705     outch(ch == 27 ? '*' : ch);
706   }
707 }
708 
block_outs(char * text,int column)709 block_outs(char* text, int column)
710 {
711   register char ch;
712 
713   while ((ch = *text++) && (++column < SCR_WIDTH))
714   {
715     outch(ch == 27 ? '*' : ch);
716   }
717 }
718 
719 int outs();
720 
display_buffer()721 static void display_buffer()
722 {
723   register textline *p;
724   register int i;
725   int inblock;
726   char buf[WRAPMARGIN + 2];
727   int min, max;
728   int (*OUTS)();
729 
730   if (currpnt > blockpnt) {
731      min = blockpnt;
732      max = currpnt;
733   }
734   else {
735      min = currpnt;
736      max = blockpnt;
737   }
738 
739   OUTS = my_ansimode ? outs : edit_outs;
740 
741   for (p = top_of_win, i = 0; i < b_lines; i++)
742   {
743 
744     move(i, 0);
745     clrtoeol();
746 /*
747 woju
748 */
749     if (blockln >= 0
750         && (blockln <= currln
751               && blockln <= (currln - curr_window_line + i)
752               &&            (currln - curr_window_line + i) <= currln
753            ||
754                  currln  <= (currln - curr_window_line + i)
755               &&            (currln - curr_window_line + i) <= blockln)) {
756        outs("");
757        inblock = 1;
758     }
759     else
760        inblock = 0;
761     if (p)
762     {
763       if (currln == blockln && p == currline && max > min) {
764          if (min > edit_margin) {
765             outs("");
766             strncpy(buf, p->data + edit_margin, min - edit_margin);
767             buf[min - edit_margin] = 0;
768             block_outs(buf, 0);
769          }
770          outs("");
771          if (min > edit_margin) {
772             strncpy(buf, p->data + min, max - min);
773             buf[max - min] = 0;
774             block_outs(buf, min - edit_margin);
775          }
776          else {
777             strncpy(buf, p->data + edit_margin, max - edit_margin);
778             buf[max - edit_margin] = 0;
779             block_outs(buf, 0);
780          }
781          outs("");
782          block_outs(p->data + max, max - edit_margin);
783       }
784       else
785          OUTS(&p->data[edit_margin]);
786       p = p->next;
787       if (inblock)
788          outs("");
789     }
790     else
791       outch('~');
792   }
793   edit_msg();
794 }
795 
796 static char *vedithelp[] =
797 {
798   "\01�@����O",
799   "^X       �ɮ׳B�z       ^L             ���s��ܵe��",
800   "^V       ����ANSI��m   ^G             ��ܥ��D�U�e��",
801   "\01��в��ʫ��O",
802   "��       ���Ჾ�ʤ@��   ^A,Home        ���즹��}�Y",
803   "��       ���e���ʤ@��   ^E,End         ���즹�浲��",
804   "��,^P    ���W���ʤ@��   (ESC-,)        �����ɮ׶}�Y",
805   "��,^N    ���U���ʤ@��   (ESC-.),^T     �����ɮ׵���",
806   "^B,PgUp  ���W���ʤ@��   ^F,PgDn        ���U���ʤ@��",
807   "\01�R�����J���O",
808   "^O,Ins   ���ܼҦ��� ���J/�л\\",
809   "^H,BS    �R���e�@�Ӧr��",
810   "(ESC-l)  �аO�϶�",
811   "^D,Del   �R���ثe���r��         ANSI�x�¬�����ŵ��Q��",
812   "^K       �R����Ф���ܦ��     �e���x3031323334353637",
813   "^Y       �R���ثe�o��           �I���x4041424344454647",
814   "\01�S����O",
815   "^U       ��J ESC �X(�H * ���)  ^C    �٭�/�]�w ANSI ��m",
816   "��ԲӪ�����: ve.hlp",
817 NULL};
818 
819 void
show_help(helptext)820 show_help(helptext)
821   char *helptext[];
822 {
823   char *str;
824   int i;
825   char resolvedname[MAXPATHLEN], *rp;
826 
827   clear();
828   for (i = 0; (str = helptext[i]); i++)
829   {
830     if (*str == '\0')
831       prints("�i %s �j\n", str + 1);
832     else if (*str == '\01')
833       prints("\n�i %s �j\n", str + 1);
834     else
835       prints("        %s\n", str);
836   }
837   move(0, 0);
838   prints((rp = realpath(FPath, resolvedname)) ? resolvedname : FPath);
839 
840   pressanykey();
841 }
842 
843 /*
844 woju
845 lino == 0 for prompt
846 */
847 
goto_line(int lino)848 goto_line(int lino)
849 {
850    char buf[10];
851 
852    if (lino > 0 || getdata(b_lines - 1, 0, "���ܲĴX��:", buf, 10, DOECHO)
853        && sscanf(buf, "%d", &lino) && lino > 0) {
854       textline* p;
855 
856       prevln = currln;
857       prevpnt = currpnt;
858       p = firstline;
859       currln = lino - 1;
860 
861       while (--lino && p->next)
862          p = p->next;
863 
864       if (p)
865          currline = p;
866       else {
867          currln = totaln;
868          currline = lastline;
869       }
870       currpnt = 0;
871       if (currln < 11) {
872          top_of_win = firstline;
873          curr_window_line = currln;
874       }
875       else {
876          int i;
877          curr_window_line = 11;
878 
879          for (i = curr_window_line; i; i--)
880             p = p->prev;
881             top_of_win = p;
882       }
883    }
884    redraw_everything = YEA;
885 }
886 
887 
strcasestr(const char * big,const char * little)888 char *strcasestr(const char* big, const char* little)
889 {
890    char* ans = (char*)big;
891    int len = strlen(little);
892    char* endptr = (char*)big + strlen(big) - len;
893 
894    while (ans <= endptr)
895       if (!strncasecmp(ans, little, len))
896          return ans;
897       else
898          ans++;
899    return 0;
900 }
901 
902 
903 /*
904 woju
905 mode:
906     0: prompt
907     1: forward
908     -1: backward
909 */
search_str(int mode)910 search_str(int mode)
911 {
912    static char str[80];
913    char buf[100];
914    typedef char* (*FPTR)();
915    static FPTR fptr;
916    char ans[4] = "n";
917 
918    if (!mode) {
919       sprintf(buf, "�M��r��[%s]", str);
920       if (getdata(b_lines - 1, 0, buf, buf, 40, DOECHO))
921          strcpy(str, buf);
922       if (*str)
923          if (getdata(b_lines - 1, 0, "�Ϥ��j�p�g(Y/N/Q)? [N] ", ans, 4, LCECHO)
924              && *ans == 'y')
925             fptr = strstr;
926          else
927             fptr = strcasestr;
928    }
929 
930    if (*str && *ans != 'q') {
931       textline* p;
932       char* pos  = 0;
933       int lino;
934 
935       if (mode >= 0) {
936          for (lino = currln, p = currline; p; p = p->next, lino++) {
937             if (*str == KEY_ESC) {
938                if (!strncmp(str + 1, p->data, strlen(str + 1))
939                    && (lino != currln || currpnt)) {
940                   pos = p->data;
941                   break;
942                }
943             }
944             else if ((pos =
945                       fptr(p->data + (lino == currln ? currpnt + 1 : 0), str))
946                 && (lino != currln || pos - p->data != currpnt))
947                break;
948          }
949       }
950       else {
951          for (lino = currln, p = currline; p; p = p->prev, lino--) {
952             if (*str == KEY_ESC) {
953                if (!strncmp(str + 1, p->data, strlen(str + 1))
954                    && (lino != currln || currpnt)) {
955                   pos = p->data;
956                   break;
957                }
958             }
959             if ((pos = fptr(p->data, str))
960                 && (lino != currln || pos - p->data != currpnt))
961                break;
962             else
963                pos = 0;
964          }
965       }
966       if (pos) {
967          prevln = currln;
968          prevpnt = currpnt;
969          currline = p;
970          currln = lino;
971          currpnt = pos - p->data;
972          if (lino < 11) {
973             top_of_win = firstline;
974             curr_window_line = currln;
975          }
976          else {
977             int i;
978             curr_window_line = 11;
979 
980             for (i = curr_window_line; i; i--)
981                p = p->prev;
982             top_of_win = p;
983          }
984          redraw_everything = YEA;
985       }
986    }
987    if (!mode)
988       redraw_everything = YEA;
989 }
990 
match_paren()991 void match_paren()
992 {
993    static char parens[] = "()[]{}<>";
994    int type, mode;
995    int parenum = 0;
996    char *ptype;
997    textline* p;
998    int lino;
999    int c, i;
1000 
1001    if (!(ptype = strchr(parens, currline->data[currpnt])))
1002       return;
1003 
1004    type = (ptype - parens) / 2;
1005    parenum += ((ptype - parens) % 2) ? -1 : 1;
1006 
1007 
1008    if (parenum > 0) {
1009      for (lino = currln, p = currline; p; p = p->next, lino++) {
1010          lino = lino;
1011          for (i = (lino == currln) ? currpnt + 1 : 0; i < strlen(p->data); i++)
1012             if (p->data[i] == '/' && p->data[++i] == '*') {
1013                ++i;
1014                while (1) {
1015                   while(i < strlen(p->data) - 1
1016                       && !(p->data[i] == '*' && p->data[i + 1] == '/'))
1017                      i++;
1018                   if (i >= strlen(p->data) - 1 && p->next) {
1019                      p = p->next;
1020                      ++lino;
1021                      i = 0;
1022                   }
1023                   else
1024                      break;
1025                }
1026             }
1027             else if ((c = p->data[i]) == '\'' || c == '"') {
1028                while (1) {
1029                   while (i < (int)(strlen(p->data) - 1))
1030                      if (p->data[++i] == '\\' && i < strlen(p->data) - 2)
1031                         ++i;
1032                      else if (p->data[i] == c)
1033                         goto end_quote;
1034                   if (i >= strlen(p->data) - 1 && p->next) {
1035                      p = p->next;
1036                      ++lino;
1037                      i = -1;
1038                   }
1039                   else
1040                      break;
1041                }
1042 end_quote:
1043                ;
1044             }
1045             else if ((ptype = strchr(parens, p->data[i]))
1046                      && (ptype - parens) / 2 == type)
1047                if (!(parenum += ((ptype - parens) % 2) ? -1 : 1))
1048                   goto p_outscan;
1049      }
1050    }
1051    else {
1052       for (lino = currln, p = currline; p; p = p->prev, lino--)
1053          for (i = (lino == currln) ? currpnt - 1 : strlen(p->data) - 1;
1054               i >= 0; i--)
1055             if (p->data[i] == '/' && p->data[--i] == '*' && i >= 0) {
1056                --i;
1057                while (1) {
1058                   while(i > 0
1059                       && !(p->data[i] == '*' && p->data[i - 1] == '/'))
1060                      i--;
1061                   if (i <= 0 && p->prev) {
1062                      p = p->prev;
1063                      --lino;
1064                      i = strlen(p->data) - 1;
1065                   }
1066                   else
1067                      break;
1068                }
1069             }
1070             else if ((c = p->data[i]) == '\'' || c == '"') {
1071                while (1) {
1072                   while (i > 0)
1073                      if (i > 1 && p->data[i - 2] == '\\')
1074                         i -= 2;
1075                      else if ((p->data[--i]) == c)
1076                         goto begin_quote;
1077                   if (i <= 0 && p->prev) {
1078                      p = p->prev;
1079                      --lino;
1080                      i = strlen(p->data);
1081                   }
1082                   else
1083                      break;
1084                }
1085 begin_quote:
1086                ;
1087             }
1088             else if ((ptype = strchr(parens, p->data[i]))
1089                      && (ptype - parens) / 2 == type)
1090                if (!(parenum += ((ptype - parens) % 2) ? -1 : 1))
1091                   goto p_outscan;
1092    }
1093 
1094 p_outscan:
1095 
1096    if (!parenum) {
1097       int top = currln - curr_window_line;
1098       int bottom = currln - curr_window_line + b_lines - 1;
1099 
1100       currpnt = i;
1101       currline = p;
1102       curr_window_line += lino - currln;
1103       currln = lino;
1104 
1105       if (lino < top || lino > bottom) {
1106          if (lino < 11) {
1107             top_of_win = firstline;
1108             curr_window_line = currln;
1109          }
1110          else {
1111             int i;
1112             curr_window_line = 11;
1113 
1114             for (i = curr_window_line; i; i--)
1115                p = p->prev;
1116             top_of_win = p;
1117          }
1118          redraw_everything = YEA;
1119       }
1120    }
1121 }
1122 
1123 
block_del(int hide)1124 block_del(int hide)
1125 {
1126    if (blockln < 0) {
1127       blockln = currln;
1128       blockpnt = currpnt;
1129       blockline = currline;
1130    }
1131    else {
1132       char fp_tmpbuf[80];
1133       FILE* fp;
1134       textline *begin, *end, *p;
1135       int lines;
1136       char tmpfname[10] = "buf.0";
1137       char ans[6] = "w+n";
1138 
1139       move(b_lines - 1, 0);
1140       clrtoeol();
1141       if (hide == 1)
1142          tmpfname[4] = 'q';
1143       else if (!hide && !getdata(b_lines - 1, 0, "��϶����ܼȦs�� (0:Cut, 5:Copy, 6-9, q: Cancel)[0] ",  tmpfname + 4, 4, LCECHO))
1144          tmpfname[4] = '0';
1145       if (tmpfname[4] < '0' || tmpfname[4] > '9')
1146          tmpfname[4] = 'q';
1147       if ('1' <= tmpfname[4] && tmpfname[4] <= '9') {
1148          setuserfile(fp_tmpbuf, tmpfname);
1149          if (tmpfname[4] != '5' && dashf(fp_tmpbuf)) {
1150             more(fp_tmpbuf, NA);
1151             getdata(b_lines - 1, 0, "�Ȧs�ɤw����� (A)���[ (W)�мg (Q)�����H[W] ", ans, 4, LCECHO);
1152             if (*ans == 'q')
1153                tmpfname[4] = 'q';
1154             else if (*ans != 'a')
1155                *ans = 'w';
1156           }
1157           if (tmpfname[4] != '5') {
1158              getdata(b_lines - 1, 0, "�R���϶�(Y/N)?[N] ", ans + 2, 4, LCECHO);
1159              if (ans[2] != 'y')
1160                 ans[2] = 'n';
1161           }
1162       }
1163       else if (hide != 3)
1164          ans[2] = 'y';
1165 
1166       tmpfname[5] = ans[1] = ans[3] = 0;
1167       if (tmpfname[4] != 'q') {
1168          if (currln >= blockln) {
1169             begin = blockline;
1170             end = currline;
1171          }
1172          else {
1173             begin = currline;
1174             end = blockline;
1175          }
1176 
1177          if (ans[2] == 'y' && !(begin == end && currpnt != blockpnt)) {
1178             if (currln > blockln) {
1179                curr_window_line -= (currln - blockln);
1180                currln = blockln;
1181                if (curr_window_line < 0) {
1182                   curr_window_line = 0;
1183                   if (end->next)
1184                      top_of_win = end->next;
1185                   else
1186                      top_of_win = begin->prev;
1187                }
1188             }
1189             if (!curr_window_line)
1190                if (end->next)
1191                   top_of_win = end->next;
1192                else
1193                   top_of_win = begin->prev;
1194 
1195             if (begin->prev)
1196                begin->prev->next = end->next;
1197             else if (end->next)
1198                top_of_win = firstline = end->next;
1199             else {
1200                currline = top_of_win = firstline = lastline = alloc_line();
1201 
1202                currln = curr_window_line = edit_margin = 0;
1203             }
1204 
1205             if (end->next)
1206                (currline = end->next)->prev = begin->prev;
1207             else if (begin->prev) {
1208                currline = (lastline = begin->prev);
1209                currln--;
1210                if (curr_window_line > 0)
1211                   curr_window_line--;
1212             }
1213          }
1214 
1215          setuserfile(fp_tmpbuf, tmpfname);
1216          if (fp = fopen(fp_tmpbuf, ans)) {
1217             if (begin == end && currpnt != blockpnt) {
1218                char buf[WRAPMARGIN + 2];
1219 
1220                if (currpnt > blockpnt) {
1221                   strcpy(buf, begin->data + blockpnt);
1222                   buf[currpnt - blockpnt] = 0;
1223                }
1224                else {
1225                   strcpy(buf, begin->data + currpnt);
1226                   buf[blockpnt - currpnt] = 0;
1227                }
1228                fputs(buf, fp);
1229             }
1230             else {
1231                for (p = begin; p != end; p = p->next)
1232                   fprintf(fp, "%s\n", p->data);
1233                fprintf(fp, "%s\n", end->data);
1234             }
1235             fclose(fp);
1236          }
1237 
1238          if (ans[2] == 'y') {
1239             modified = -2;
1240             if (begin == end && currpnt != blockpnt) {
1241                int min, max;
1242 
1243                if (currpnt > blockpnt) {
1244                   min = blockpnt;
1245                   max = currpnt;
1246                }
1247                else {
1248                   min = currpnt;
1249                   max = blockpnt;
1250                }
1251                strcpy(begin->data + min, begin->data + max);
1252                begin->len -= max - min;
1253                currpnt = min;
1254             }
1255             else {
1256                for (p = begin; p != end; totaln--)
1257                   free((p = p->next)->prev);
1258                free(end);
1259                totaln--;
1260                currpnt = 0;
1261             }
1262          }
1263       }
1264       blockln = -1;
1265       redraw_everything = YEA;
1266    }
1267 }
1268 
block_shift_left()1269 block_shift_left()
1270 {
1271    textline *begin, *end, *p;
1272 
1273    if (currln >= blockln) {
1274       begin = blockline;
1275       end = currline;
1276    }
1277    else {
1278       begin = currline;
1279       end = blockline;
1280    }
1281    p = begin;
1282    while (1) {
1283       if (p->len) {
1284          strcpy(p->data, p->data + 1);
1285          --p->len;
1286       }
1287       if (p == end)
1288          break;
1289       else
1290          p = p->next;
1291    }
1292    if (currpnt > currline->len)
1293       currpnt = currline->len;
1294    modified = -2;
1295    redraw_everything = YEA;
1296 }
1297 
block_shift_right()1298 block_shift_right()
1299 {
1300    textline *begin, *end, *p;
1301 
1302    if (currln >= blockln) {
1303       begin = blockline;
1304       end = currline;
1305    }
1306    else {
1307       begin = currline;
1308       end = blockline;
1309    }
1310    p = begin;
1311    while (1) {
1312       if (p->len < WRAPMARGIN) {
1313          int i = p->len + 1;
1314 
1315          while (i--)
1316             p->data[i + 1] = p->data[i];
1317          p->data[0] = insert_character ? ' ' : insert_c;
1318          ++p->len;
1319       }
1320       if (p == end)
1321          break;
1322       else
1323          p = p->next;
1324    }
1325    if (currpnt > currline->len)
1326       currpnt = currline->len;
1327    modified = -2;
1328    redraw_everything = YEA;
1329 }
1330 
1331 
transform_to_color(char * line)1332 transform_to_color(char* line)
1333 {
1334    while (line[0] && line[1])
1335       if (line[0] == '*' && line[1] == '[') {
1336          modified = -2;
1337          line[0] = KEY_ESC;
1338          line += 2;
1339       }
1340       else
1341          ++line;
1342 }
1343 
1344 
block_color()1345 block_color()
1346 {
1347    textline *begin, *end, *p;
1348 
1349    if (currln >= blockln) {
1350       begin = blockline;
1351       end = currline;
1352    }
1353    else {
1354       begin = currline;
1355       end = blockline;
1356    }
1357    p = begin;
1358    while (1) {
1359       transform_to_color(p->data);
1360       if (p == end)
1361          break;
1362       else
1363          p = p->next;
1364    }
1365    block_del(1);
1366 }
1367 
1368 
1369 /* ----------------------------------------------------- */
1370 /* �s��B�z�G�D�{���B��L�B�z                            */
1371 /* ----------------------------------------------------- */
1372 
1373 extern int my_write();
1374 
vedit(fpath,saveheader)1375 int vedit(fpath, saveheader)
1376   char *fpath;
1377   int saveheader;
1378 {
1379   int ch, foo;
1380   int lastindent = -1;
1381   int last_margin;
1382   int line_dirty = 0;
1383   char* pstr;
1384   extern char* phone_char();
1385 
1386   FPath = fpath;
1387   stat(FPath, &st0);
1388 
1389   insert_character = redraw_everything = 1;
1390 
1391   currpnt = totaln = my_ansimode = 0;
1392   if (currline == NULL)
1393      currline = top_of_win = firstline = lastline = alloc_line();
1394 
1395   if (*fpath)
1396   {
1397     read_file(fpath);
1398   }
1399 
1400   currline = firstline;
1401   currpnt = currln = curr_window_line = edit_margin = last_margin = 0;
1402   modified = -1;
1403 
1404   while (1)
1405   {
1406     if (redraw_everything || blockln >=0)
1407     {
1408       display_buffer();
1409       redraw_everything = NA;
1410     }
1411     if (my_ansimode)
1412        ch = n2ansi(currpnt, currline);
1413     else
1414        ch = currpnt - edit_margin;
1415     move(curr_window_line, ch);
1416     if (!line_dirty && strcmp(line, currline->data))
1417        strcpy(line, currline->data);
1418     ch = igetkey();
1419 
1420     if (raw_mode)
1421        switch (ch) {
1422        case Ctrl('S'):
1423        case Ctrl('Q'):
1424        case Ctrl('T'):
1425           continue;
1426           break;
1427        }
1428 
1429 /*
1430     if (ch == Ctrl('J') && !raw_mode)
1431        goto_line(0);
1432 */
1433     else if (phone_mode && (pstr = phone_char(ch)) || ch < 0x100 && isprint2(ch))
1434     {
1435       if (phone_mode && pstr)
1436          insert_string(pstr);
1437       else
1438          insert_char(ch);
1439       lastindent = -1;
1440       if (modified > -2)
1441          modified = currln;
1442       line_dirty = 1;
1443     }
1444     else
1445     {
1446       if (ch == Ctrl('P') || ch == KEY_UP || ch == KEY_DOWN || ch == Ctrl('N'))
1447       {
1448         if (lastindent == -1)
1449           lastindent = currpnt;
1450       }
1451       else
1452         lastindent = -1;
1453 
1454 /*
1455 woju
1456 */
1457       if (ch == KEY_ESC)
1458          switch (KEY_ESC_arg) {
1459          case ',':
1460             ch = Ctrl(']');
1461             break;
1462          case '.':
1463             ch = Ctrl('T');
1464             break;
1465          case 'v':
1466             ch = KEY_PGUP;
1467             break;
1468          case 'a':
1469          case 'A':
1470             ch = Ctrl('V');
1471             break;
1472          case 'X':
1473             ch = Ctrl('X');
1474             break;
1475          case 'q':
1476             ch = Ctrl('Q');
1477             break;
1478          case 'o':
1479             ch = Ctrl('O');
1480             break;
1481          case '-':
1482             ch = Ctrl('_');
1483             break;
1484          case 's':
1485             ch = Ctrl('S');
1486             break;
1487          }
1488 
1489       switch (ch)
1490       {
1491       case Ctrl('X'):           /* Save and exit */
1492         foo = write_file(fpath, saveheader);
1493         if (foo != KEEP_EDITING)
1494         {
1495           return foo;
1496         }
1497         line_dirty = 1;
1498         redraw_everything = YEA;
1499         break;
1500 
1501       case Ctrl('W'):
1502          if (blockln >= 0)
1503             block_del(2);
1504          line_dirty = 1;
1505          break;
1506 
1507       case Ctrl('Q'):           /* Quit without saving */
1508         ch = ask("���������x�s (Y/N)? [N]: ");
1509         if (ch == 'y' || ch == 'Y') {
1510            clear();
1511            return 0;
1512         }
1513         line_dirty = 1;
1514         redraw_everything = YEA;
1515         break;
1516 
1517       case Ctrl('C'):
1518         ch = insert_character;
1519         insert_character = redraw_everything = YEA;
1520 
1521         if (!my_ansimode)
1522         {
1523           insert_string(reset_color);
1524          if (modified > -2)
1525              modified = currln;
1526         }
1527         else
1528         {
1529           char ans[4];
1530           move(b_lines - 2, 55);
1531           outs("\033[1;33;40mB\033[41mR\033[42mG\033[43mY\033[44mL\033[45mP\033[46mC\033[47mW\033[m");
1532           if (getdata(b_lines - 1, 0, "�п�J  �G��/�e��/�I��[���`�զr�©�][0wb]�G", ans, 4, LCECHO))
1533           {
1534             char t[] = "BRGYLPCW";
1535             char color[15];
1536             char *tmp, *apos = ans;
1537             int fg, bg;
1538 
1539             if (!strchr(ans, 'q')) {
1540                strcpy(color, "\033[");
1541                if (isdigit(*apos))
1542                {
1543                  sprintf(color, "%s%c", color, *(apos++));
1544                  if (*apos)
1545                    sprintf(color, "%s;", color);
1546                }
1547                if (*apos)
1548                {
1549                  if (tmp = strchr(t, toupper(*(apos++))))
1550                    fg = tmp - t + 30;
1551                  else
1552                    fg = 37;
1553                  sprintf(color, "%s%d", color, fg);
1554                }
1555                if (*apos)
1556                {
1557                  if (tmp = strchr(t, toupper(*(apos++))))
1558                    bg = tmp - t + 40;
1559                  else
1560                    bg = 40;
1561                  sprintf(color, "%s;%d", color, bg);
1562                }
1563                sprintf(color, "%sm", color);
1564                insert_string(color);
1565                if (modified > -2)
1566                   modified = currln;
1567             }
1568           }
1569           else {
1570             insert_string(reset_color);
1571             if (modified > -2)
1572                modified = currln;
1573           }
1574         }
1575         insert_character = ch;
1576         line_dirty = 1;
1577         break;
1578 
1579       case KEY_ESC:
1580          line_dirty = 0;
1581          switch (KEY_ESC_arg) {
1582          case 'w':
1583             ch = ask("�T�w�s�� (Y/N)? [Y]: ");
1584             if (!(ch == 'n' || ch == 'N'))
1585                write_file(fpath, YEA);
1586             line_dirty = 1;
1587             redraw_everything = YEA;
1588             break;
1589          case 'x':
1590             if (prevln >= 0) {
1591                int prevln0 = prevln;
1592                int prevpnt0 = prevpnt;
1593                prevln = currln;
1594                prevpnt = currpnt;
1595                goto_line(prevln0 + 1);
1596                currpnt = prevpnt0;
1597             }
1598             break;
1599          case 'n':
1600             search_str(1);
1601             edit_margin = currpnt < SCR_WIDTH - 1 ? 0 : currpnt / 72 * 72;
1602             if (edit_margin != last_margin)
1603                redraw_everything = NA;
1604             break;
1605          case 'p':
1606             search_str(-1);
1607             edit_margin = currpnt < SCR_WIDTH - 1 ? 0 : currpnt / 72 * 72;
1608             if (edit_margin != last_margin)
1609                redraw_everything = NA;
1610             break;
1611          case 'J':
1612          case 'L':
1613          case 'g':
1614             goto_line(0);
1615             break;
1616          case ']':
1617             match_paren();
1618             break;
1619          case '0':
1620          case '5':
1621          case '6':
1622          case '7':
1623          case '8':
1624          case '9':
1625          {
1626             int currln0 = currln;
1627             int currpnt0 = currpnt;
1628 
1629             read_tmpbuf(KEY_ESC_arg - '0');
1630             redraw_everything = (currln0 == currln && currpnt0 != currpnt) ? NA : YEA;
1631          }
1632             break;
1633          case 'l':                       /* block delete */
1634          case ' ':
1635             block_del(0);
1636             line_dirty = 1;
1637             break;
1638          case 'u':
1639             if (blockln >= 0)
1640                block_del(1);
1641             line_dirty = 1;
1642             break;
1643          case 'c':
1644             if (blockln >= 0)
1645                block_del(3);
1646             line_dirty = 1;
1647             break;
1648          case 'y':
1649             undelete_line();
1650             break;
1651          case 'P':
1652             phone_mode ^= 1;
1653             line_dirty = 1;
1654             break;
1655          case 'R':
1656             raw_mode ^= 1;
1657             line_dirty = 1;
1658             break;
1659          case 'I':
1660             indent_mode ^= 1;
1661             line_dirty = 1;
1662             break;
1663          case 'j':
1664             if (blockln >= 0)
1665                block_shift_left();
1666             else if (currline->len) {
1667                int currpnt0 = currpnt;
1668                if (modified > -2)
1669                   modified = currln;
1670                currpnt = 0;
1671                delete_char();
1672                currpnt = (currpnt0 <= currline->len) ? currpnt0 : currpnt0 - 1;
1673                if (my_ansimode)
1674                    currpnt = ansi2n(n2ansi(currpnt, currline),currline);
1675             }
1676             line_dirty = 1;
1677             break;
1678          case 'k':
1679             if (blockln >= 0)
1680                block_shift_right();
1681             else {
1682                int currpnt0 = currpnt;
1683               if (modified > -2)
1684                   modified = currln;
1685                currpnt = 0;
1686                insert_char(' ');
1687                currpnt = currpnt0;
1688             }
1689             line_dirty = 1;
1690             break;
1691          case 'f':
1692             while (currpnt < currline->len && isalnum(currline->data[++currpnt]))
1693                ;
1694             while (currpnt < currline->len && isspace(currline->data[++currpnt]))
1695                ;
1696             line_dirty = 1;
1697             break;
1698          case 'b':
1699             while (currpnt && isalnum(currline->data[--currpnt]))
1700                ;
1701             while (currpnt && isspace(currline->data[--currpnt]))
1702                ;
1703             line_dirty = 1;
1704             break;
1705          case 'd':
1706             if (modified > -2)
1707                modified = currln;
1708             while (currpnt < currline->len) {
1709                delete_char();
1710                if (!isalnum(currline->data[currpnt]))
1711                   break;
1712             }
1713             while (currpnt < currline->len && isspace(currline->data[currpnt]))
1714                delete_char();
1715             line_dirty = 1;
1716             break;
1717          default:
1718             line_dirty = 1;
1719          }
1720          break;
1721       case Ctrl('S'):
1722          search_str(0);
1723          edit_margin = currpnt < SCR_WIDTH - 1 ? 0 : currpnt / 72 * 72;
1724          if (edit_margin != last_margin)
1725             redraw_everything = NA;
1726          break;
1727       case Ctrl('_'):
1728          if (strcmp(line, currline->data)) {
1729             char buf[WRAPMARGIN];
1730 
1731             strcpy(buf, currline->data);
1732             strcpy(currline->data, line);
1733             strcpy(line, buf);
1734             currline->len = strlen(currline->data);
1735             currpnt = 0;
1736             line_dirty = 1;
1737             if (modified == currln)
1738                modified = -1;
1739          }
1740          break;
1741       case Ctrl('U'):
1742         if (modified > -2)
1743            modified = currln;
1744         insert_char('');
1745         line_dirty = 1;
1746         break;
1747 
1748       case Ctrl('V'):                   /* Toggle ANSI color */
1749          my_ansimode ^= 1;
1750          if (my_ansimode && blockln >= 0)
1751             block_color();
1752          clear();
1753          redraw_everything = YEA;
1754          line_dirty = 1;
1755          break;
1756 
1757       case Ctrl('I'):
1758         if (modified > -2)
1759            modified = currln;
1760         do
1761         {
1762           insert_char(' ');
1763         }
1764         while (currpnt & 0x7);
1765         line_dirty = 1;
1766         break;
1767 
1768       case '\r':
1769       case '\n':
1770         split(currline, currpnt);
1771         line_dirty = 0;
1772         break;
1773       case Ctrl('Z'):
1774         clear();
1775         refresh();
1776         reset_tty();
1777         system(getenv("SHELL"));
1778         restore_tty();
1779         clear();
1780         redraw_everything = YEA;
1781         line_dirty = 1;
1782         break;
1783       case Ctrl('L'):
1784         clear();
1785         redraw_everything = YEA;
1786         line_dirty = 1;
1787         break;
1788       case Ctrl('G'):
1789         show_help(vedithelp);
1790         redraw_everything = YEA;
1791         line_dirty = 1;
1792         break;
1793 
1794       case KEY_LEFT:
1795         if (currpnt) {
1796           if (my_ansimode)
1797              currpnt = n2ansi(currpnt, currline);
1798           currpnt--;
1799           if (my_ansimode)
1800              currpnt = ansi2n(currpnt, currline);
1801           line_dirty = 1;
1802         }
1803         else if (currline->prev)
1804         {
1805           curr_window_line--;
1806           currln--;
1807           currline = currline->prev;
1808           currpnt = currline->len;
1809           line_dirty = 0;
1810         }
1811         break;
1812 
1813       case KEY_RIGHT:
1814         if (currline->len != currpnt) {
1815           if (my_ansimode)
1816              currpnt = n2ansi(currpnt, currline);
1817           currpnt++;
1818           if (my_ansimode)
1819              currpnt = ansi2n(currpnt, currline);
1820           line_dirty = 1;
1821         }
1822         else if (currline->next)
1823         {
1824           currpnt = 0;
1825           curr_window_line++;
1826           currln++;
1827           currline = currline->next;
1828           line_dirty = 0;
1829         }
1830         break;
1831 
1832       case KEY_UP:
1833       case Ctrl('P'):
1834         if (currline->prev)
1835         {
1836           if (my_ansimode)
1837              ch = n2ansi(currpnt,currline);
1838           curr_window_line--;
1839           currln--;
1840           currline = currline->prev;
1841           if (my_ansimode)
1842              currpnt = ansi2n(ch , currline);
1843           else
1844              currpnt = (currline->len > lastindent) ? lastindent : currline->len;
1845           line_dirty = 0;
1846         }
1847         break;
1848 
1849       case KEY_DOWN:
1850       case Ctrl('N'):
1851         if (currline->next)
1852         {
1853           if (my_ansimode)
1854              ch = n2ansi(currpnt,currline);
1855           currline = currline->next;
1856           curr_window_line++;
1857           currln++;
1858           if (my_ansimode)
1859              currpnt = ansi2n(ch , currline);
1860           else
1861              currpnt = (currline->len > lastindent) ? lastindent : currline->len;
1862           line_dirty = 0;
1863         }
1864         break;
1865       case Ctrl('B'):
1866       case KEY_PGUP:
1867         redraw_everything = currln;
1868         top_of_win = back_line(top_of_win, 22);
1869         currln = redraw_everything;
1870         currline = back_line(currline, 22);
1871         curr_window_line = getlineno();
1872         if (currpnt > currline->len)
1873           currpnt = currline->len;
1874         redraw_everything = YEA;
1875         line_dirty = 0;
1876         break;
1877 
1878       case KEY_PGDN:
1879       case Ctrl('F'):
1880         redraw_everything = currln;
1881         top_of_win = forward_line(top_of_win, 22);
1882         currln = redraw_everything;
1883         currline = forward_line(currline, 22);
1884         curr_window_line = getlineno();
1885         if (currpnt > currline->len)
1886           currpnt = currline->len;
1887         redraw_everything = YEA;
1888         line_dirty = 0;
1889         break;
1890 
1891       case KEY_END:
1892       case Ctrl('E'):
1893         trim(currline->data);
1894         currpnt = currline->len = strlen(currline->data);
1895         line_dirty = 1;
1896         break;
1897 
1898       case Ctrl(']'):   /* start of file */
1899         prevln = currln;
1900         prevpnt = currpnt;
1901         currline = top_of_win = firstline;
1902         currpnt = currln = curr_window_line = 0;
1903         redraw_everything = YEA;
1904         line_dirty = 0;
1905         break;
1906 
1907       case Ctrl('T'):           /* tail of file */
1908         prevln = currln;
1909         prevpnt = currpnt;
1910         top_of_win = back_line(lastline, 23);
1911         currline = lastline;
1912         curr_window_line = getlineno();
1913         currln = totaln;
1914         redraw_everything = YEA;
1915         currpnt = 0;
1916         line_dirty = 0;
1917         break;
1918 
1919       case KEY_HOME:
1920       case Ctrl('A'):
1921         currpnt = 0;
1922         line_dirty = 1;
1923         break;
1924 
1925       case KEY_INS:             /* Toggle insert/overwrite */
1926       case Ctrl('O'):
1927         if (blockln >= 0 && insert_character) {
1928            char ans[4];
1929 
1930            getdata(b_lines - 1, 0, "�϶��L�եk�����J�r��(�w�]���ťզr��)", ans, 4);
1931            insert_c = (*ans) ? *ans : ' ';
1932         }
1933         insert_character ^= 1;
1934         line_dirty = 1;
1935         break;
1936 
1937       case Ctrl('H'):
1938       case '\177':              /* backspace */
1939         line_dirty = 1;
1940         if (my_ansimode) {
1941            my_ansimode = 0;
1942            clear();
1943            redraw_everything = YEA;
1944         }
1945         else {
1946            if (currpnt == 0) {
1947               textline *p;
1948 
1949               if (!currline->prev)
1950               {
1951                 break;
1952               }
1953               line_dirty = 0;
1954               curr_window_line--;
1955               currln--;
1956               currline = currline->prev;
1957               currpnt = currline->len;
1958               redraw_everything = YEA;
1959               if (*killsp(currline->next->data) == '\0')
1960               {
1961                 delete_line(currline->next);
1962                 break;
1963               }
1964               p = currline;
1965               while (!join(p))
1966               {
1967                 p = p->next;
1968                 if (p == NULL)
1969                 {
1970                   indigestion(2);
1971                   abort_bbs();
1972                 }
1973               }
1974               break;
1975            }
1976            if (modified > -2)
1977               modified = currln;
1978            currpnt--;
1979            delete_char();
1980         }
1981         break;
1982 
1983       case Ctrl('D'):
1984       case KEY_DEL:             /* delete current character */
1985         line_dirty = 1;
1986         if (currline->len == currpnt)
1987         {
1988           textline *p = currline;
1989 
1990           while (!join(p))
1991           {
1992             p = p->next;
1993             if (p == NULL)
1994             {
1995               indigestion(2);
1996               abort_bbs();
1997             }
1998           }
1999           line_dirty = 0;
2000           redraw_everything = YEA;
2001         }
2002         else {
2003            delete_char();
2004            if (modified > -2)
2005               modified = currln;
2006            if (my_ansimode)
2007               currpnt = ansi2n(n2ansi(currpnt, currline),currline);
2008         }
2009         break;
2010 
2011       case Ctrl('Y'):           /* delete current line */
2012         modified = -2;
2013         currline->len = currpnt = 0;
2014 
2015       case Ctrl('K'):           /* delete to end of line */
2016         if (currline->len == 0)
2017         {
2018           textline *p = currline->next;
2019 
2020           if (!p)
2021           {
2022             p = currline->prev;
2023             if (!p)
2024             {
2025               break;
2026             }
2027             if (curr_window_line > 0)
2028             {
2029               curr_window_line--;
2030               currln--;
2031             }
2032           }
2033           if (currline == top_of_win)
2034             top_of_win = p;
2035           delete_line(currline);
2036           currline = p;
2037           redraw_everything = YEA;
2038           modified = -2;
2039           line_dirty = 0;
2040           break;
2041         }
2042 
2043         if (currline->len == currpnt)
2044         {
2045           textline *p = currline;
2046 
2047           while (!join(p))
2048           {
2049             p = p->next;
2050             if (p == NULL)
2051             {
2052               indigestion(2);
2053               abort_bbs();
2054             }
2055           }
2056           redraw_everything = YEA;
2057           line_dirty = 0;
2058           break;
2059         }
2060         currline->len = currpnt;
2061         currline->data[currpnt] = '\0';
2062         line_dirty = 1;
2063         if (modified > -2)
2064            modified = currln;
2065         break;
2066       }
2067 
2068       if (currln < 0)
2069         currln = 0;
2070       if (curr_window_line < 0)
2071       {
2072         curr_window_line = 0;
2073         if (!top_of_win->prev)
2074         {
2075           indigestion(6);
2076         }
2077         else
2078         {
2079           top_of_win = top_of_win->prev;
2080           rscroll();
2081         }
2082       }
2083       if (curr_window_line == b_lines)
2084       {
2085         curr_window_line = t_lines - 2;
2086         if (!top_of_win->next)
2087         {
2088           indigestion(7);
2089         }
2090         else
2091         {
2092           top_of_win = top_of_win->next;
2093           move(b_lines, 0);
2094           clrtoeol();
2095           scroll();
2096         }
2097       }
2098     }
2099     edit_margin = currpnt < SCR_WIDTH - 1 ? 0 : currpnt / 72 * 72;
2100 
2101     if (!redraw_everything)
2102     {
2103       if (edit_margin != last_margin)
2104       {
2105         last_margin = edit_margin;
2106         redraw_everything = YEA;
2107       }
2108       else
2109       {
2110          move(curr_window_line, 0);
2111          clrtoeol();
2112          if (my_ansimode)
2113            outs(currline->data);
2114          else
2115             edit_outs(&currline->data[edit_margin]);
2116          edit_msg();
2117       }
2118     }
2119   }
2120 }
2121