12 #define MAX(A, B) ((A) > (B) ? (A) : (B))
13 #define CLEARWRAP do{ if (term->col >= term->cols) term->col = term->cols-1; }while(0)
14 #define CLIPROW(X) if (term->row<0 || term->row >= term->rows) term->row = X
15 #define CLIPCOL(X) if (term->col<0 || term->col >= term->cols) term->col = X
17 static int verbose
= 0;
20 logfmt(char *fmt
, ...)
25 vfprintf(stderr
, fmt
, args
);
30 set_verbosity(int level
)
36 save_cursor(Term
*term
)
38 term
->save_cursor
.row
= term
->row
;
39 term
->save_cursor
.col
= term
->col
;
43 load_cursor(Term
*term
)
45 term
->row
= term
->save_cursor
.row
;
46 term
->col
= term
->save_cursor
.col
;
52 term
->save_misc
.row
= term
->row
;
53 term
->save_misc
.col
= term
->col
;
54 term
->save_misc
.origin_on
= term
->mode
& M_ORIGIN
;
55 term
->save_misc
.attr
= term
->attr
;
56 term
->save_misc
.pair
= term
->pair
;
57 term
->save_misc
.cs_array
[0] = term
->cs_array
[0];
58 term
->save_misc
.cs_array
[1] = term
->cs_array
[1];
59 term
->save_misc
.cs_index
= term
->cs_index
;
65 term
->row
= term
->save_misc
.row
;
66 term
->col
= term
->save_misc
.col
;
67 if (term
->save_misc
.origin_on
)
68 term
->mode
|= M_ORIGIN
;
70 term
->mode
&= ~M_ORIGIN
;
71 term
->attr
= term
->save_misc
.attr
;
72 term
->pair
= term
->save_misc
.pair
;
73 term
->cs_array
[0] = term
->save_misc
.cs_array
[0];
74 term
->cs_array
[1] = term
->save_misc
.cs_array
[1];
75 term
->cs_index
= term
->save_misc
.cs_index
;
79 set_default_palette(char * pname
)
85 { "xterm", plt_xterm
},
86 { "vga", plt_vga_ansi
},
87 { "sol_ansi", plt_solarized_like_ansi
},
88 { "solarized", plt_solarized
},
89 { "putty", plt_putty
},
93 if (pname
[0] == '@') {
95 for(i
=0; pal
[i
].name
; i
++) {
96 if (strcasecmp(pname
+1, pal
[i
].name
) == 0) {
101 fprintf(stderr
, "Known standard palette names are:\n");
102 for(i
=0; pal
[i
].name
; i
++)
103 fprintf(stderr
, " @%s\n", pal
[i
].name
);
109 uint8_t * plt
= malloc(sizeof(term
->plt
));
110 memcpy(plt
, def_plt
, sizeof(term
->plt
));
113 if ((fd
= fopen(pname
, "r")) == 0) {
114 perror(pname
); exit(1);
116 while (fgets(buf
, sizeof(buf
), fd
) != 0) {
118 long cno
= 0, colour
= 0;
120 while (*s
== ' ' || *s
== '\t') s
++;
121 if (*s
== '#') continue;
123 if (strncasecmp(s
, "color", 5) == 0) {
125 } else if (strncasecmp(s
, "colour", 6) == 0) {
129 // Only lines that match /^ *colou?r[0-9]+/i
130 if (*s
< '0' || *s
> '9') continue;
132 cno
= strtol(s
, &e
, 0);
133 if (s
== e
) goto bad_line
;
134 if (cno
< 0 || cno
> 16) goto bad_line
;
137 while (*s
== ' ' || *s
== '\t' || *s
== '#' || *s
== '=') s
++;
138 colour
= strtol(s
, &e
, 16);
139 if (e
-s
!= 6) goto bad_line
;
141 plt
[cno
*3+0] = ((colour
>>16) & 0xFF);
142 plt
[cno
*3+1] = ((colour
>> 8) & 0xFF);
143 plt
[cno
*3+2] = ((colour
) & 0xFF);
146 fprintf(stderr
, "Bad line in colour file: %s", buf
);
160 term
->row
= term
->col
= 0;
162 term
->bot
= term
->rows
- 1;
163 term
->mode
= def_mode
;
164 term
->attr
= def_attr
;
165 term
->pair
= def_pair
;
166 term
->cs_array
[0] = CS_BMP
;
167 term
->cs_array
[1] = CS_VTG
;
171 if (memcmp(term
->plt
, def_plt
, sizeof(term
->plt
) != 0)) {
174 memcpy(term
->plt
, def_plt
, sizeof(term
->plt
));
176 for (i
= 0; i
< term
->rows
; i
++) {
177 term
->addr
[i
] = &term
->cells
[i
*term
->cols
];
178 for (j
= 0; j
< term
->cols
; j
++)
179 term
->addr
[i
][j
] = (Cell
) {EMPTY
, def_attr
, def_pair
};
186 new_term(int rows
, int cols
)
188 size_t size
= sizeof(Term
) + rows
*sizeof(Cell
*) + rows
*cols
*sizeof(Cell
);
189 Term
*term
= malloc(size
);
194 term
->addr
= (Cell
**) &term
[1];
195 term
->cells
= (Cell
*) &term
->addr
[rows
];
202 char_code(Term
*term
)
205 uint16_t code
= term
->partial
[0] & ((1 << (8 - term
->parlen
)) - 1);
206 for (i
= 1; i
< term
->parlen
; i
++)
207 code
= (code
<< 6) | (term
->partial
[i
] & 0x3F);
212 within_bounds(Term
*term
, int row
, int col
)
214 if (row
< 0 || row
>= term
->rows
|| col
< 0 || col
> term
->cols
) {
215 logfmt("position %d,%d is out of bounds %d,%d\n",
216 row
+1, col
+1, term
->rows
, term
->cols
);
223 /* Move lines down and put a blank line at the top. */
225 scroll_up(Term
*term
)
230 if (!within_bounds(term
, term
->top
, 0))
232 if (!within_bounds(term
, term
->bot
, 0))
234 addr
= term
->addr
[term
->bot
];
235 for (row
= term
->bot
; row
> term
->top
; row
--)
236 term
->addr
[row
] = term
->addr
[row
-1];
237 term
->addr
[term
->top
] = addr
;
238 for (col
= 0; col
< term
->cols
; col
++)
239 term
->addr
[term
->top
][col
] = BLANK
;
242 /* Move lines up and put a blank line at the bottom. */
244 scroll_down(Term
*term
)
249 if (!within_bounds(term
, term
->top
, 0))
251 if (!within_bounds(term
, term
->bot
, 0))
253 addr
= term
->addr
[term
->top
];
254 for (row
= term
->top
; row
< term
->bot
; row
++)
255 term
->addr
[row
] = term
->addr
[row
+1];
256 term
->addr
[term
->bot
] = addr
;
257 for (col
= 0; col
< term
->cols
; col
++)
258 term
->addr
[term
->bot
][col
] = BLANK
;
262 addchar(Term
*term
, uint16_t code
)
264 Cell cell
= (Cell
) {code
, term
->attr
, term
->pair
};
265 if (term
->col
>= term
->cols
) {
266 if (term
->mode
& M_AUTOWRAP
) {
268 if (term
->row
< term
->bot
)
273 term
->col
= term
->cols
- 1;
276 if (!within_bounds(term
, term
->row
, term
->col
))
278 if (term
->mode
& M_INSERT
) {
281 for (col
= term
->col
; col
< term
->cols
; col
++) {
282 next
= term
->addr
[term
->row
][col
];
283 term
->addr
[term
->row
][col
] = cell
;
287 term
->addr
[term
->row
][term
->col
] = cell
;
295 if (term
->row
== term
->bot
)
299 if (term
->mode
& M_NEWLINE
)
304 ctrlchar(Term
*term
, uint8_t byte
)
309 if (term
->col
) term
->col
--;
312 /* TODO: See ESC Sequence H (HTS) */
313 term
->col
&= ~7; term
->col
+= 8;
314 CLIPCOL(term
->cols
-1);
316 case 0x0A: case 0x0B: case 0x0C:
333 escseq(Term
*term
, uint8_t byte
)
335 uint8_t first
, second
;
338 first
= *term
->partial
;
350 if (term
->row
== term
->bot
)
357 if (term
->row
== term
->bot
) {
365 /* TODO: set tab stop at current column */
366 logfmt("NYI: ESC Sequence H (HTS)\n");
369 if (term
->row
== term
->top
)
375 /* Identify Terminal (DECID) */
376 /* if we were a real terminal, we'd reply with "ESC [ ? 6 c" */
377 /* since there is no application listening, we can ignore this */
388 /* TODO: select charset */
389 logfmt("NYI: ESC Sequence %% (character set selection)\n");
392 case '8': /* Linux switch to UTF8 */
393 case 'G': /* DOCS: Designate other coding system */
394 term
->mode
&= ~M_ISOLAT1
;
395 if (term
->cs_array
[0] == CS_ISO
)
396 term
->cs_array
[0] = CS_BMP
;
397 if (term
->cs_array
[1] == CS_ISO
)
398 term
->cs_array
[1] = CS_BMP
;
400 case '@': /* DOCS, Standard return */
401 term
->mode
|= M_ISOLAT1
;
402 if (term
->cs_array
[0] == CS_BMP
)
403 term
->cs_array
[0] = CS_ISO
;
404 if (term
->cs_array
[1] == CS_BMP
)
405 term
->cs_array
[1] = CS_ISO
;
415 for (i
= 0; i
< term
->rows
; i
++) {
416 for (j
= 0; j
< term
->cols
; j
++) {
417 term
->addr
[i
][j
] = (Cell
) {'E', def_attr
, def_pair
};
424 logfmt("NYI: ESC Sequence # 3..6 DECDWL etc\n");
431 term
->cs_array
[0] = (term
->mode
&M_ISOLAT1
)?CS_ISO
:CS_BMP
;
434 term
->cs_array
[0] = CS_VTG
;
437 term
->cs_array
[0] = CS_437
;
440 logfmt("UNS: user-defined mapping\n");
441 term
->cs_array
[0] = (term
->mode
&M_ISOLAT1
)?CS_ISO
:CS_BMP
;
448 term
->cs_array
[1] = (term
->mode
&M_ISOLAT1
)?CS_ISO
:CS_BMP
;
451 term
->cs_array
[1] = CS_VTG
;
454 term
->cs_array
[1] = CS_437
;
457 logfmt("UNS: user-defined mapping\n");
458 term
->cs_array
[1] = (term
->mode
&M_ISOLAT1
)?CS_ISO
:CS_BMP
;
463 /* TODO: set numeric keypad mode */
464 logfmt("NYI: ESC Sequence > (DECPNM)\n");
467 /* TODO: set application keypad mode */
468 logfmt("NYI: ESC Sequence = (DECPAM)\n");
471 logfmt("UNS: ESC Sequence %c\n", first
);
476 do_linux_osc(Term
*term
)
479 uint8_t buf
[4] = {0,0,0,0};
480 if (term
->partial
[0] == 'R')
482 if (memcmp(term
->plt
, def_plt
, sizeof(term
->plt
) != 0))
484 memcpy(term
->plt
, def_plt
, sizeof(term
->plt
));
488 if (term
->partial
[0] != 'P' || term
->parlen
!= 8)
491 for (i
=1; i
<8; i
++) {
492 /* isxdigit is locale broken */
493 int ch
= term
->partial
[i
];
494 if (ch
>= '0' && ch
<= '9')
495 buf
[i
>>1] = (buf
[i
>>1] << 4) + (ch
- '0');
496 else if (ch
>= 'a' && ch
<= 'f')
497 buf
[i
>>1] = (buf
[i
>>1] << 4) + (ch
- 'a' + 10);
498 else if (ch
>= 'A' && ch
<= 'F')
499 buf
[i
>>1] = (buf
[i
>>1] << 4) + (ch
- 'A' + 10);
504 if (term
->plt
[buf
[0]*3+i
] != buf
[i
+1]) {
505 term
->plt
[buf
[0]*3+i
] = buf
[i
+1];
506 term
->plt_local
= term
->plt_dirty
= 1;
514 getparams(char *partial
, int *params
, int n
)
517 char *token
= partial
;
523 while (i
< n
&& *token
) {
524 params
[i
++] = strtol(token
, &next
, 10);
528 if (i
< n
&& *(token
-1) == ';')
533 #define SWITCH(T, F, V) (T)->mode = (V) ? (T)->mode | (F) : (T)->mode & ~(F)
536 modeswitch(Term
*term
, int private, int number
, int value
)
542 SWITCH(term
, M_CURSORKEY
, value
);
545 /* TODO: 80/132 columns mode switch */
546 logfmt("NYI: DEC mode 3\n");
549 SWITCH(term
, M_REVERSE
, value
);
552 SWITCH(term
, M_ORIGIN
, value
);
553 term
->row
= term
->top
;
557 SWITCH(term
, M_AUTOWRAP
, value
);
560 SWITCH(term
, M_AUTORPT
, value
);
563 SWITCH(term
, M_MOUSEX10
, value
);
566 SWITCH(term
, M_CURSORVIS
, value
);
569 SWITCH(term
, M_MOUSEX11
, value
);
572 logfmt("UNS: DEC mode %d\n", number
);
578 SWITCH(term
, M_DISPCTRL
, value
);
581 SWITCH(term
, M_INSERT
, value
);
584 SWITCH(term
, M_NEWLINE
, value
);
587 logfmt("UNS: ANSI mode %d\n", number
);
593 fake_colour_16m(int red
, int green
, int blue
)
595 int av
= (red
+green
+blue
)/3;
596 int palno
= 1*(red
>=av
) + 2*(green
>=av
) + 4*(blue
>=av
);
597 if (red
==green
&& green
==blue
) {
598 if (av
> 212) palno
= 15-8;
599 else if (av
> 127) palno
= 7-8;
600 else if (av
> 42) palno
= 8;
603 return palno
+ 8*(av
>127);
607 fake_colour_256(int colnum
){
610 nr
= (colnum
&1) ? 170:0;
611 ng
= (colnum
&2) ? 170:0;
612 nb
= (colnum
&4) ? 170:0;
613 if (colnum
&8) { nr
+= 85; ng
+= 85; nb
+= 85; }
614 if (colnum
== 3) ng
= 85;
615 } else if (colnum
< 232) {
617 nr
= i
/ 36; ng
= (i
/ 6) % 6; nb
= i
% 6;
618 nr
= nr
? nr
* 40 + 55 : 0;
619 ng
= ng
? ng
* 40 + 55 : 0;
620 nb
= nb
? nb
* 40 + 55 : 0;
621 } else if (colnum
< 256) {
622 int i
= colnum
- 232;
623 nr
= ng
= nb
= i
* 10 + 8;
627 return fake_colour_16m(nr
, ng
, nb
);
631 sgr(Term
*term
, int n
, int *params
)
639 term
->attr
= def_attr
;
640 term
->pair
= def_pair
;
643 term
->attr
|= A_BOLD
;
649 term
->attr
|= A_ITALIC
;
652 term
->attr
|= A_UNDERLINE
;
655 term
->attr
|= A_BLINK
;
658 term
->attr
|= A_INVERSE
;
661 term
->attr
|= A_INVISIBLE
;
664 /* TODO: reset toggle meta flag */
665 term
->cs_array
[term
->cs_index
= 0] = (term
->mode
&M_ISOLAT1
)?CS_ISO
:CS_BMP
;
666 term
->mode
&= ~M_DISPCTRL
;
669 /* TODO: reset toggle meta flag */
670 term
->cs_array
[term
->cs_index
] = CS_437
;
671 term
->mode
|= M_DISPCTRL
;
674 /* TODO: set toggle meta flag */
675 term
->cs_array
[term
->cs_index
] = CS_437
;
676 term
->mode
|= M_DISPCTRL
;
680 term
->attr
|= A_UNDERLINE
; /* Linux say should be: DOUBLE_ULINE */
684 term
->attr
&= ~A_DIM
;
685 term
->attr
&= ~A_BOLD
;
688 term
->attr
&= ~A_ITALIC
;
691 term
->attr
&= ~A_UNDERLINE
;
694 term
->attr
&= ~A_BLINK
;
697 term
->attr
&= ~A_INVERSE
;
699 case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
700 term
->pair
= ((number
- 30) << 4) | (term
->pair
& 0x0F);
704 term
->attr
|= A_UNDERLINE
;
705 term
->pair
= (DEF_FORE
<< 4) | (term
->pair
& 0x0F);
708 term
->attr
&= ~A_UNDERLINE
;
709 term
->pair
= (DEF_FORE
<< 4) | (term
->pair
& 0x0F);
716 if (params
[i
] == 5) {
718 term
->pair
= (fake_colour_256(params
[i
+1]) << 4) | (term
->pair
& 0x0F);
721 } else if (params
[i
] == 2) {
722 /* 16M colours, note I'm using common form not strict ITU T.416 */
723 term
->pair
= (fake_colour_16m(params
[i
+1],params
[i
+2],params
[i
+3]) << 4) | (term
->pair
& 0x0F);
727 /* Could be CMYK; probably broken */
731 term
->pair
= (DEF_FORE
<< 4) | (term
->pair
& 0x0F);
734 case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47:
735 term
->pair
= (term
->pair
& 0xF0) | (number
- 40);
741 if (params
[i
] == 5) {
743 term
->pair
= (term
->pair
& 0xF0) | fake_colour_256(params
[i
+1]);
746 } else if (params
[i
] == 2) {
747 /* 16M colours, note I'm using common form not strict ITU T.416 */
748 term
->pair
= (term
->pair
& 0xF0) | fake_colour_16m(params
[i
+1],params
[i
+2],params
[i
+3]);
752 /* Could be CMYK; probably broken */
757 term
->pair
= (term
->pair
& 0xF0) | DEF_BACK
;
759 case 90: case 91: case 92: case 93: case 94: case 95: case 96: case 97:
760 term
->pair
= ((number
- 90 + 8) << 4) | (term
->pair
& 0x0F);
762 case 100: case 101: case 102: case 103: case 104: case 105: case 106: case 107:
763 term
->pair
= (term
->pair
& 0xF0) | (number
- 100 + 8);
766 logfmt("UNS: SGR %d\n", number
);
772 ctrlseq(Term
*term
, uint8_t byte
)
776 int params
[MAX_PARAMS
];
782 if (!within_bounds(term
, term
->row
, term
->col
))
784 term
->partial
[term
->parlen
] = '\0';
785 if (*term
->partial
== '?') {
787 str
= (char *) term
->partial
+ 1;
790 str
= (char *) term
->partial
;
792 n
= getparams(str
, params
, MAX_PARAMS
);
798 /* TODO: insert the indicated # of blank characters */
799 logfmt("NYI: Control Sequence @ (ICH)\n");
809 CLIPROW(term
->rows
-1);
814 CLIPCOL(term
->cols
-1);
824 CLIPROW(term
->rows
-1);
833 CLIPCOL(term
->cols
-1);
837 term
->row
= MAX(params
[0], 1) - 1;
838 term
->col
= MAX(params
[1], 1) - 1;
840 term
->row
= MAX(params
[0], 1) - 1;
843 term
->row
= term
->col
= 0;
845 if (term
->mode
& M_ORIGIN
)
846 term
->row
+= term
->top
;
847 CLIPROW(term
->rows
-1);
848 CLIPCOL(term
->cols
-1);
852 ra
= 0; rb
= term
->rows
- 1;
853 ca
= 0; cb
= term
->cols
- 1;
861 for (j
= ca
; j
< term
->cols
; j
++)
862 term
->addr
[ra
][j
] = BLANK
;
863 for (i
= ra
+1; i
< rb
; i
++) {
864 for (j
= 0; j
< term
->cols
; j
++) {
865 term
->addr
[i
][j
] = BLANK
;
868 for (j
= 0; j
<= cb
; j
++)
869 term
->addr
[rb
][j
] = BLANK
;
873 ca
= 0; cb
= term
->cols
- 1;
878 for (j
= ca
; j
<= cb
; j
++)
879 term
->addr
[term
->row
][j
] = BLANK
;
883 if (term
->row
< term
->top
|| term
->row
> term
->bot
)
885 /* This is implemented naively:
886 1. temporarily change the top margin to current row;
887 2. scroll up as many times as requested;
888 3. restore top margin to previous value. */
890 term
->top
= term
->row
;
891 for (j
= 0; j
< k1
; j
++)
897 if (term
->row
< term
->top
|| term
->row
> term
->bot
)
899 /* This is implemented naively:
900 1. temporarily change the top margin to current row;
901 2. scroll down as many times as requested;
902 3. restore top margin to previous value. */
905 "Lines added to bottom of screen have spaces with same character
906 attributes as last line moved up."
907 we need a more flexible scroll_down() to fix this. */
909 term
->top
= term
->row
;
910 for (j
= 0; j
< k1
; j
++)
916 cell
= term
->addr
[term
->row
][term
->cols
-1];
918 for (j
= term
->col
; j
< term
->cols
-k1
; j
++)
919 term
->addr
[term
->row
][j
] = term
->addr
[term
->row
][j
+k1
];
920 for (j
= term
->cols
-k1
; j
< term
->cols
; j
++)
921 term
->addr
[term
->row
][j
] = cell
;
925 for (j
= 0; j
< k1
; j
++)
926 term
->addr
[term
->row
][term
->col
+j
] = BLANK
;
929 /* Device Attributes (DA) */
930 /* if we were a real terminal, we'd reply with "ESC [ ? 6 c" */
931 /* since there is no application listening, we can ignore this */
938 /* TODO: clear tab stop */
939 logfmt("NYI: Control Sequence g (TBC)\n");
942 for (i
= 0; i
< n
; i
++)
943 modeswitch(term
, private, params
[i
], 1);
946 for (i
= 0; i
< n
; i
++)
947 modeswitch(term
, private, params
[i
], 0);
950 sgr(term
, n
, params
);
953 /* Device Status Report (DSR) */
954 /* if we were a real terminal, we'd send a status reply (e.g. CPR) */
955 /* since there is no application listening, we can ignore this */
958 /* TODO: set keyboard LEDs */
959 logfmt("NYI: Control Sequence q (DECLL)\n");
963 term
->top
= MAX(params
[0], 1) - 1;
964 term
->bot
= MAX(params
[1], 1) - 1;
967 term
->bot
= term
->rows
- 1;
969 term
->row
= term
->mode
& M_ORIGIN
? term
->top
: 0;
979 logfmt("UNS: Control Sequence %c\n", byte
);
983 #define CHARSET(T) ((T)->cs_array[(T)->cs_index])
984 #define PARCAT(T, B) ((T)->partial[(T)->parlen++] = (B))
985 #define RESET_STATE(T) do { (T)->state = S_ANY; (T)->parlen = 0; } while(0)
986 #define CHARLEN(B) ((B) < 0xE0 ? 2 : ((B) < 0xF0 ? 3 : 4))
989 parse(Term
*term
, uint8_t byte
)
993 /* Bad suffix for a unicode sequence, dump it and interpret this byte normally. */
994 if (term
->state
== S_UNI
&& (byte
< 0x80 || byte
>= 0xC0)) {
995 addchar(term
, 0xFFFD);
998 if (byte
!= 0x1B && byte
< 0x20 && !(term
->mode
& M_DISPCTRL
)) {
999 ctrlchar(term
, byte
);
1001 switch (term
->state
) {
1005 term
->state
= S_ESC
;
1008 term
->state
= S_CSI
;
1011 switch (CHARSET(term
)) {
1014 /* single-byte UTF-8, i.e. ASCII */
1015 addchar(term
, byte
);
1016 } else if (byte
>= 0xC0) {
1017 term
->unilen
= CHARLEN(byte
);
1019 term
->state
= S_UNI
;
1021 addchar(term
, 0xFFFD);
1024 addchar(term
, byte
);
1027 addchar(term
, cs_vtg
[byte
]);
1030 addchar(term
, cs_437
[byte
]);
1035 case S_OSCESC
: case S_STRESC
:
1038 if (term
->state
== S_OSCESC
)
1039 logfmt("NYI: Operating System Sequence\n");
1042 term
->state
= S_ESC
;
1046 if (!term
->parlen
) {
1048 term
->state
= S_CSI
;
1050 } else if (byte
== 0x5D) {
1051 term
->state
= S_OSC
;
1053 } else if (byte
== 'P' || /* DCS */
1054 byte
== '_' || /* APC */
1055 byte
== '^' || /* PM */
1056 byte
== 'X' /* SOS */
1058 term
->state
= S_STR
; /* A string to eat */
1063 if (byte
>= 0x20 && byte
< 0x30) {
1072 if (byte
< 0x40 || byte
>= 0x7F) {
1075 ctrlseq(term
, byte
);
1079 case S_OSC
: case S_STR
:
1080 /* TODO: set/reset palette entries */
1081 /* Currently this just eats the string */
1083 if (term
->state
== S_OSC
)
1084 term
->state
= S_OSCESC
;
1086 term
->state
= S_STRESC
;
1087 } else if (byte
== 13 || byte
== 10)
1088 RESET_STATE(term
); /* CR or LF assume something broke */
1089 else if (byte
== 7) {
1091 if (term
->state
== S_OSC
)
1092 logfmt("NYI: Operating System Sequence\n");
1095 if (term
->parlen
< MAX_PARTIAL
-3)
1098 term
->state
= S_STR
;
1100 if (term
->partial
[0] == 'P' && term
->parlen
== 8) {
1101 if (do_linux_osc(term
))
1103 } else if (term
->partial
[0] == 'R' && term
->parlen
== 1) {
1104 if (do_linux_osc(term
))
1111 if (term
->parlen
== term
->unilen
) {
1112 addchar(term
, char_code(term
));