14 #define MODE_NOCURSOR 0x01
15 #define MODE_NOWRAP 0x02
16 #define MODE_ORIGIN 0x04
17 #define MODE_NOAUTOCR 0x08
18 #define BIT_SET(i, b, val) ((val) ? ((i) | (b)) : ((i) & ~(b)))
19 #define SQRADDR(r, c) (&screen[(r) * pad_cols() + (c)])
21 static struct term
*term
;
22 static struct square
*screen
;
29 #define MAXLINES (1 << 13)
30 static int dirty
[MAXLINES
];
33 static void _term_show(int r
, int c
, int cursor
)
35 struct square
*sqr
= SQRADDR(r
, c
);
36 int fgcolor
= sqr
->c
? sqr
->fg
: fg
;
37 int bgcolor
= sqr
->c
? sqr
->bg
: bg
;
38 if (cursor
&& !(mode
& MODE_NOCURSOR
)) {
44 pad_put(sqr
->c
, r
, c
, fgcolor
, bgcolor
);
47 static void _draw_row(int r
)
50 for (i
= 0; i
< pad_cols(); i
++)
54 static void lazy_draw(int sr
, int er
)
59 for (i
= sr
; i
< er
; i
++) {
67 static void lazy_drawcols(int r
, int sc
, int ec
)
75 for (i
= sc
; i
< ec
; i
++)
80 static void lazy_put(int ch
, int r
, int c
)
82 struct square
*sqr
= SQRADDR(r
, c
);
94 static void lazy_cursor(int put
)
101 _term_show(row
, col
, put
);
104 static void lazy_clean()
107 memset(dirty
, 0, sizeof(*dirty
) * MAXLINES
);
110 static void lazy_flush()
115 _term_show(row
, col
, 0);
116 for (i
= 0; i
< pad_rows(); i
++)
120 _term_show(row
, col
, 1);
123 static int origin(void)
125 return mode
& MODE_ORIGIN
;
128 static void setsize(void)
131 size
.ws_col
= pad_cols();
132 size
.ws_row
= pad_rows();
135 ioctl(term
->fd
, TIOCSWINSZ
, &size
);
138 #define PTYBUFSIZE (1 << 13)
139 static char ptybuf
[PTYBUFSIZE
];
142 static int readpty(void)
145 return ptybuf
[ptycur
++];
146 if ((ptylen
= read(term
->fd
, ptybuf
, PTYBUFSIZE
)) > 0) {
153 static void empty_rows(int sr
, int er
)
155 memset(SQRADDR(sr
, 0), 0, (er
- sr
) * sizeof(*screen
) * pad_cols());
158 static void blank_rows(int sr
, int er
)
165 static void scroll_screen(int sr
, int nr
, int n
)
168 memmove(SQRADDR(sr
+ n
, 0), SQRADDR(sr
, 0),
169 nr
* pad_cols() * sizeof(*screen
));
171 empty_rows(sr
, sr
+ n
);
173 empty_rows(sr
+ nr
+ n
, sr
+ nr
);
174 lazy_draw(MIN(sr
, sr
+ n
), MAX(sr
+ nr
, sr
+ nr
+ n
));
178 static void insert_lines(int n
)
180 int sr
= MAX(top
, row
);
181 int nr
= bot
- row
- n
;
183 scroll_screen(sr
, nr
, n
);
186 static void delete_lines(int n
)
188 int r
= MAX(top
, row
);
190 int nr
= bot
- r
- n
;
192 scroll_screen(sr
, nr
, -n
);
195 static void move_cursor(int r
, int c
)
199 t
= origin() ? top
: 0;
200 b
= origin() ? bot
: pad_rows();
201 row
= MAX(t
, MIN(r
, b
- 1));
202 col
= MAX(0, MIN(c
, pad_cols() - 1));
206 static void advance(int dr
, int dc
, int scrl
)
210 if (c
>= pad_cols()) {
211 if (!scrl
|| (mode
& MODE_NOWRAP
)) {
218 if (r
>= bot
&& scrl
) {
220 int nr
= (bot
- top
) + n
;
221 scroll_screen(top
+ -n
, nr
, n
);
223 if (r
< top
&& scrl
) {
225 int nr
= (bot
- top
) - n
;
226 scroll_screen(top
, nr
, n
);
228 r
= MIN(bot
- 1, MAX(top
, r
));
229 move_cursor(r
, MAX(0, c
));
232 void term_send(int c
)
234 unsigned char b
= (unsigned char) c
;
236 write(term
->fd
, &b
, 1);
239 void term_sendstr(char *s
)
242 write(term
->fd
, s
, strlen(s
));
245 static void setmode(int m
)
258 if (m
>= 30 && m
<= 37)
260 if (m
>= 40 && m
<= 47)
264 static void kill_chars(int sc
, int ec
)
267 for (i
= sc
; i
< ec
; i
++)
268 lazy_put(' ', row
, i
);
272 static void move_chars(int sc
, int nc
, int n
)
275 memmove(SQRADDR(row
, sc
+ n
), SQRADDR(row
, sc
),
276 nc
* sizeof(*screen
));
278 memset(SQRADDR(row
, sc
), 0, n
* sizeof(*screen
));
280 memset(SQRADDR(row
, pad_rows() + n
), 0, -n
* sizeof(*screen
));
281 lazy_drawcols(row
, MIN(sc
, sc
+ n
), pad_cols());
285 static void delete_chars(int n
)
287 move_chars(col
+ n
, pad_cols(), -n
);
290 static void insert_chars(int n
)
292 int nc
= pad_cols() - col
- n
;
293 move_chars(col
, nc
, n
);
296 static void term_blank(void)
298 memset(screen
, 0, MAXCHARS
* sizeof(*screen
));
305 static void ctlseq(void);
310 while (ptycur
< ptylen
)
316 void term_exec(char *cmd
)
319 if ((term
->pid
= forkpty(&term
->fd
, NULL
, NULL
, NULL
)) == -1) {
320 perror("failed to fork");
325 setenv("TERM", "linux", 1);
326 execlp(cmd
, cmd
, NULL
);
329 fcntl(term
->fd
, F_SETFD
, fcntl(term
->fd
, F_GETFD
) | FD_CLOEXEC
);
330 fcntl(term
->fd
, F_SETFL
, fcntl(term
->fd
, F_GETFL
) | O_NONBLOCK
);
336 static void misc_save(struct term_state
*state
)
347 static void misc_load(struct term_state
*state
)
358 void term_save(struct term
*term
)
361 misc_save(&term
->cur
);
364 void term_load(struct term
*t
, int flags
)
367 misc_load(&term
->cur
);
368 screen
= term
->screen
;
370 if (term
->fd
&& flags
== TERM_REDRAW
) {
371 lazy_draw(0, pad_rows());
374 if (!term
->fd
&& flags
)
387 void set_region(int t
, int b
)
389 top
= MIN(pad_rows(), MAX(0, t
- 1));
390 bot
= MIN(pad_rows(), MAX(0, b
? b
: pad_rows()));