blob: 5a35a5f0f4ad09d21a01cba344e62d7f47e9831d [file] [log] [blame]
adamdunkelsb9614dc2004-08-09 20:33:51 +00001#include "libconio.h"
2#include "ctk-term-int.h"
3#include <string.h>
4#include <stdio.h> // sprintf
5
6#define PRINTF(x)
7
8/*-----------------------------------------------------------------------------------*/
9/*
10 * #defines and enums
11 */
12/*-----------------------------------------------------------------------------------*/
13
14#define CHARS_WIDTH LIBCONIO_CONF_SCREEN_WIDTH
15#define CHARS_HEIGHT LIBCONIO_CONF_SCREEN_HEIGHT
16
17/*-----------------------------------------------------------------------------------*/
18/*
19 * Local variables
20 */
21/*-----------------------------------------------------------------------------------*/
22
23/* ANSI/VT100 colors
24 0 - None
25 1 - Bold (inc. inten)
26 4 - Underscore
27 7 - Reverse
28 x0 - black
29 x1 - red
30 x2 - green
31 x3 - yellow
32 x4 - blue
33 x5 - magenta
34 x6 - cyan
35 x7 - white
36 x = 3 fg x = 4 bg
37*/
38#if 0 /* Colorfull theme */
39static const char backgroundcolor[] = "\033[0;37;40m";
40
41static const char wincol[] = "\033[0;37;40m";
42static const char wincol_f[] = "\033[0;1;37;40m";
43static const char wincol_d[] = "\033[0;30;47m";
44
45static const char sepcol[] = "\033[0;37;40m";
46static const char sepcol_f[] = "\033[0;1;37;40m";
47static const char sepcol_d[] = "\033[0;30;47m";
48
49static const char labcol[] = "\033[0;37;40m";
50static const char labcol_f[] = "\033[1;37;40m";
51static const char labcol_d[] = "\033[0;30;47m";
52
53static const char butcol[] = "\033[0;37;40m";
54static const char butcol_w[] = "\033[0;30;47m";
55static const char butcol_f[] = "\033[0;1;37;40m";
56static const char butcol_fw[] = "\033[0;1;37;46m";
57static const char butcol_d[] = "\033[0;30;47m";
58static const char butcol_dw[] = "\033[0;37;46m";
59
60static const char hlcol[] = "\033[0;4;36;40m";
61static const char hlcol_w[] = "\033[0;4;30;47m";
62static const char hlcol_f[] = "\033[0;1;4;36;40m";
63static const char hlcol_fw[] = "\033[0;1;4;37;46m";
64static const char hlcol_d[] = "\033[0;4;34;47m";
65static const char hlcol_dw[] = "\033[0;4;37;46m";
66
67static const char iconcol[] = "\033[0;32;40m";
68static const char iconcol_w[] = "\033[0;30;42m";
69
70static const char menucolor[] = "\033[0;37;43m";
71static const char activemenucolor[] = "\033[0;1;37;43m";
72#endif
73
74#if 1 /* B/W theme */
75static const char backgroundcolor[] = "\033[0m";
76
77static const char wincol[] = "\033[0m";
78static const char wincol_f[] = "\033[0;1m";
79static const char wincol_d[] = "\033[0;7m";
80
81static const char sepcol[] = "\033[0m";
82static const char sepcol_f[] = "\033[0;1m";
83static const char sepcol_d[] = "\033[0;7m";
84
85static const char labcol[] = "\033[0m";
86static const char labcol_f[] = "\033[0;1m";
87static const char labcol_d[] = "\033[0;7m";
88
89static const char butcol[] = "\033[0m";
90static const char butcol_w[] = "\033[0m";
91static const char butcol_f[] = "\033[0;1m";
92static const char butcol_fw[] = "\033[0;1;7m";
93static const char butcol_d[] = "\033[0;7m";
94static const char butcol_dw[] = "\033[0m";
95
96static const char hlcol[] = "\033[0;4m";
97static const char hlcol_w[] = "\033[0;4;7m";
98static const char hlcol_f[] = "\033[0;1;4m";
99static const char hlcol_fw[] = "\033[0;1;4;7m";
100static const char hlcol_d[] = "\033[0;4;7m";
101static const char hlcol_dw[] = "\033[0;4m";
102
103static const char iconcol[] = "\033[0m";
104static const char iconcol_w[] = "\033[0;7m";
105
106static const char menucolor[] = "\033[0;7m";
107static const char activemenucolor[] = "\033[0m";
108
109#endif
110
111static const char* const colortheme[] =
112{
113 backgroundcolor,
114
115 /* Window colors */
116 wincol, wincol, wincol_f, wincol_f, wincol_d, wincol_d,
117
118 /* Separator colors. */
119 sepcol, sepcol, sepcol_f, sepcol_f, sepcol_d, sepcol_d,
120
121 /* Label colors. */
122 labcol, labcol, labcol_f, labcol_f, labcol_d, labcol_d,
123
124 /* Button colors. */
125 butcol, butcol_w, butcol_f, butcol_fw, butcol_d, butcol_dw,
126
127 /* Hyperlink colors. */
128 hlcol, hlcol_w, hlcol_f, hlcol_fw, hlcol_d, hlcol_dw,
129
130 /* Textentry colors. */
131 butcol, butcol_w, butcol_f, butcol_fw, butcol_d, butcol_dw,
132
133 /* Icon colors */
134 iconcol, iconcol_w, iconcol, iconcol_w, iconcol, iconcol_w,
135
136 /* Menu colors. */
137 menucolor, activemenucolor, activemenucolor
138 };
139
140static unsigned char
141 screen[CHARS_WIDTH * CHARS_HEIGHT],
142 colorscreen[CHARS_WIDTH * CHARS_HEIGHT];
143
144/*-----------------------------------------------------------------------------------*/
145/*
146 * Add a character to the screen buffer
147 */
148/*-----------------------------------------------------------------------------------*/
149void
150ctk_term_out_update_screen(unsigned char xpos,
151 unsigned char ypos,
152 unsigned char c,
153 unsigned char color)
154{
155 if (c < 0x20) c = 0x20;
156 screen[xpos + ypos * CHARS_WIDTH] = c;
157 colorscreen[xpos + ypos * CHARS_WIDTH] = color;
158}
159
160/*-----------------------------------------------------------------------------------*/
161/*
162 * Check if there are any updated pending. If so, make the first one current
163 */
164/*-----------------------------------------------------------------------------------*/
165static void
166check_updates(struct ctk_term_state* ts)
167{
168 if (ts->updates_current != NULL) return;
169 ts->updates_current = ctk_term_update_dequeue(ts);
170 if (ts->updates_current != NULL) {
171 ts->x = ts->updates_current->x;
172 ts->y = ts->updates_current->y;
173 ts->w = ts->updates_current->w;
174 ts->h = ts->updates_current->h;
175 ts->x1 = ts->x2 = ts->x;
176 ts->y1 = ts->y2 = ts->y;
177 }
178}
179
180/*-----------------------------------------------------------------------------------*/
181/** \internal
182 * Adds a cursor position change to buffer. Returns 0 if string doesn't fit else
183 * number of bytes actually written is returned.
184 *
185 * \param x X coordinate (screen coordinates)
186 * \param y Y coordinate (screen coordinates)
187 * \param buf Output buffer
188 * \param maxlen Maximum number of bytes to store in buffer
189 */
190/*-----------------------------------------------------------------------------------*/
191static unsigned short
192move_to(unsigned char x, unsigned char y, unsigned char* buf, unsigned short maxlen)
193{
194 if (maxlen < 14) return 0;
195 return (unsigned short)sprintf((char*)buf, "\033[%d;%dH", y+1, x+1);
196}
197
198/*-----------------------------------------------------------------------------------*/
199/** \internal
200 * Adds a attribute string to buffer. Returns 0 if string doesn't fit else
201 * number of bytes actually written is returned.
202 *
203 * \param c Color number
204 * \param buf Output buffer
205 * \param maxlen Maximum number of bytes to store in buffer
206 */
207/*-----------------------------------------------------------------------------------*/
208static unsigned short
209set_color(unsigned char c, unsigned char* buf, unsigned short maxlen)
210{
211 int len = strlen((const char*)colortheme[c]);
212 if (maxlen < len) return 0;
213 memcpy(buf, colortheme[c], len);
214 return len;
215}
216
217/*-----------------------------------------------------------------------------------*/
218/**
219 * Stores terminal data in buffer provided by caller. Returns number of bytes written
220 * to the output buffer.
221 *
222 * \param ts State information
223 * \param buf Output buffer
224 * \param maxlen Maximum number of bytes to store in buffer
225 */
226/*-----------------------------------------------------------------------------------*/
227unsigned short
228ctk_term_send(struct ctk_term_state* ts,
229 unsigned char* buf,
230 unsigned short maxlen)
231{
232 unsigned char x, y, x0;
233 unsigned char col, c;
234 unsigned short tmp;
235 unsigned short totlen;
236
237 check_updates(ts);
238
239 if (ts->updates_current == NULL) return 0;
240
241 x0 = ts->x1;
242 col = ts->c1;
243 totlen = 0;
244 /* Loop across the update region starting at (x1,y1) */
245 for(y = ts->y1; y < ts->y + ts->h; ++y) {
246 for(x = x0; x < ts->x + ts->w; ++x) {
247 /* New line ? */
248 if (x == ts->x) {
249 /* Move cursor to start of line */
250 tmp = move_to(x,y,buf,maxlen);
251 if (tmp == 0) goto loopend;
252 buf += tmp;
253 totlen += tmp;
254 maxlen -= tmp;
255 }
256 /* Check color */
257 c = colorscreen[x + y * CHARS_WIDTH];
258 if (c != col) {
259 PRINTF(("colorchange at (%d, %d) to %d\n", x,y,c));
260 /* Send new color information */
261 tmp = set_color(c, buf, maxlen);
262 if (tmp == 0) goto loopend;
263 col = c;
264 buf += tmp;
265 totlen += tmp;
266 maxlen -= tmp;
267 }
268 /* Check remaining space */
269 if (maxlen < 1) goto loopend;
270 /* Add character */
271 *buf = screen[x + y * CHARS_WIDTH];
272 buf++;
273 maxlen--;
274 totlen++;
275 }
276 x0 = ts->x;
277 }
278loopend:
279 /* Always save current color state */
280 ts->c2 = col;
281 PRINTF(("ending loop at (%d, %d)\n", x,y));
282 /* Check if done */
283 if (x == ts->x+ts->w && y == ts->y+ts->h) {
284 /* Signal done with this update */
285 ts->x2 = ts->y2 = 0;
286 }
287 else {
288 /* Not done. Save state */
289 ts->x2 = x;
290 ts->y2 = y;
291 }
292 return totlen;
293}
294
295/*-----------------------------------------------------------------------------------*/
296/**
297 * Called by client when the data returned by ctk_term_send() are successfully sent.
298 *
299 * \param ts State information
300 */
301/*-----------------------------------------------------------------------------------*/
302void ctk_term_sent(struct ctk_term_state* ts)
303{
304 if (ts->updates_current != NULL) {
305 /* Check if current update done */
306 if (ts->x2 == 0 && ts->y2 == 0) {
307 /* Yes, free it */
308 ctk_term_update_free(ts, ts->updates_current);
309 ts->updates_current = NULL;
310 }
311 else {
312 /* Nop. Update start posititions */
313 ts->x1 = ts->x2;
314 ts->y1 = ts->y2;
315 }
316 ts->c1 = ts->c2;
317 }
318}