1 /* See LICENSE for licence details. */
20 #include <sys/ioctl.h>
21 #include <sys/select.h>
24 #include <sys/types.h>
34 ////////////////////////////////////////////////////////////////////////////////
40 # define K8TERM_EXTERN extern
44 ////////////////////////////////////////////////////////////////////////////////
46 #define K8T_ESC_TITLE_SIZ (4096)
47 #define K8T_ESC_BUF_SIZ (256)
48 #define K8T_ESC_ARG_SIZ (16)
49 #define K8T_DRAW_BUF_SIZ (2048)
50 #define K8T_UTF_SIZ (4)
51 #define K8T_OBUFSIZ (256)
52 #define K8T_WBUFSIZ (256)
55 ////////////////////////////////////////////////////////////////////////////////
56 /* misc utility macros */
60 #define K8T_MAX(__a,__b) \
61 ({ typeof(__a)_a = (__a); \
62 typeof(__b)_b = (__b); \
68 #define K8T_MIN(__a,__b) \
69 ({ typeof(__a)_a = (__a); \
70 typeof(__b)_b = (__b); \
73 #define K8T_ARRLEN(a) (sizeof(a)/sizeof(a[0]))
74 #define K8T_DEFAULT(a, b) (a) = ((a) ? (a) : (b))
75 #define K8T_BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b))
76 #define K8T_LIMIT(x, a, b) ((x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x))
77 #define K8T_ATTRCMP(a, b) ((a).attr != (b).attr || (a).fg != (b).fg || (a).bg != (b).bg)
78 #define K8T_ISSET(_tr,flag) ((_tr)->mode&(flag))
79 #define K8T_X2COL(x) ((x)/xw.cw)
80 #define K8T_Y2ROW(_tr, y) ((y-(opt_tabposition==1 ? xw.tabheight : 0))/xw.ch-((_tr) != NULL ? (_tr)->topline : 0))
81 #define K8T_ISGFX(mode) ((mode)&K8T_ATTR_GFX)
84 ////////////////////////////////////////////////////////////////////////////////
86 K8T_BELL_AUDIO
= 0x01,
87 K8T_BELL_URGENT
= 0x02
90 // glyph attributes (bitmask)
93 K8T_ATTR_REVERSE
= 0x01,
94 K8T_ATTR_UNDERLINE
= 0x02,
97 K8T_ATTR_DEFFG
= 0x10,
98 K8T_ATTR_DEFBG
= 0x20,
101 // cursor operations for k8t_tmCursor()
107 // cursor state (bitmask)
109 K8T_CURSOR_DEFAULT
= 0x00,
110 K8T_CURSOR_HIDE
= 0x01,
111 K8T_CURSOR_WRAPNEXT
= 0x02
114 // glyph state (bitmask)
116 K8T_GLYPH_SET
= 0x01, /* for selection only */
117 K8T_GLYPH_DIRTY
= 0x02,
118 K8T_GLYPH_WRAP
= 0x10, /* can be set for the last line glyph */
121 // terminal mode flags (bitmask)
123 K8T_MODE_WRAP
= 0x01,
124 K8T_MODE_INSERT
= 0x02,
125 K8T_MODE_APPKEYPAD
= 0x04,
126 K8T_MODE_ALTSCREEN
= 0x08,
127 K8T_MODE_CRLF
= 0x10,
128 K8T_MODE_MOUSEBTN
= 0x20,
129 K8T_MODE_MOUSEMOTION
= 0x40,
130 K8T_MODE_MOUSE
= 0x20|0x40,
131 K8T_MODE_REVERSE
= 0x80,
132 K8T_MODE_BRACPASTE
= 0x100,
133 K8T_MODE_FOCUSEVT
= 0x200,
134 K8T_MODE_DISPCTRL
= 0x400, //TODO: not implemented yet
135 K8T_MODE_GFX0
= 0x1000,
136 K8T_MODE_GFX1
= 0x2000,
139 // escape sequence processor state
141 K8T_ESC_START
= 0x01,
144 K8T_ESC_TITLE
= 0x08,
145 K8T_ESC_ALTCHARSET
= 0x10,
147 K8T_ESC_PERCENT
= 0x40,
148 K8T_ESC_ALTG1
= 0x80,
153 K8T_MOUSE_STATE_SHIFT
= 0x01,
154 K8T_MOUSE_STATE_CTRL
= 0x02,
155 K8T_MOUSE_STATE_ALT
= 0x04,
156 K8T_MOUSE_STATE_WIN
= 0x08
160 K8T_MOUSE_BUTTON_LEFT
= 1,
161 K8T_MOUSE_BUTTON_MIDDLE
= 2,
162 K8T_MOUSE_BUTTON_RIGHT
= 3
166 K8T_MOUSE_EVENT_MOTION
= -1,
167 K8T_MOUSE_EVENT_UP
= 0,
168 K8T_MOUSE_EVENT_DOWN
= 1
172 ////////////////////////////////////////////////////////////////////////////////
173 typedef int64_t K8TTimeMSec
;
174 typedef struct K8Term K8Term
;
177 typedef struct __attribute__((packed
)) {
179 union __attribute__((packed
)) {
183 uint8_t attr
; /* attribute flags */
184 uint16_t fg
; /* foreground */
185 uint16_t bg
; /* background */
186 uint8_t state
; /* state flags */
189 typedef K8TGlyph
*K8TLine
;
193 K8TGlyph attr
; /* current char attributes */
200 /* CSI Escape sequence structs */
201 /* ESC '[' [[ [<priv>] <arg> [;]] <mode>] */
203 char buf
[K8T_ESC_BUF_SIZ
]; /* raw string */
204 int len
; /* raw string length */
206 int arg
[K8T_ESC_ARG_SIZ
];
207 int narg
; /* nb of args */
212 /* TODO: use better name for vars... */
217 struct { int x
, y
; } b
, e
;
224 /* Internal representation of the screen */
226 // unicode conversion map
229 int cmdfd
; // for tty i/o
230 int dead
; // !0: don't do tty i/o
232 int needConv
; /* 0: utf-8 locale */
239 int curbhidden
; // 0: visible; <0: should be hidden; >0: already hidden
240 K8TTimeMSec lastBlinkTime
;
241 int curblinkinactive
;
243 int row
; /* nb row */
244 int col
; /* nb col */
245 int topline
; /* top line for drawing (0: no history; 1: show one history line; etc) */
246 int linecount
; /* full, with history */
247 int maxhistory
; /* max history lines; 0: none; <0: infinite */
248 K8TLine
*line
; /* screen */
249 K8TLine
*alt
; /* alternate screen */
250 char *dirty
; /* dirtyness of lines */
251 K8TCursor c
; /* cursor */
252 int top
; /* top scroll limit */
253 int bot
; /* bottom scroll limit */
254 int mode
; /* terminal mode flags */
255 int mousemode
; /* mouse mode: 1000, 1005, 1006, 1015 */
256 int esc
; /* escape state flags */
257 int charset
; /* K8T_MODE_GFX0 or K8T_MODE_GFX1 */
260 K8TCursor csaved
; /* saved cursor info */
261 // old cursor position
265 char title
[K8T_ESC_TITLE_SIZ
+1];
272 char obuf
[K8T_OBUFSIZ
];
275 char ubuf
[K8T_UTF_SIZ
];
278 char drawbuf
[K8T_DRAW_BUF_SIZ
];
280 char wrbuf
[K8T_WBUFSIZ
];
287 K8TTimeMSec lastDrawTime
;
290 int defboldfg
, defunderfg
;
291 int defcurfg
, defcurbg
;
292 int defcurinactivefg
, defcurinactivebg
;
296 K8TTimeMSec lastActiveTime
;
304 K8TTimeMSec (*clockTicks
) (K8Term
*term
);
305 void (*setLastDrawTime
) (K8Term
*term
, K8TTimeMSec time
);
306 // locale conversions
307 // returns new length
308 int (*isConversionNecessary
) (K8Term
*term
);
309 int (*loc2utf
) (K8Term
*term
, char *dest
, const char *src
, int len
);
310 int (*utf2loc
) (K8Term
*term
, char *dest
, const char *src
, int len
);
312 int (*isFocused
) (K8Term
*term
); // used to draw various cursor shapes, for example
313 int (*isVisible
) (K8Term
*term
); // at least partially
315 void (*drawSetFG
) (K8Term
*term
, int clr
);
316 void (*drawSetBG
) (K8Term
*term
, int clr
);
318 void (*drawRect
) (K8Term
*term
, int x0
, int y0
, int cols
, int rows
); // use FG
319 void (*drawFillRect
) (K8Term
*term
, int x0
, int y0
, int cols
, int rows
); // use FG
320 void (*drawCopyArea
) (K8Term
*term
, int x0
, int y0
, int cols
, int rows
); // copy pixmap to screen
321 void (*drawString
) (K8Term
*term
, int x
, int y
, int cols
, const K8TGlyph
*base
, int fontset
, const char *s
, int bytelen
);
322 //TODO: FIX OVERLAY SYSTEM!
323 // check and draw overlay, return 1 to stop built-in drawing
324 int (*drawOverlay
) (K8Term
*term
, int x0
, int x1
, int scry
, int lineno
, int dontcopy
);
326 void (*fixSelection
) (K8Term
*term
);
327 void (*clearSelection
) (K8Term
*term
);
329 void (*titleChanged
) (K8Term
*term
);
330 void (*doBell
) (K8Term
*term
);
332 int (*isUnderOverlay
) (K8Term
*term
, int x
, int y
, int w
); // 0: none; 1: fully; -1: partially
333 void (*clipToOverlay
) (K8Term
*term
, int *x0
, int y
, int *w
); // if w < 1: completely out of
337 ////////////////////////////////////////////////////////////////////////////////
338 K8TERM_EXTERN
void k8t_tmWantRedraw (K8Term
*term
, int forceFast
);
339 K8TERM_EXTERN
void k8t_tmDirtyMark (K8Term
*term
, int lineno
, int flag
);
340 K8TERM_EXTERN
void k8t_selInit (K8Term
*term
);
341 K8TERM_EXTERN
void k8t_selHide (K8Term
*term
);
342 K8TERM_EXTERN
int k8t_isSelected (K8Term
*term
, int x
, int y
);
343 K8TERM_EXTERN
void k8t_mouseReport (K8Term
*term
, int x
, int y
, int event
, int button
, int state
);
344 K8TERM_EXTERN
void k8t_selXSet (K8Term
*term
, char *str
);
345 K8TERM_EXTERN
void k8t_selClear (K8Term
*term
);
346 K8TERM_EXTERN K8TLine
k8t_selGet (K8Term
*term
, int y
);
347 K8TERM_EXTERN
void k8t_selCopy (K8Term
*term
);
348 K8TERM_EXTERN
void k8t_dbgCSIDump (K8Term
*term
);
349 K8TERM_EXTERN
void k8t_tmResetAttrs (K8Term
*term
);
350 K8TERM_EXTERN
void k8t_tmSetAttr (K8Term
*term
, int *attr
, int l
);
351 K8TERM_EXTERN
int k8t_tmDoWrap (K8Term
*term
);
352 K8TERM_EXTERN
void k8t_tmCSIHandle (K8Term
*term
);
353 K8TERM_EXTERN
void k8t_tmCSIReset (K8Term
*term
);
354 K8TERM_EXTERN
void k8t_tmCSIParse (K8Term
*term
);
355 K8TERM_EXTERN
void k8t_tmPutTab (K8Term
*term
);
356 K8TERM_EXTERN
int k8t_tmPutCtrl (K8Term
*term
, char ascii
);
357 K8TERM_EXTERN
void k8t_tmPutC (K8Term
*term
, const char *c
);
358 K8TERM_EXTERN
int k8t_ttyCanRead (K8Term
*term
);
359 K8TERM_EXTERN
int k8t_ttyCanWrite (K8Term
*term
);
360 K8TERM_EXTERN
int k8t_ttyRead (K8Term
*term
);
361 K8TERM_EXTERN
void k8t_ttyFlushWriteBuf (K8Term
*term
);
362 K8TERM_EXTERN
int k8t_ttyWriteRawChar (K8Term
*term
, const char *s
, int len
, int noenc
);
363 K8TERM_EXTERN
void k8t_ttyWriteNoEnc (K8Term
*term
, const char *s
, size_t n
);
364 K8TERM_EXTERN
void k8t_ttyWrite (K8Term
*term
, const char *s
, size_t n
);
365 K8TERM_EXTERN
void k8t_tmDirty (K8Term
*term
, int top
, int bot
);
366 K8TERM_EXTERN
void k8t_tmFullDirty (K8Term
*term
);
367 K8TERM_EXTERN
void k8t_tmMoveTo (K8Term
*term
, int x
, int y
);
368 K8TERM_EXTERN
void k8t_tmClearRegion (K8Term
*term
, int x1
, int y1
, int x2
, int y2
);
369 K8TERM_EXTERN
void k8t_tmCursor (K8Term
*term
, int mode
);
370 K8TERM_EXTERN
void k8t_tmAdjMaxHistory (K8Term
*term
, int maxh
);
371 K8TERM_EXTERN
void k8t_tmSwapScreen (K8Term
*term
);
372 K8TERM_EXTERN
void k8t_tmScrollSelection (K8Term
*term
, int orig
, int n
, int tohistory
);
373 K8TERM_EXTERN
void k8t_tmScrollDown (K8Term
*term
, int orig
, int n
);
374 K8TERM_EXTERN
void k8t_tmScrollUp (K8Term
*term
, int orig
, int n
, int tohistory
);
375 K8TERM_EXTERN
void k8t_tmCharWrap (K8Term
*term
, int y
, int wrap
);
376 K8TERM_EXTERN
void k8t_tmNewLine (K8Term
*term
, int first_col
);
377 K8TERM_EXTERN
void k8t_tmSetChar (K8Term
*term
, const char *c
);
378 K8TERM_EXTERN
void k8t_tmDeleteChar (K8Term
*term
, int n
);
379 K8TERM_EXTERN
void k8t_tmInsertBlank (K8Term
*term
, int n
);
380 K8TERM_EXTERN
void k8t_tmInsertBlankLine (K8Term
*term
, int n
);
381 K8TERM_EXTERN
void k8t_tmDeleteLine (K8Term
*term
, int n
);
382 K8TERM_EXTERN
void k8t_tmSetScrollRegion (K8Term
*term
, int t
, int b
);
383 K8TERM_EXTERN
void k8t_tmUnshowHistory (K8Term
*term
);
384 K8TERM_EXTERN
void k8t_tmSendFocusEvent (K8Term
*term
, int focused
);
385 K8TERM_EXTERN
void k8t_tmResetMode (K8Term
*term
);
386 K8TERM_EXTERN
void k8t_tmReset (K8Term
*term
);
387 K8TERM_EXTERN
int k8t_tmInitialize (K8Term
*term
, int col
, int row
, int maxhistory
);
388 K8TERM_EXTERN
int k8t_tmResize (K8Term
*term
, int col
, int row
);
389 K8TERM_EXTERN
void k8t_ttyResize (K8Term
*term
);
390 K8TERM_EXTERN
int k8t_UTF8Decode (uint32_t *u
, const void *buf
);
391 K8TERM_EXTERN
int k8t_UTF8Encode (void *buf
, uint32_t uc
);
392 K8TERM_EXTERN
int k8t_UTF8IsFull (const void *buf
, int buflen
);
393 K8TERM_EXTERN
int k8t_UTF8Size (const void *buf
);
394 K8TERM_EXTERN
int k8t_UTF8strlen (const char *s
);
395 K8TERM_EXTERN
void k8t_UTF8ChopLast (char *s
);
396 K8TERM_EXTERN
void k8t_drawLine (K8Term
*term
, int x1
, int x2
, int scry
, int lineno
, int dontcopy
);
397 K8TERM_EXTERN
void k8t_drawRegion (K8Term
*term
, int x1
, int y1
, int x2
, int y2
, int forced
);
398 K8TERM_EXTERN
void k8t_drawTerm (K8Term
*term
, int forced
);
399 K8TERM_EXTERN
void k8t_drawCursor (K8Term
*term
, int forceblit
);
400 K8TERM_EXTERN
void k8t_drawString (K8Term
*term
, const char *s
, const K8TGlyph
*base
, int x
, int y
, int charlen
, int bytelen
);
401 K8TERM_EXTERN
void k8t_drawClear (K8Term
*term
, int x1
, int y1
, int x2
, int y2
);
402 K8TERM_EXTERN
void k8t_drawCopy (K8Term
*term
, int x
, int y
, int cols
, int rows
);
405 static inline void k8t_ttyWriteStr (K8Term
*term
, const char *s
) { if (s
!= NULL
&& s
[0]) k8t_ttyWrite(term
, s
, strlen(s
)); }
406 static inline void k8t_ttyWriteStrNoEnc (K8Term
*term
, const char *s
) { if (s
!= NULL
&& s
[0]) k8t_ttyWriteNoEnc(term
, s
, strlen(s
)); }
409 static inline void k8t_ttyPutStr (K8Term
*term
, const char *s
) { if (s
!= NULL
) while (*s
) { k8t_tmPutC(term
, s
); ++s
; } }
412 ////////////////////////////////////////////////////////////////////////////////
413 K8TERM_API
void k8t_die (const char *errstr
, ...) __attribute__((noreturn
)) __attribute__((format(printf
,1,2)));