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