1 /*
2  * Terminal-handling definitions common to the interpreter and edlis.
3  * This also includes some presentation-related functions, e.g. syntax highlighting.
4  *
5  * There are two relevant library layers here:
6  * 1. Curses is high-level, but only appropriate for fullscreen programs
7  * 2. Terminfo is lower-level (curses is built on it)
8  *
9  * I only considered standardized libraries (e.g. X/Open).
10  */
11 
12 #ifndef TERM_H
13 #define TERM_H
14 
15 #include <ncurses.h>
16 #ifndef FULLSCREEN
17 #include <term.h>
18 #endif
19 
20 struct position {
21     int             row;
22     int             col;
23 };
24 
25 // special charactor
26 #define EOL '\n'
27 #define RET '\r'
28 #define TAB '\t'
29 #define SPACE ' '
30 #define ESC 27
31 static const char NUL = '\0';
32 static const char BEL = '\a';
33 static const char BS = '\b';
34 #define DEL 127
35 
36 #ifndef FULLSCREEN
37 #define ARROW_PREFIX '['
38 extern char     ed_key_down;
39 extern char     ed_key_left;
40 extern char     ed_key_right;
41 extern char     ed_key_up;
42 #endif
43 
44 #ifdef FULLSCREEN
45 /*
46  * Edlis uses the higher-level curses interface
47  */
48 
49 __dead void     errw(const char *msg);
50 #define CHECK(fn, ...) { \
51         if ((fn)(__VA_ARGS__) == ERR) { \
52                 errw(#fn); \
53         } \
54 }
55 
56 static inline void
ESCHOME(void)57 ESCHOME(void)
58 {
59     CHECK(move, 0, 0);
60 }
61 
62 static inline void
ESCTOP(void)63 ESCTOP(void)
64 {
65     CHECK(move, 1, 0);
66 }
67 
68 static inline void
ESCCLS(void)69 ESCCLS(void)
70 {
71     CHECK(clear);
72 }
73 
74 static inline void
ESCCLS1(void)75 ESCCLS1(void)
76 {
77     CHECK(clrtobot);
78 }
79 
80 static inline void
ESCCLSL(void)81 ESCCLSL(void)
82 {
83     CHECK(clrtoeol);
84 }
85 
86 static inline void
ESCMVLEFT(int x)87 ESCMVLEFT(int x)
88 {
89     int             dummy,
90                     cur_y;
91 
92     getyx(stdscr, cur_y, dummy);
93     CHECK(move, cur_y, x - 1);
94 }
95 
96 static inline void
ESCCLSLA(void)97 ESCCLSLA(void)
98 {
99     ESCMVLEFT(1);
100     CHECK(clrtoeol);
101 }
102 
103 static inline void
ESCMOVE(int y,int x)104 ESCMOVE(int y, int x)
105 {
106     CHECK(move, y - 1, x - 1);
107 }
108 
109 static inline void
ESCFORG(void)110 ESCFORG(void)
111 {
112     if (has_colors()) {
113 	CHECK(color_set, 0, NULL);
114     }
115 }
116 
117 enum Color { RED_ON_DFL =
118 	1, YELLOW_ON_DFL, BLUE_ON_DFL, MAGENTA_ON_DFL, CYAN_ON_DFL,
119     DFL_ON_CYAN,
120 };
121 static inline void
ESCBCYAN(void)122 ESCBCYAN(void)
123 {
124     if (has_colors()) {
125 	CHECK(color_set, DFL_ON_CYAN, NULL);
126     }
127 }
128 
129 static inline void
ESCBORG(void)130 ESCBORG(void)
131 {
132     if (has_colors()) {
133 	CHECK(color_set, 0, NULL);
134     }
135 }
136 
137 static inline void
ESCREV(void)138 ESCREV(void)
139 {
140     CHECK(attron, A_REVERSE);
141 }
142 
143 static inline void
ESCRST(void)144 ESCRST(void)
145 {
146     CHECK(attrset, A_NORMAL);
147 }
148 
149 static inline void
ESCBOLD(void)150 ESCBOLD(void)
151 {
152     CHECK(attron, A_BOLD);
153 }
154 #else
155 /*
156  * The REPL uses the lower-level terminfo interface because we don't want
157  * to clear the screen
158  */
159 
160 static inline void
ESCCLSL(void)161 ESCCLSL(void)
162 {
163     putp(clr_eol);
164 }
165 
166 static inline void
ESCMVLEFT(int x)167 ESCMVLEFT(int x)
168 {
169     putp(tparm(column_address, x - 1));
170 }
171 
172 static inline void
ESCMVU(void)173 ESCMVU(void)
174 {
175     putp(cursor_up);
176 }
177 
178 static inline void
ESCSCR(void)179 ESCSCR(void)
180 {
181     putp(scroll_forward);
182 }
183 
184 static inline void
ESCFORG(void)185 ESCFORG(void)
186 {
187     putp(exit_attribute_mode);
188 }
189 
190 static inline void
ESCBCYAN(void)191 ESCBCYAN(void)
192 {
193     putp(tparm(set_a_background, COLOR_CYAN));
194 }
195 
196 static inline void
ESCBORG(void)197 ESCBORG(void)
198 {
199     putp(exit_attribute_mode);
200 }
201 
202 static inline void
ESCREV(void)203 ESCREV(void)
204 {
205     putp(enter_reverse_mode);
206 }
207 
208 static inline void
ESCRST(void)209 ESCRST(void)
210 {
211     putp(exit_attribute_mode);
212 }
213 
214 static inline void
ESCBOLD(void)215 ESCBOLD(void)
216 {
217     putp(enter_bold_mode);
218 }
219 #endif
220 
221 enum HighlightToken { HIGHLIGHT_NONE, HIGHLIGHT_SYNTAX, HIGHLIGHT_BUILTIN,
222     HIGHLIGHT_STRING, HIGHLIGHT_COMMENT, HIGHLIGHT_EXTENDED,
223     HIGHLIGHT_MULTILINE_COMMENT,
224 };
225 enum HighlightToken maybe_match(const char *str);
226 bool            in_special_table(const char *str);
227 void            gather_fuzzy_matches(const char *str,
228 				     const char *candidates[],
229 				     int *candidate_pt);
230 #define COMPLETION_CANDIDATES_MAX 50
231 
232 #endif
233