chiark / gitweb /
*** empty log message ***
[sympathy.git] / src / vt102.c
1 /*
2  * vt102.c:
3  *
4  * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>,
5  * All rights reserved.
6  *
7  */
8
9 static char rcsid[] = "$Id$";
10
11 /*
12  * $Log$
13  * Revision 1.10  2008/02/06 17:53:28  james
14  * *** empty log message ***
15  *
16  * Revision 1.9  2008/02/06 15:53:22  james
17  * *** empty log message ***
18  *
19  * Revision 1.8  2008/02/06 11:49:47  james
20  * *** empty log message ***
21  *
22  * Revision 1.7  2008/02/06 11:30:37  james
23  * *** empty log message ***
24  *
25  * Revision 1.6  2008/02/05 01:11:46  james
26  * *** empty log message ***
27  *
28  * Revision 1.5  2008/02/04 20:23:55  james
29  * *** empty log message ***
30  *
31  * Revision 1.4  2008/02/04 05:45:55  james
32  * ::
33  *
34  * Revision 1.3  2008/02/04 02:05:06  james
35  * *** empty log message ***
36  *
37  * Revision 1.2  2008/02/04 01:32:39  james
38  * *** empty log message ***
39  *
40  * Revision 1.1  2008/02/03 23:36:41  james
41  * *** empty log message ***
42  *
43  */
44
45
46 /* Termcap he say:
47
48 vt102|dec vt102:\
49         :mi:\
50         :al=\E[L:dc=\E[P:dl=\E[M:ei=\E[4l:im=\E[4h:tc=vt100:
51
52 vt100|vt100-am|dec vt100 (w/advanced video):\
53         :am:bs:ms:xn:xo:\
54         :co#80:it#8:li#24:vt#3:\
55         :DO=\E[%dB:LE=\E[%dD:RA=\E[?7l:RI=\E[%dC:SA=\E[?7h:\
56         :UP=\E[%dA:\
57         :ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~:\
58         :ae=^O:as=^N:bl=^G:cb=\E[1K:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
59         :cm=\E[%i%d;%dH:cr=^M:cs=\E[%i%d;%dr:ct=\E[3g:do=^J:\
60         :eA=\E(B\E)0:ho=\E[H:kb=^H:kd=\EOB:ke=\E[?1l\E>:kl=\EOD:\
61         :kr=\EOC:ks=\E[?1h\E=:ku=\EOA:le=^H:mb=\E[5m:md=\E[1m:\
62         :me=\E[m\017:mr=\E[7m:nd=\E[C:rc=\E8:\
63         :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:sc=\E7:se=\E[m:\
64         :sf=^J:so=\E[7m:sr=\EM:st=\EH:ta=^I:ue=\E[m:up=\E[A:\
65         :us=\E[4m:tc=vt100+fnkeys:
66
67 vt100+fnkeys|dec vt100 numeric keypad:\
68         :k0=\EOy:k5=\EOt:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:\
69         :tc=vt100+pfkeys:
70
71 vt100+pfkeys|dec vt100 numeric keypad:\
72         :@8=\EOM:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:tc=vt100+keypad:
73
74 vt100+keypad|dec vt100 numeric keypad no fkeys:\
75         :K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:
76
77 */
78
79 /*
80 so the parser needs to be able to at least do
81 CTRL-G
82 CTRL-H
83 CTRL-I
84 CTRL-J
85 CTRL-M
86 CTRL-N
87
88 CTRL-O
89 ESC7
90 ESC8
91 ESCH
92 ESCM
93 ESC> 
94
95 ESC[%dA
96 ESC[%dB
97 ESC[%dC
98 ESC[%dD
99 ESC[H
100 ESC[%d;%dH
101 ESC[J
102 ESC[K
103 ESC[1K
104 ESC[L
105 ESC[M
106 ESC[P
107
108 ESC[3g
109 ESC[4h
110 ESC[4l
111 ESC[m 
112 ESC[1m
113 ESC[4m
114 ESC[5m
115 ESC[7m
116 ESC[%d;%dr
117
118
119 ESC[?3l 
120 ESC[?4l 
121 ESC[?5l
122 ESC[?7h
123 ESC[?7h
124 ESC[?7l
125 ESC[?8h
126
127 ESC(B
128 ESC)0
129
130
131 TODO:
132
133 ESC(B
134 ESC)0
135
136 CTRL-O
137
138 ESC7
139 ESC8
140 ESCH
141 ESCM
142 ESC> 
143
144 */
145
146 #include "project.h"
147
148
149
150 static inline int
151 csi_ender (int c)
152 {
153   if ((c >= 'a') && (c <= 'z'))
154     return 1;
155   if ((c >= 'A') && (c <= 'Z'))
156     return 1;
157   return 0;
158 }
159
160 static inline int
161 csi_starter (int c)
162 {
163   switch (c)
164     {
165     case '[':
166     case '(':
167     case ')':
168       return 1;
169     }
170   return 0;
171 }
172
173 static inline int
174 in_margins (VT102 * v, CRT_Pos p)
175 {
176   if (v->pos.x < v->top_margin.x)
177     return 0;
178   if (v->pos.y < v->top_margin.y)
179     return 0;
180
181   if (v->pos.x > v->bottom_margin.x)
182     return 0;
183   if (v->pos.y > v->bottom_margin.y)
184     return 0;
185
186   return 1;
187 }
188
189 void
190 vt102_log_line (VT102 * v, int line)
191 {
192   static FILE *log;
193   CRT_Pos e = { VT102_COLS - 1, line };
194   CRT_Pos p = { 0, line };
195
196   if (!log) 
197         log=fopen("log","a+");
198
199    if (!log) return;
200   
201
202   for (; e.x > 0; --e.x)
203     {
204       if (v->crt.screen[CRT_ADDR_POS (&e)].chr != ' ')
205         break;
206     }
207
208   for (; p.x <= e.x; ++p.x)
209     {
210       int c = v->crt.screen[CRT_ADDR_POS (&p)].chr;
211       if (c < 32)
212         c = ' ';
213       if (c > 126)
214         c = ' ';
215       fputc (c, log);
216     }
217   fputc ('\n', log);
218 }
219
220 void
221 vt102_clip_cursor (VT102 * v, CRT_Pos tl, CRT_Pos br)
222 {
223   if (v->pos.x < tl.x)
224     v->pos.x = tl.x;
225   if (v->pos.y < tl.y)
226     v->pos.y = tl.y;
227
228   if (v->pos.x > br.x)
229     v->pos.x = br.x;
230   if (v->pos.y > br.y)
231     v->pos.y = br.y;
232 }
233
234
235 void
236 vt102_cursor_normalize (VT102 * v)
237 {
238   CRT_Pos *top, *bottom;
239
240   if (v->private_modes[VT102_PRIVATE_MODE_ORIGIN_MODE])
241     {
242       vt102_clip_cursor (v, v->top_margin, v->bottom_margin);
243     }
244   else
245     {
246       vt102_clip_cursor (v, v->screen_start, v->screen_end);
247     }
248 }
249
250
251 void
252 vt102_cursor_carriage_return (VT102 * v)
253 {
254    /*FISH*/ v->pos.x = v->top_margin.x;
255   v->pending_wrap = 0;
256 }
257
258 void
259 vt102_cursor_advance_line (VT102 * v)
260 {
261   int couldscroll = in_margins (v, v->pos);
262
263 /*have wraped off end of last line in scrolling region */
264 /* (|| not necessary, but shuts compiler up */
265   if (((v->pos.y == v->bottom_margin.y) || (v->pos.y == v->screen_end.y)) &&
266       (couldscroll))
267     {
268       vt102_log_line (v, v->pos.y);
269       crt_scroll_up (&v->crt, v->top_margin, v->bottom_margin, 1);
270       return;
271     }
272
273   v->pos.y++;
274   v->pending_wrap = 0;
275 }
276
277
278 void
279 vt102_cursor_advance (VT102 * v)
280 {
281
282   if (v->pos.x < v->bottom_margin.x)
283     {
284 /*Normal advance*/
285       v->pos.x++;
286       v->pending_wrap = 0;
287       return;
288     }
289   v->pending_wrap++;
290 }
291
292
293 void
294 vt102_do_pending_wrap (VT102 * v)
295 {
296   int couldscroll = in_margins (v, v->pos);
297   int autowrap = v->private_modes[VT102_PRIVATE_MODE_AUTO_WRAP];
298
299   if (!v->pending_wrap)
300     return;
301
302 #if 0
303   fprintf (stderr, "ca: (%d,%d) autowrap %d couldscroll %d\n", v->pos.x,
304            v->pos.y, autowrap, couldscroll);
305 #endif
306
307 /*End of line but no autowrap, nothing to do*/
308   if (!autowrap)
309     return;
310
311 /*End of screen and not allowed to scroll, nothing to do*/
312   if ((v->pos.y == v->screen_end.y) && (!couldscroll))
313     return;
314
315   if (couldscroll)
316     {
317       v->pos.x = v->top_margin.x;
318     }
319   else
320     {
321       v->pos.x = 0;
322     }
323
324   vt102_cursor_advance_line (v);
325 }
326
327
328 void
329 vt102_cursor_retard (VT102 * v)
330 {
331   if (v->pos.x != v->top_margin.x)
332     v->pos.x--;
333
334   v->pending_wrap = 0;
335 }
336
337 void
338 vt102_reset_tabs (VT102 * v)
339 {
340   int i;
341
342   memset (v->tabs, 0, sizeof (v->tabs));
343
344   for (i = 0; i < VT102_COLS; i += 8)
345     {
346       v->tabs[i]++;
347     }
348 }
349 void
350 vt102_cursor_advance_tab (VT102 * v)
351 {
352   if (v->pos.x == v->bottom_margin.x)
353     return;
354   while (v->pos.x < v->bottom_margin.x)
355     {
356       v->pos.x++;
357       if (v->tabs[v->pos.x])
358         break;
359     }
360   v->pending_wrap = 0;
361 }
362
363 vt102_cursor_home (VT102 * v)
364 {
365   v->pos = v->top_margin;
366   vt102_cursor_normalize (v);
367   v->pending_wrap = 0;
368  
369 }
370
371 vt102_cursor_absolute (VT102 * v, int x, int y)
372 {
373   if (v->private_modes[VT102_PRIVATE_MODE_ORIGIN_MODE])
374     {
375       v->pos.x = x + v->top_margin.x;
376       v->pos.y = y + v->top_margin.x;
377     }
378   else
379     {
380       v->pos.x = x;
381       v->pos.y = y;
382     }
383   vt102_cursor_normalize (v);
384   v->pending_wrap = 0;
385 }
386
387 vt102_cursor_relative (VT102 * v, int x, int y)
388 {
389   v->pos.x += x;
390   v->pos.y += y;
391   vt102_cursor_normalize (v);
392   v->pending_wrap = 0;
393 }
394
395
396
397 void
398 vt102_delete_from_line (VT102 * v, CRT_Pos p)
399 {
400   int n = v->bottom_margin.x - p.x;
401
402   if (n < 0)
403     return;
404
405   if (n)
406     {
407
408       memmove (&v->crt.screen[CRT_ADDR_POS (&p)],
409                &v->crt.screen[CRT_ADDR_POS (&p) + 1], sizeof (CRT_CA) * n);
410     }
411
412   v->crt.screen[CRT_ADDR (p.y, v->bottom_margin.x)].chr = ' ';
413 /*But not attr due to vt102 bug*/
414 }
415
416 void
417 vt102_insert_into_line (VT102 * v, CRT_Pos p)
418 {
419   int n = v->bottom_margin.x - p.x;
420
421   if (n < 0)
422     return;
423
424   if (n)
425     {
426
427       memmove (&v->crt.screen[CRT_ADDR_POS (&p) + 1],
428                &v->crt.screen[CRT_ADDR_POS (&p)], sizeof (CRT_CA) * n);
429     }
430
431   v->crt.screen[CRT_ADDR (p.y, v->bottom_margin.x)].chr = ' ';
432   v->crt.screen[CRT_ADDR (p.y, v->bottom_margin.x)].attr = CRT_ATTR_NORMAL;
433 }
434
435
436
437 void
438 vt102_change_mode (VT102 * v, int private, char *ns, int set)
439 {
440   int m;
441
442
443   if (*ns)
444     {
445       m = atoi (ns);
446     }
447   else
448     {
449       m = 1;
450     }
451
452   if (m < 0)
453     return;
454   if (m >= VT102_NMODES)
455     return;
456
457   if (private)
458     {
459       v->private_modes[m] = set;
460       switch (m)
461         {
462         case VT102_PRIVATE_MODE_ORIGIN_MODE:
463           vt102_cursor_home (v);
464           break;
465         }
466
467     }
468   else
469     v->modes[m] = set;
470
471 #if 0
472   fprintf (stderr, "mode set=%d private=%d num=%d\n", set, private, m);
473 #endif
474 }
475
476 void
477 vt102_parse_mode_string (VT102 * v, char *buf, int len)
478 {
479   int private = 0;
480   char last = buf[len - 1];
481   char num[4];
482   int o;
483
484   memset (num, 0, sizeof (num));
485   o = sizeof (num) - 1;
486
487   len--;
488
489   if (*buf == '?')
490     {
491       private++;
492       buf++;
493       len--;
494     }
495
496   if (len < 0)
497     return;
498
499   while (len--)
500     {
501       if (*buf == ';')
502         {
503           vt102_change_mode (v, private, &num[o], last == 'h');
504           memset (num, 0, sizeof (num));
505           o = sizeof (num) - 1;
506           buf++;
507           continue;
508         }
509
510       num[0] = num[1];
511       num[1] = num[2];
512       num[2] = *buf;
513
514       if (o)
515         o--;
516
517       buf++;
518     }
519
520   vt102_change_mode (v, private, &num[o], last == 'h');
521
522 }
523
524
525 void
526 vt102_change_attr (VT102 * v, char *na)
527 {
528   int a;
529
530
531   if (*na)
532     {
533       a = atoi (na);
534     }
535   else
536     {
537       a = 0;
538     }
539
540   switch (a)
541     {
542     case 0:
543       v->attr = CRT_ATTR_NORMAL;
544       break;
545     case 1:
546       v->attr |= CRT_ATTR_BOLD;
547       break;
548     case 21:
549     case 22:
550       v->attr &= ~CRT_ATTR_BOLD;
551       break;
552     case 4:
553       v->attr |= CRT_ATTR_UNDERLINE;
554       break;
555     case 24:
556       v->attr &= ~CRT_ATTR_UNDERLINE;
557       break;
558     case 5:
559       v->attr |= CRT_ATTR_BLINK;
560       break;
561     case 25:
562       v->attr &= ~CRT_ATTR_BLINK;
563       break;
564     case 7:
565       v->attr |= CRT_ATTR_REVERSE;
566       break;
567     case 27:
568       v->attr &= ~CRT_ATTR_REVERSE;
569       break;
570     default:
571         ;
572 #if 0
573       fprintf (stderr, "unhandled SGR %d\n", a);
574 #endif
575     }
576
577 }
578
579
580 void
581 vt102_parse_attr_string (VT102 * v, char *buf, int len)
582 {
583   int private = 0;
584   char last = buf[len - 1];
585   char num[4];
586   int o;
587
588   memset (num, 0, sizeof (num));
589   o = sizeof (num) - 1;
590
591   len--;
592
593   if (len < 0)
594     return;
595
596   while (len--)
597     {
598       if (*buf == ';')
599         {
600           vt102_change_attr (v, &num[o]);
601           memset (num, 0, sizeof (num));
602           o = sizeof (num) - 1;
603           buf++;
604           continue;
605         }
606
607       num[0] = num[1];
608       num[1] = num[2];
609       num[2] = *buf;
610
611       if (o)
612         o--;
613
614       buf++;
615     }
616   vt102_change_attr (v, &num[o]);
617 }
618
619 void vt102_save_state(VT102 *v)
620 {
621 v->saved.pos=v->pos;
622 v->saved.attr=v->attr;
623 v->saved.origin_mode=v->private_modes[VT102_PRIVATE_MODE_ORIGIN_MODE];
624 }
625
626 void vt102_restore_state(VT102 *v)
627 {
628 v->pos=v->saved.pos;
629 v->attr=v->saved.attr;
630 v->private_modes[VT102_PRIVATE_MODE_ORIGIN_MODE]=v->saved.origin_mode;
631 vt102_cursor_normalize(v);
632 v->pending_wrap = 0;
633 }
634
635 void
636 vt102_parse_esc (VT102 * v, int c)
637 {
638   switch (c)
639     {
640 case 'E':
641         if(v->pos.y==v->bottom_margin.y) {
642                 vt102_log_line (v, v->pos.y);
643                 crt_scroll_up (&v->crt, v->top_margin, v->bottom_margin, 1);
644         } else {
645                 vt102_cursor_relative(v,0,1);
646         }
647         break;
648 case 'H':
649         v->tabs[v->pos.x]++;
650         break;  
651 case 'M':
652         if(v->pos.y==v->top_margin.y) {
653                 crt_scroll_down (&v->crt, v->top_margin, v->bottom_margin, 1);
654         } else {
655                 vt102_cursor_relative(v,0,-1);
656         }
657         break;
658 case '7':
659         vt102_save_state(v);
660         break;
661 case '8':
662         vt102_restore_state(v);
663         break;
664 #if 0
665     case '=':
666     case '>':
667       {
668         char s[] = { 033, c };
669 /*Horrid hack for the moment in testing change the key mode of the upstream te*/
670         write (1, s, 2);
671       }
672       break;
673 #endif
674     default:
675 #if 0
676       fprintf (stderr, "unhandled ESC \\033 \\%03o (ESC %c)\n", c,
677                (c < 32) ? '?' : c);
678 #endif
679         ;
680     }
681 }
682 void
683 vt102_parse_csi (VT102 * v, char *buf, int len)
684 {
685   char last;
686   char *ptr;
687   char *arg = buf + 1;
688   int narg;
689
690   buf[len] = 0;
691
692   last = buf[len - 1];
693 #if 0
694   buf[len - 1] = 0;
695 #endif
696
697   if (len > 2)
698     {
699       narg = atoi (arg);
700     }
701   else
702     {
703       narg = 1;
704     }
705
706   switch (buf[0])
707     {
708     case '[':
709       switch (last)
710         {
711         case 'A':
712           vt102_cursor_relative (v, 0, -narg);
713           break;
714         case 'B':
715           vt102_cursor_relative (v, 0, narg);
716           break;
717         case 'C':
718           vt102_cursor_relative (v, narg, 0);
719           break;
720         case 'D':
721           vt102_cursor_relative (v, -narg, 0);
722           break;
723         case 'E':
724           vt102_cursor_relative (v, 0, narg);
725           vt102_cursor_carriage_return (v);
726             break;
727         case 'F':
728           vt102_cursor_relative (v, 0, -narg);
729           vt102_cursor_carriage_return (v);
730             break;
731         case 'G':
732             vt102_cursor_absolute (v, narg-1, v->pos.y);
733             break;
734         case 'H':
735         case 'f':
736           {
737             int x, y;
738
739             y = narg - 1;
740
741             ptr = index (arg, ';');
742             if (ptr)
743               x = atoi (ptr + 1) - 1;
744             else
745               x = 0;
746
747             vt102_cursor_absolute (v, x, y);
748           }
749           break;
750         case 'J':
751           switch (narg)
752             {
753             case 1:
754               crt_erase (&v->crt, v->pos, v->screen_end, 1);
755               break;
756             case 2:
757               crt_erase (&v->crt, v->screen_start, v->screen_end, 1);
758               break;
759             }
760           break;
761         case 'K':
762           {
763             CRT_Pos ls = { 0, v->pos.y };
764             CRT_Pos le = { VT102_COLS - 1, v->pos.y };
765             if (len == 2)
766               narg = 0;         /*Different default */
767
768             switch (narg)
769               {
770               case 0:
771                 crt_erase (&v->crt, v->pos, le, 1);
772                 break;
773               case 1:
774                 crt_erase (&v->crt, ls, v->pos, 1);
775                 break;
776               case 2:
777                 crt_erase (&v->crt, ls, le, 1);
778                 break;
779               }
780           }
781           break;
782
783         case 'P':
784           while (narg--)
785             vt102_delete_from_line (v, v->pos);
786           break;
787         case 'L':
788           if ((v->pos.y >= v->top_margin.y)
789               && (v->pos.y <= v->bottom_margin.y))
790             {
791               while (narg--)
792                 crt_scroll_down (&v->crt, v->pos, v->bottom_margin, 1);
793             }
794           break;
795
796         case 'M':
797           if ((v->pos.y >= v->top_margin.y)
798               && (v->pos.y <= v->bottom_margin.y))
799             {
800               while (narg--)
801                 crt_scroll_up (&v->crt, v->pos, v->bottom_margin, 0);
802             }
803           break;
804
805         case 'g':
806           if (len == 2)
807             narg = 0;           /*Different default */
808
809           switch (narg)
810             {
811             case 0:
812               v->tabs[v->pos.x] = 0;
813               break;
814             case 3:
815               memset (v->tabs, 0, sizeof (v->tabs));
816               break;
817             }
818           break;
819
820         case 'h':
821         case 'l':
822           vt102_parse_mode_string (v, &buf[1], len - 1);
823           break;
824
825         case 'm':
826           vt102_parse_attr_string (v, &buf[1], len - 1);
827           break;
828         case 'r':
829           v->top_margin = v->screen_start;
830           v->bottom_margin = v->screen_end;
831
832           if ((len > 2) && (ptr = index (arg, ';')))
833             {
834               ptr++;
835               v->top_margin.y = narg - 1;
836               v->bottom_margin.y = atoi (ptr) - 1;
837             }
838
839           if (v->top_margin.y < v->screen_start.y)
840             v->top_margin.y = v->screen_start.y;
841           if (v->top_margin.y > v->screen_end.y)
842             v->top_margin.y = v->screen_end.y;
843           if (v->bottom_margin.y < v->screen_start.y)
844             v->bottom_margin.y = v->screen_start.y;
845           if (v->bottom_margin.y > v->screen_end.y)
846             v->bottom_margin.y = v->screen_end.y;
847
848           vt102_cursor_home (v);
849           break;
850         case 's':
851                 v->saved.pos=v->pos;
852                 break;
853         case 'u':
854                 v->pos=v->saved.pos;
855                 vt102_cursor_normalize(v);
856                 v->pending_wrap = 0;
857                 break;
858
859         default:
860 #if 0
861           fprintf (stderr, "unhandled CSI  \\033%s\n", buf, buf[0]);
862 #endif
863         ;
864         }
865       break;
866     default:
867 #if 0
868       fprintf (stderr, "unhandled CSI  \\033%s\n", buf, buf[0]);
869 #endif
870         ;
871     }
872
873
874
875 }
876
877 void
878 vt102_status_line (VT102 * v, char *str)
879 {
880   int i = VT102_COLS;
881   CRT_CA *ca = &v->crt.screen[CRT_ADDR (VT102_STATUS_ROW, 0)];
882
883   while (i--)
884     {
885       ca->attr = CRT_ATTR_REVERSE;
886       ca->chr = *str;
887       if (*str)
888         str++;
889       ca++;
890     }
891
892 }
893
894
895 void
896 vt102_parse_char (VT102 * v, int c)
897 {
898   VT102_parser *p = &v->parser;
899
900 #if 0
901   fprintf (stderr, "char %c pc %d %d %d   %d %d\n", (c < 32) ? 32 : c, c,
902            p->in_csi, p->in_escape, v->pos.x, v->pos.y);
903 #endif
904   if (p->in_csi)
905     {
906       p->csi_buf[p->csi_ptr++] = c;
907       if (csi_ender (c) || (p->csi_ptr == VT102_CSI_LEN))
908         {
909           vt102_parse_csi (v, p->csi_buf, p->csi_ptr);
910           p->in_csi = 0;
911         }
912     }
913   else if (p->in_escape)
914     {
915       if (csi_starter (c))
916         {
917           p->csi_ptr = 0;
918           p->csi_buf[p->csi_ptr++] = c;
919           p->in_csi++;
920           p->in_escape = 0;
921         }
922       else
923         {
924           p->in_escape = 0;
925           vt102_parse_esc (v, c);
926         }
927     }
928   else
929     {
930
931       switch (c)
932         {
933          /*NUL*/ case 0:
934          /*SOH*/ case 1:
935          /*STX*/ case 2:
936          /*ETX*/ case 3:
937          /*EOT*/ case 4:
938                 break;
939          /*ENQ*/ case 5:
940           /*FIXME: Should send ack*/
941         break;
942          /*ACK*/ case 6:
943          /*BEL*/ case 7:
944           break;
945          /*BS*/ case 8:
946           vt102_cursor_retard (v);
947           break;
948          /*HT*/ case 9:
949           vt102_cursor_advance_tab (v);
950           break;
951          /*LF*/ case 10:
952          /*VT*/ case 11:
953          /*FF*/ case 12:
954           vt102_cursor_advance_line (v);
955           if (!v->modes[VT102_MODE_NEWLINE_MODE])
956             break;
957          /*CR*/ case 13:
958           vt102_cursor_carriage_return (v);
959           break;
960          /*SO*/ case 14:
961          /*SI*/ case 15:
962          /*DLE*/ case 16:
963         /*DC1 */ case 17:
964         /*DC2 */ case 18:
965         /*DC3 */ case 19:
966         /*DC4 */ case 20:
967          /*NAK*/ case 21:
968          /*SYN*/ case 22:
969          /*ETB*/ case 23:
970          /*CAN*/ case 24:
971          /*EM*/ case 25:
972          /*SUB*/ case 26:
973           break;
974          /*ESC*/ case 27:
975           p->in_escape++;
976           return;
977          /*FS*/ case 28:
978          /*GS*/ case 29:
979          /*RS*/ case 30:
980          /*US*/ case 31:
981          /*DEL*/ case 127:
982           break;
983         /*regular character */ default:
984           vt102_do_pending_wrap (v);
985
986           if (v->modes[VT102_MODE_INSERT])
987             vt102_insert_into_line (v, v->pos);
988
989           v->crt.screen[CRT_ADDR_POS (&v->pos)].chr = c;
990           v->crt.screen[CRT_ADDR_POS (&v->pos)].attr = v->attr;
991           vt102_cursor_advance (v);
992         }
993     }
994
995   v->crt.pos = v->pos;
996   v->crt.hide_cursor=v->private_modes[VT102_PRIVATE_MODE_SHOW_CURSOR] ? 0:1;
997
998   if (v->current_line.y != v->pos.y)
999     {
1000       vt102_log_line (v, v->current_line.y);
1001       v->current_line = v->pos;
1002     }
1003
1004   vt102_status_line (v, "VT102 foo bar baz I'm the urban spaceman baby");
1005 }
1006
1007 void
1008 vt102_parser_reset (VT102_parser * p)
1009 {
1010   p->in_csi = 0;
1011   p->in_escape = 0;
1012   p->csi_ptr = 0;
1013 }
1014
1015 void
1016 vt102_reset (VT102 * v)
1017 {
1018   VT102_parser *p = &v->parser;
1019
1020   vt102_parser_reset (p);
1021   crt_cls (&v->crt);
1022
1023
1024
1025   v->current_line = v->pos;
1026   v->pending_wrap = 0;
1027
1028   v->screen_start.x = 0;
1029   v->screen_start.y = 0;
1030   v->screen_end.x = VT102_COLS - 1;
1031   v->screen_end.y = VT102_ROWS - 1;
1032
1033   v->top_margin = v->screen_start;
1034   v->bottom_margin = v->screen_end;
1035
1036   memset (v->modes, 0, VT102_NMODES);
1037   memset (v->private_modes, 0, VT102_NMODES);
1038
1039   v->private_modes[VT102_PRIVATE_MODE_AUTO_WRAP] = 1;
1040   v->private_modes[VT102_PRIVATE_MODE_AUTO_REPEAT] = 1;
1041   v->private_modes[VT102_PRIVATE_MODE_SHOW_CURSOR] = 1;
1042
1043   vt102_cursor_home (v);
1044   vt102_reset_tabs (v);
1045   v->current_line = v->pos;
1046
1047   vt102_save_state(v);
1048
1049 #if 0
1050 {
1051 char buf[3];
1052 int i;
1053   for (i=0;i<200;++i) {
1054         sprintf(buf,"%3d",i);
1055         vt102_parse_char (v,buf[0]);
1056         vt102_parse_char (v,buf[1]);
1057         vt102_parse_char (v,buf[2]);
1058         vt102_parse_char (v,13);
1059         vt102_parse_char (v,27);
1060         vt102_parse_char (v,'M');
1061   }
1062   vt102_parse_char(v,'f');
1063         vt102_parse_char (v,13);
1064    for (i=0;i<23;++i) {
1065         vt102_parse_char (v,27);
1066         vt102_parse_char (v,'M');
1067    }
1068   vt102_parse_char(v,'b');
1069         vt102_parse_char (v,13);
1070 }
1071 #endif
1072
1073
1074   vt102_status_line (v, "VT102 foo bar baz I'm the urban spaceman baby");
1075
1076 }