1 /*
2 *
3 * Copyright (C) 2007 Uwe Hermann <[email protected]>
4 * Copyright (C) 2008 Ulf Jordan <[email protected]>
5 * Copyright (C) 2008-2009 coresystems GmbH
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 /*
32 * This is a tiny implementation of the (n)curses library intended to be
33 * used in embedded/firmware/BIOS code where no libc or operating system
34 * environment is available and code size is very important.
35 *
36 * Design goals:
37 * - Small object code.
38 * - Self-contained.
39 * - Doesn't require a libc (no glibc/uclibc/dietlibc/klibc/newlib).
40 * - Works without any other external libraries or header files.
41 * - Works without an underlying operating system.
42 * - Doesn't use files, signals, syscalls, ttys, library calls, etc.
43 * - Doesn't do any dynamic memory allocation (no malloc() and friends).
44 * - All data structures are statically allocated.
45 * - Supports standard VGA console (80x25) and serial port console.
46 * - This includes character output and keyboard input over serial.
47 * - Supports beep() through a minimal PC speaker driver.
48 *
49 * Limitations:
50 * - Only implements a small subset of the (n)curses functions.
51 * - Only implements very few sanity checks (for smaller code).
52 * - Thus: Don't do obviously stupid things in your code.
53 * - Doesn't implement the 'form', 'panel', and 'menu' extensions.
54 * - Only implements C bindings (no C++, Ada95, or others).
55 * - Doesn't include wide character support.
56 */
57
58 #include "local.h"
59
60 #undef _XOPEN_SOURCE_EXTENDED
61 #define _XOPEN_SOURCE_EXTENDED 1
62
63 #define MAX_WINDOWS 3
64
65 /* Statically allocate all structures (no malloc())! */
66 static WINDOW window_list[MAX_WINDOWS];
67 static int window_count = 0;
68
69 // struct ldat foo;
70 static struct ldat ldat_list[MAX_WINDOWS][SCREEN_Y];
71 static int ldat_count = 0;
72
73 /* One item bigger than SCREEN_X to reserve space for a NUL byte. */
74 static NCURSES_CH_T linebuf_list[SCREEN_Y * MAX_WINDOWS][SCREEN_X + 1];
75 static int linebuf_count = 0;
76
77 /* Globals */
78 int COLORS; /* Currently unused? */
79 int COLOR_PAIRS = 255;
80 WINDOW *stdscr;
81 WINDOW *curscr;
82 WINDOW *newscr;
83 int LINES = 25;
84 int COLS = 80;
85 int TABSIZE;
86 int ESCDELAY;
87 // char ttytype[];
88 // cchar_t *_nc_wacs;
89 SCREEN *SP;
90 chtype acs_map[128];
91
92 /* See terminfo(5). */
93 chtype fallback_acs_map[128] =
94 {
95 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
96 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
97 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
98 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
99 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
100 ' ', ' ', ' ', '>', '<', '^', 'v', ' ',
101 '#', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
102 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
103 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
104 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
105 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
106 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
107 '+', ':', ' ', ' ', ' ', ' ', '\\', '#',
108 '#', '#', '+', '+', '+', '+', '+', '~',
109 '-', '-', '-', '_', '+', '+', '+', '+',
110 '|', '<', '>', '*', '!', 'f', 'o', ' ',
111 };
112
113 #if CONFIG(LP_SERIAL_CONSOLE)
114 #if CONFIG(LP_SERIAL_ACS_FALLBACK)
115 chtype serial_acs_map[128];
116 #else
117 /* See acsc of vt100. */
118 chtype serial_acs_map[128] =
119 {
120 0, 0, 0, 0, 0, 0, 0, 0,
121 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0,
123 0, 0, 0, 0, 0, 0, 0, 0,
124 0, 0, 0, 0, 0, 0, 0, 0,
125 0, 0, 0, 0, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0,
127 0, 0, 0, 0, 0, 0, 0, 0,
128 0, 0, 0, 0, 0, 0, 0, 0,
129 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0,
132 '`', 'a', 0, 0, 0, 0, 'f', 'g',
133 0, 0, 'j', 'k', 'l', 'm', 'n', 'o',
134 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
135 'x', 'y', 'z', '{', '|', '}', '~', 0,
136 };
137 #endif
138 #endif
139
140 #if CONFIG(LP_VIDEO_CONSOLE)
141 /* See acsc of linux. */
142 chtype console_acs_map[128] =
143 {
144 0, 0, 0, 0, 0, 0, 0, 0,
145 0, 0, 0, 0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, 0,
147 0, 0, 0, 0, 0, 0, 0, 0,
148 0, 0, 0, 0, 0, 0, 0, 0,
149 0, 0, 0, '\020', '\021', '\030', '\031', 0,
150 '\333', 0, 0, 0, 0, 0, 0, 0,
151 0, 0, 0, 0, 0, 0, 0, 0,
152 0, 0, 0, 0, 0, 0, 0, 0,
153 0, 0, 0, 0, 0, 0, 0, 0,
154 0, 0, 0, 0, 0, 0, 0, 0,
155 0, 0, 0, 0, 0, 0, 0, 0,
156 '\004', '\261', 0, 0, 0, 0, '\370', '\361',
157 '\260', '\316', '\331', '\277', '\332', '\300', '\305', '~',
158 '\304', '\304', '\304', '_', '\303', '\264', '\301', '\302',
159 '\263', '\363', '\362', '\343', '\330', '\234', '\376', 0,
160 };
161 #endif
162
163 // FIXME: Ugly (and insecure!) hack!
164 char sprintf_tmp[1024];
165
166 int curses_flags = (F_ENABLE_CONSOLE | F_ENABLE_SERIAL);
167
168 /* Return bit mask for clearing color pair number if given ch has color */
169 #define COLOR_MASK(ch) (~(attr_t)((ch) & A_COLOR ? A_COLOR : 0))
170
171 /* Compute a rendition of the given char correct for the current context. */
render_char(WINDOW * win,NCURSES_CH_T ch)172 static inline NCURSES_CH_T render_char(WINDOW *win, NCURSES_CH_T ch)
173 {
174 /* TODO. */
175 return ch;
176 }
177
178 /* Make render_char() visible while still allowing us to inline it below. */
_nc_render(WINDOW * win,NCURSES_CH_T ch)179 NCURSES_CH_T _nc_render(WINDOW *win, NCURSES_CH_T ch)
180 {
181 return render_char(win, ch);
182 }
183
184 /*
185 * Implementations of most functions marked 'implemented' in include/curses.h:
186 */
187
188 // int baudrate(void) {}
beep(void)189 int beep(void)
190 {
191 /* TODO: Flash the screen if beeping fails? */
192 #if CONFIG(LP_SPEAKER)
193 speaker_tone(1760, 500); /* 1760 == note A6 */
194 #endif
195 return OK;
196 }
197 // bool can_change_color(void) {}
cbreak(void)198 int cbreak(void) { /* TODO */ return 0; }
clearok(WINDOW * win,bool flag)199 /* D */ int clearok(WINDOW *win, bool flag) { win->_clear = flag; return OK; }
200 // int color_content(short color, short *r, short *g, short *b) {}
curs_set(int on)201 int curs_set(int on)
202 {
203 #if CONFIG(LP_SERIAL_CONSOLE)
204 if (curses_flags & F_ENABLE_SERIAL) {
205 serial_cursor_enable(on);
206 }
207 #endif
208 #if CONFIG(LP_VIDEO_CONSOLE)
209 if (curses_flags & F_ENABLE_CONSOLE) {
210 video_console_cursor_enable(on);
211 }
212 #endif
213
214 return OK;
215 }
216 // int def_prog_mode(void) {}
217 // int def_shell_mode(void) {}
218 // int delay_output(int) {}
219 // void delscreen(SCREEN *) {}
delwin(WINDOW * win)220 int delwin(WINDOW *win)
221 {
222 /* TODO: Don't try to delete stdscr. */
223 /* TODO: Don't delete parent windows before subwindows. */
224
225 // if (win->_flags & _SUBWIN)
226 // touchwin(win->_parent);
227 // else if (curscr != 0)
228 // touchwin(curscr);
229
230 // return _nc_freewin(win);
231 return OK;
232 }
derwin(WINDOW * orig,int num_lines,int num_columns,int begy,int begx)233 WINDOW *derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx)
234 {
235 #if 0
236 WINDOW *win = NULL;
237 int i;
238 int flags = _SUBWIN;
239
240 /* Make sure window fits inside the original one. */
241 if (begy < 0 || begx < 0 || orig == 0 || num_lines < 0
242 || num_columns < 0)
243 return NULL;
244
245 if (begy + num_lines > orig->_maxy + 1
246 || begx + num_columns > orig->_maxx + 1)
247 return NULL;
248
249 if (num_lines == 0)
250 num_lines = orig->_maxy + 1 - begy;
251
252 if (num_columns == 0)
253 num_columns = orig->_maxx + 1 - begx;
254
255 if (orig->_flags & _ISPAD)
256 flags |= _ISPAD;
257
258 // FIXME
259 if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy,
260 orig->_begx + begx, flags)) == 0)
261 return NULL;
262
263 win->_pary = begy;
264 win->_parx = begx;
265 WINDOW_ATTRS(win) = WINDOW_ATTRS(orig);
266 win->_nc_bkgd = orig->_nc_bkgd;
267
268 for (i = 0; i < num_lines; i++)
269 win->_line[i].text = &orig->_line[begy++].text[begx];
270
271 win->_parent = orig;
272
273 return win;
274 #else
275 return NULL;
276 #endif
277 }
doupdate(void)278 int doupdate(void) { /* TODO */ return(0); }
279 // WINDOW * dupwin (WINDOW *) {}
echo(void)280 /* D */ int echo(void) { SP->_echo = TRUE; return OK; }
endwin(void)281 int endwin(void)
282 {
283 if (!SP)
284 return ERR;
285
286 SP->_endwin = TRUE;
287 #ifdef NCURSES_MOUSE_VERSION
288 SP->_mouse_wrap(SP);
289 #endif
290 // _nc_screen_wrap();
291 // _nc_mvcur_wrap(); /* wrap up cursor addressing */
292 // return reset_shell_mode();
293 return OK; // FIXME
294 }
295 // char erasechar (void) {}
296 // void filter (void) {}
297 // int flash(void) {}
flushinp(void)298 int flushinp(void) { /* TODO */ return 0; }
299 // WINDOW *getwin (FILE *) {}
has_colors(void)300 bool has_colors (void) { return(TRUE); }
301 // bool has_ic (void) {}
302 // bool has_il (void) {}
303 // void idcok (WINDOW *, bool) {}
304 // int idlok (WINDOW *, bool) {}
immedok(WINDOW * win,bool flag)305 void immedok(WINDOW *win, bool flag) { win->_immed = flag; }
306 /** Note: Must _not_ be called twice! */
initscr(void)307 WINDOW *initscr(void)
308 {
309 int i;
310
311 // newterm(name, stdout, stdin);
312 // def_prog_mode();
313
314 for (i = 0; i < 128; i++)
315 acs_map[i] = (chtype) i | A_ALTCHARSET;
316 #if CONFIG(LP_SERIAL_CONSOLE)
317 if (curses_flags & F_ENABLE_SERIAL) {
318 serial_clear();
319 }
320 #endif
321 #if CONFIG(LP_VIDEO_CONSOLE)
322 if (curses_flags & F_ENABLE_CONSOLE) {
323 /* Clear the screen and kill the cursor */
324
325 video_console_clear();
326 video_console_cursor_enable(0);
327 }
328 #endif
329
330 // Speaker init?
331
332 stdscr = newwin(SCREEN_Y, SCREEN_X, 0, 0);
333 // TODO: curscr, newscr?
334
335 werase(stdscr);
336
337 return stdscr;
338 }
339 // int intrflush (WINDOW *,bool) {}
isendwin(void)340 /* D */ bool isendwin(void) { return ((SP == NULL) ? FALSE : SP->_endwin); }
341 // bool is_linetouched (WINDOW *,int) {}
342 // bool is_wintouched (WINDOW *) {}
343 // NCURSES_CONST char * keyname (int) {}
keypad(WINDOW * win,bool flag)344 int keypad (WINDOW *win, bool flag) { /* TODO */ return 0; }
345 // char killchar (void) {}
leaveok(WINDOW * win,bool flag)346 /* D */ int leaveok(WINDOW *win, bool flag) { win->_leaveok = flag; return OK; }
347 // char *longname (void) {}
348 // int meta (WINDOW *,bool) {}
349 // int mvcur (int,int,int,int) {}
350 // int mvderwin (WINDOW *, int, int) {}
mvprintw(int y,int x,const char * fmt,...)351 int mvprintw(int y, int x, const char *fmt, ...)
352 {
353 va_list argp;
354 int code;
355
356 if (move(y, x) == ERR)
357 return ERR;
358
359 va_start(argp, fmt);
360 code = vwprintw(stdscr, fmt, argp);
361 va_end(argp);
362
363 return code;
364 }
365 // int mvscanw (int,int, NCURSES_CONST char *,...) {}
366 // int mvwin (WINDOW *,int,int) {}
mvwprintw(WINDOW * win,int y,int x,const char * fmt,...)367 int mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...)
368 {
369 va_list argp;
370 int code;
371
372 if (wmove(win, y, x) == ERR)
373 return ERR;
374
375 va_start(argp, fmt);
376 code = vwprintw(win, fmt, argp);
377 va_end(argp);
378
379 return code;
380 }
381 // int mvwscanw (WINDOW *,int,int, NCURSES_CONST char *,...) {}
382 // int napms (int) {}
383 // WINDOW *newpad (int,int) {}
384 // SCREEN *newterm (NCURSES_CONST char *,FILE *,FILE *) {}
newwin(int num_lines,int num_columns,int begy,int begx)385 WINDOW *newwin(int num_lines, int num_columns, int begy, int begx)
386 {
387 WINDOW *win;
388 int i;
389
390 /* Use next statically allocated window. */
391 // TODO: Error handling. Yes. Please.
392 // TODO: WINDOWLIST?
393
394 if (window_count >= MAX_WINDOWS)
395 return NULL;
396
397 win = &window_list[window_count++];
398
399 // bool is_pad = (flags & _ISPAD);
400
401 // TODO: Checks.
402
403 win->_cury = 0;
404 win->_curx = 0;
405 win->_maxy = num_lines - 1;
406 win->_maxx = num_columns - 1;
407 win->_begy = begy;
408 win->_begx = begx;
409 // win->_yoffset = SP->_topstolen;
410
411 win->_line = ldat_list[ldat_count++];
412
413 /* FIXME: Is this right? Should the window attributes be normal? */
414 win->_color = PAIR_NUMBER(0);
415 win->_attrs = A_NORMAL;
416
417 for (i = 0; i < num_lines; i++)
418 win->_line[i].text =
419 (NCURSES_CH_T *)&linebuf_list[linebuf_count++];
420
421 return win;
422 }
nl(void)423 /* D */ int nl(void) { SP->_nl = TRUE; return OK; }
noecho(void)424 /* D */ int noecho(void) { SP->_echo = FALSE; return OK; }
nonl(void)425 /* D */ int nonl(void) { SP->_nl = FALSE; return OK; }
426 // void noqiflush (void) {}
427 // int noraw (void) {}
notimeout(WINDOW * win,bool f)428 /* D */ int notimeout (WINDOW *win, bool f) { win->_notimeout = f; return OK; }
429 // int overlay (const WINDOW*,WINDOW *) {}
430 // int overwrite (const WINDOW*,WINDOW *) {}
431 // int pair_content (short,short*,short*) {}
432 // int pechochar (WINDOW *, const chtype) {}
433 // int pnoutrefresh (WINDOW*,int,int,int,int,int,int) {}
434 // int prefresh (WINDOW *,int,int,int,int,int,int) {}
printw(const char * fmt,...)435 int printw(const char *fmt, ...)
436 {
437 va_list argp;
438 int code;
439
440 va_start(argp, fmt);
441 code = vwprintw(stdscr, fmt, argp);
442 va_end(argp);
443
444 return code;
445 }
446 // int putwin (WINDOW *, FILE *) {}
447 // void qiflush (void) {}
448 // int raw (void) {}
449 // int resetty (void) {}
450 // int reset_prog_mode (void) {}
451 // int reset_shell_mode (void) {}
452 // int ripoffline (int, int (*)(WINDOW *, int)) {}
453 // int savetty (void) {}
454 // int scanw (NCURSES_CONST char *,...) {}
455 // int scr_dump (const char *) {}
456 // int scr_init (const char *) {}
scrollok(WINDOW * win,bool flag)457 /* D */ int scrollok(WINDOW *win, bool flag) { win->_scroll = flag; return OK; }
458 // int scr_restore (const char *) {}
459 // int scr_set (const char *) {}
460 // SCREEN *set_term (SCREEN *) {}
461 // int slk_attroff (const chtype) {}
462 // int slk_attron (const chtype) {}
463 // int slk_attrset (const chtype) {}
464 // attr_t slk_attr (void) {}
465 // int slk_attr_set (const attr_t,short,void*) {}
466 // int slk_clear (void) {}
467 // int slk_color (short) {}
468 // int slk_init (int) {}
slk_label(int n)469 /* D */ char *slk_label(int n)
470 {
471 // TODO: Needed?
472 // if (SP == NULL || SP->_slk == NULL || n < 1 || n > SP->_slk->labcnt)
473 // return NULL;
474 return SP->_slk->ent[n - 1].ent_text;
475 }
476 // int slk_noutrefresh (void) {}
477 // int slk_refresh (void) {}
478 // int slk_restore (void) {}
479 // int slk_set (int,const char *,int) {}
480 // int slk_touch (void) {}
481
482 // WINDOW *subpad (WINDOW *, int, int, int, int) {}
subwin(WINDOW * w,int l,int c,int y,int x)483 WINDOW *subwin(WINDOW *w, int l, int c, int y, int x)
484 {
485 return derwin(w, l, c, y - w->_begy, x - w->_begx);
486 }
487 // int syncok (WINDOW *, bool) {}
488 // chtype termattrs (void) {}
489 // char *termname (void) {}
490 // int typeahead (int) {}
ungetch(int ch)491 int ungetch(int ch) { /* TODO */ return ERR; }
492 // void use_env (bool) {}
493 // int vidattr (chtype) {}
494 // int vidputs (chtype, int (*)(int)) {}
vwprintw(WINDOW * win,const char * fmt,va_list argp)495 int vwprintw(WINDOW *win, const char *fmt, va_list argp)
496 {
497 vsprintf((char *)&sprintf_tmp, fmt, argp);
498
499 /* TODO: Error handling? */
500 return waddstr(win, (char *)&sprintf_tmp);
501 }
502 // int vwscanw (WINDOW *, NCURSES_CONST char *,va_list) {}
waddch(WINDOW * win,const chtype ch)503 int waddch(WINDOW *win, const chtype ch)
504 {
505 int code = ERR;
506 // NCURSES_CH_T wch;
507 // SetChar2(wch, ch);
508
509 if (win->_line[win->_cury].firstchar == _NOCHANGE ||
510 win->_line[win->_cury].firstchar > win->_curx)
511 win->_line[win->_cury].firstchar = win->_curx;
512
513 win->_line[win->_cury].text[win->_curx].chars[0] =
514 ((ch) & (chtype)A_CHARTEXT);
515
516 win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win);
517 win->_line[win->_cury].text[win->_curx].attr |=
518 ((ch) & (chtype)A_ATTRIBUTES);
519
520 if (win->_line[win->_cury].lastchar == _NOCHANGE ||
521 win->_line[win->_cury].lastchar < win->_curx)
522 win->_line[win->_cury].lastchar = win->_curx;
523
524 win->_curx++; // FIXME
525
526 // if (win && (waddch_nosync(win, wch) != ERR)) {
527 // _nc_synchook(win);
528 // code = OK;
529 // }
530
531 return code;
532 }
533 // int waddchnstr (WINDOW *,const chtype *,int) {}
waddnstr(WINDOW * win,const char * astr,int n)534 int waddnstr(WINDOW *win, const char *astr, int n)
535 {
536 int code = OK;
537 const char *str = astr;
538
539 if (!str)
540 return ERR;
541
542 if (n < 0)
543 n = strlen(astr);
544
545 if (win->_line[win->_cury].firstchar == _NOCHANGE ||
546 win->_line[win->_cury].firstchar > win->_curx)
547 win->_line[win->_cury].firstchar = win->_curx;
548
549 while ((n-- > 0) && (*str != '\0')) {
550 // while (*str != '\0') {
551 win->_line[win->_cury].text[win->_curx].chars[0] = *str++;
552 win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win)
553 ;
554 win->_curx++; // FIXME
555
556 // NCURSES_CH_T ch;
557 // SetChar(ch, UChar(*str++), A_NORMAL);
558 // if (_nc_waddch_nosync(win, ch) == ERR) {
559 // code = ERR;
560 // break;
561 // }
562 }
563
564 if (win->_line[win->_cury].lastchar == _NOCHANGE ||
565 win->_line[win->_cury].lastchar < win->_curx)
566 win->_line[win->_cury].lastchar = win->_curx;
567
568 return code;
569 }
wattr_on(WINDOW * win,attr_t at,void * opts GCC_UNUSED)570 int wattr_on(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
571 {
572 if (at & A_COLOR)
573 win->_color = PAIR_NUMBER(at);
574 // toggle_attr_on(WINDOW_ATTRS(win), at);
575 return OK;
576 }
wattr_off(WINDOW * win,attr_t at,void * opts GCC_UNUSED)577 int wattr_off(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
578 {
579 if (at & A_COLOR)
580 win->_color = 0;
581 // toggle_attr_off(WINDOW_ATTRS(win), at);
582 return 0;
583 }
584 // int wbkgd (WINDOW *, chtype) {}
wbkgdset(WINDOW * win,chtype ch)585 void wbkgdset(WINDOW *win, chtype ch) { /* TODO */ }
586
wborder(WINDOW * win,chtype ls,chtype rs,chtype ts,chtype bs,chtype tl,chtype tr,chtype bl,chtype br)587 int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts, chtype bs,
588 chtype tl, chtype tr, chtype bl, chtype br)
589 {
590 int x, y;
591
592 if (ls == 0) ls = ACS_VLINE;
593 if (rs == 0) rs = ACS_VLINE;
594 if (ts == 0) ts = ACS_HLINE;
595 if (bs == 0) bs = ACS_HLINE;
596 if (tl == 0) tl = ACS_ULCORNER;
597 if (tr == 0) tr = ACS_URCORNER;
598 if (bl == 0) bl = ACS_LLCORNER;
599 if (br == 0) br = ACS_LRCORNER;
600
601 for(y = 0; y <= win->_maxy; y++) {
602
603 if (y == 0) {
604 mvwaddch(win, y, 0, tl);
605
606 for(x = 1; x < win->_maxx; x++)
607 mvwaddch(win, y, x, ts);
608
609 mvwaddch(win, y, win->_maxx, tr);
610 }
611 else if (y == win->_maxy) {
612 mvwaddch(win, y, 0, bl);
613
614 for(x = 1; x < win->_maxx; x++)
615 mvwaddch(win, y, x, bs);
616
617 mvwaddch(win, y, win->_maxx, br);
618 }
619 else {
620 mvwaddch(win, y, 0, ls);
621 mvwaddch(win, y, win->_maxx, rs);
622 }
623 }
624
625 return OK;
626 }
627
628 // int wchgat (WINDOW *, int, attr_t, short, const void *) {}
wclear(WINDOW * win)629 /* D */ int wclear(WINDOW *win)
630 {
631 if (werase(win) == ERR)
632 return ERR;
633 win->_clear = TRUE;
634 return OK;
635 }
636 // int wclrtobot (WINDOW *) {}
wclrtoeol(WINDOW * win)637 int wclrtoeol(WINDOW *win) { /* TODO */ return ERR; }
wcolor_set(WINDOW * win,short color_pair_number,void * opts)638 int wcolor_set(WINDOW *win, short color_pair_number, void *opts)
639 {
640 if (!opts && (color_pair_number >= 0)
641 && (color_pair_number < COLOR_PAIRS)) {
642 SET_WINDOW_PAIR(win, color_pair_number);
643 if_EXT_COLORS(win->_color = color_pair_number);
644 return OK;
645 }
646 return ERR;
647 }
648 // void wcursyncup (WINDOW *) {}
649 // int wdelch (WINDOW *) {}
650 // int wechochar (WINDOW *, const chtype) {}
werase(WINDOW * win)651 int werase(WINDOW *win)
652 {
653 int x, y;
654 for (y = 0; y <= win->_maxy; y++) {
655 for (x = 0; x <= win->_maxx; x++) {
656 win->_line[y].text[x].chars[0] = ' ';
657 win->_line[y].text[x].attr = WINDOW_ATTRS(win);
658 }
659 // Should we check instead?
660 win->_line[y].firstchar = 0;
661 win->_line[y].lastchar = win->_maxx;
662 }
663 return OK;
664 }
665 // int wgetnstr (WINDOW *,char *,int) {}
whline(WINDOW * win,chtype ch,int n)666 int whline(WINDOW *win, chtype ch, int n)
667 {
668 NCURSES_SIZE_T start, end;
669 struct ldat *line = &(win->_line[win->_cury]);
670 NCURSES_CH_T wch;
671
672 start = win->_curx;
673 end = start + n - 1;
674 if (end > win->_maxx)
675 end = win->_maxx;
676
677 CHANGED_RANGE(line, start, end);
678
679 //// TODO:
680 //// if (ch == 0)
681 //// SetChar2(wch, ACS_HLINE);
682 //// else
683 //// SetChar2(wch, ch);
684 // Ugly hack:
685 wch.chars[0] = ((ch) & (chtype)A_CHARTEXT);
686 wch.attr = ((ch) & (chtype)A_ATTRIBUTES);
687 wch = _nc_render(win, wch);
688
689 while (end >= start) {
690 line->text[end] = wch;
691 end--;
692 }
693
694 //// _nc_synchook(win);
695
696 return OK;
697 }
winch(WINDOW * win)698 /* D */ chtype winch(WINDOW *win)
699 {
700 //// TODO
701 // return (CharOf(win->_line[win->_cury].text[win->_curx]) |
702 // AttrOf(win->_line[win->_cury].text[win->_curx]));
703 return OK; // FIXME
704 }
705 // int winchnstr (WINDOW *, chtype *, int) {}
706 // int winnstr (WINDOW *, char *, int) {}
707 // int winsch (WINDOW *, chtype) {}
708 // int winsdelln (WINDOW *,int) {}
709 // int winsnstr (WINDOW *, const char *,int) {}
wmove(WINDOW * win,int y,int x)710 /* D */ int wmove(WINDOW *win, int y, int x)
711 {
712 if (!LEGALYX(win, y, x))
713 return ERR;
714 win->_curx = (NCURSES_SIZE_T) x;
715 win->_cury = (NCURSES_SIZE_T) y;
716 win->_flags &= ~_WRAPPED;
717 win->_flags |= _HASMOVED;
718 return OK;
719 }
720
721 #define SWAP_RED_BLUE(c) \
722 (((c) & 0x4400) >> 2) | ((c) & 0xAA00) | (((c) & 0x1100) << 2)
wnoutrefresh(WINDOW * win)723 int wnoutrefresh(WINDOW *win)
724 {
725 #if CONFIG(LP_SERIAL_CONSOLE)
726 // FIXME.
727 int serial_is_bold = 0;
728 int serial_is_reverse = 0;
729 int serial_is_altcharset = 0;
730 int serial_cur_pair = 0;
731
732 int need_altcharset;
733 short fg, bg;
734 #endif
735 int x, y;
736 chtype ch;
737
738 #if CONFIG(LP_SERIAL_CONSOLE)
739 serial_end_bold();
740 serial_end_altcharset();
741 #endif
742
743 for (y = 0; y <= win->_maxy; y++) {
744
745 if (win->_line[y].firstchar == _NOCHANGE)
746 continue;
747
748 /* Position the serial cursor */
749
750 #if CONFIG(LP_SERIAL_CONSOLE)
751 if (curses_flags & F_ENABLE_SERIAL)
752 serial_set_cursor(win->_begy + y, win->_begx +
753 win->_line[y].firstchar);
754 #endif
755
756 for (x = win->_line[y].firstchar; x <= win->_line[y].lastchar; x++) {
757 attr_t attr = win->_line[y].text[x].attr;
758
759 #if CONFIG(LP_SERIAL_CONSOLE)
760 if (curses_flags & F_ENABLE_SERIAL) {
761 ch = win->_line[y].text[x].chars[0];
762
763 if (attr & A_BOLD) {
764 if (!serial_is_bold) {
765 serial_start_bold();
766 serial_is_bold = 1;
767 }
768 } else {
769 if (serial_is_bold) {
770 serial_end_bold();
771 serial_is_bold = 0;
772 /* work around serial.c
773 * shortcoming:
774 */
775 serial_is_reverse = 0;
776 serial_cur_pair = 0;
777 }
778 }
779
780 if (attr & A_REVERSE) {
781 if (!serial_is_reverse) {
782 serial_start_reverse();
783 serial_is_reverse = 1;
784 }
785 } else {
786 if (serial_is_reverse) {
787 serial_end_reverse();
788 serial_is_reverse = 0;
789 /* work around serial.c
790 * shortcoming:
791 */
792 serial_is_bold = 0;
793 serial_cur_pair = 0;
794 }
795 }
796
797 need_altcharset = 0;
798 if (attr & A_ALTCHARSET) {
799 if (serial_acs_map[ch & 0x7f]) {
800 ch = serial_acs_map[ch & 0x7f];
801 need_altcharset = 1;
802 } else
803 ch = fallback_acs_map[ch & 0x7f];
804 }
805 if (need_altcharset && !serial_is_altcharset) {
806 serial_start_altcharset();
807 serial_is_altcharset = 1;
808 }
809 if (!need_altcharset && serial_is_altcharset) {
810 serial_end_altcharset();
811 serial_is_altcharset = 0;
812 }
813
814 if (serial_cur_pair != PAIR_NUMBER(attr)) {
815 pair_content(PAIR_NUMBER(attr),
816 &fg, &bg);
817 serial_set_color(fg, bg);
818 serial_cur_pair = PAIR_NUMBER(attr);
819 }
820
821 serial_putchar(ch);
822
823 }
824 #endif
825 #if CONFIG(LP_VIDEO_CONSOLE)
826 unsigned int c =
827 ((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
828
829 c = SWAP_RED_BLUE(c);
830
831 if (curses_flags & F_ENABLE_CONSOLE) {
832 ch = win->_line[y].text[x].chars[0];
833
834 /* Handle some of the attributes. */
835 if (attr & A_BOLD)
836 c |= 0x0800;
837 if (attr & A_DIM)
838 c &= ~0x800;
839 if (attr & A_REVERSE) {
840 unsigned char tmp = (c >> 8) & 0xf;
841 c = (c >> 4) & 0xf00;
842 c |= tmp << 12;
843 }
844 if (attr & A_ALTCHARSET) {
845 if (console_acs_map[ch & 0x7f])
846 ch = console_acs_map[ch & 0x7f];
847 else
848 ch = fallback_acs_map[ch & 0x7f];
849 }
850
851 /*
852 * FIXME: Somewhere along the line, the
853 * character value is getting sign-extented.
854 * For now grab just the 8 bit character,
855 * but this will break wide characters!
856 */
857 c |= (chtype) (ch & 0xff);
858 video_console_putc(win->_begy + y, win->_begx + x, c);
859 }
860 #endif
861 }
862 win->_line[y].firstchar = _NOCHANGE;
863 win->_line[y].lastchar = _NOCHANGE;
864 }
865
866 #if CONFIG(LP_SERIAL_CONSOLE)
867 if (curses_flags & F_ENABLE_SERIAL)
868 serial_set_cursor(win->_begy + win->_cury, win->_begx + win->_curx);
869 #endif
870
871 #if CONFIG(LP_VIDEO_CONSOLE)
872 if (curses_flags & F_ENABLE_CONSOLE)
873 video_console_set_cursor(win->_begx + win->_curx, win->_begy + win->_cury);
874 #endif
875
876 return OK;
877 }
wprintw(WINDOW * win,const char * fmt,...)878 int wprintw(WINDOW *win, const char *fmt, ...)
879 {
880 va_list argp;
881 int code;
882
883 va_start(argp, fmt);
884 code = vwprintw(win, fmt, argp);
885 va_end(argp);
886
887 return code;
888 }
889
wredrawln(WINDOW * win,int beg_line,int num_lines)890 int wredrawln (WINDOW *win, int beg_line, int num_lines)
891 {
892 int i;
893
894 for (i = beg_line; i < beg_line + num_lines; i++) {
895 win->_line[i].firstchar = 0;
896 win->_line[i].lastchar = win->_maxx;
897 }
898
899 return OK;
900 }
901
wrefresh(WINDOW * win)902 int wrefresh(WINDOW *win)
903 {
904 // FIXME
905 return wnoutrefresh(win);
906
907 // XXX
908 int code;
909
910 if (win == curscr) {
911 curscr->_clear = TRUE;
912 // code = doupdate();
913 } else if ((code = wnoutrefresh(win)) == OK) {
914 if (win->_clear)
915 newscr->_clear = TRUE;
916 // code = doupdate();
917 /*
918 * Reset the clearok() flag in case it was set for the special
919 * case in hardscroll.c (if we don't reset it here, we'll get 2
920 * refreshes because the flag is copied from stdscr to newscr).
921 * Resetting the flag shouldn't do any harm, anyway.
922 */
923 win->_clear = FALSE;
924 }
925
926 return code;
927 }
928 // int wscanw (WINDOW *, NCURSES_CONST char *,...) {}
wscrl(WINDOW * win,int n)929 int wscrl(WINDOW *win, int n)
930 {
931 int x, y;
932
933 if (!win->_scroll)
934 return ERR;
935
936 if (n == 0)
937 return OK;
938
939 for (y = 0; y <= (win->_maxy - n); y++) {
940 win->_line[y].firstchar = win->_line[y + n].firstchar;
941 win->_line[y].lastchar = win->_line[y + n].lastchar;
942 for (x = 0; x <= win->_maxx; x++) {
943 if ((win->_line[y].text[x].chars[0] != win->_line[y + n].text[x].chars[0]) ||
944 (win->_line[y].text[x].attr != win->_line[y + n].text[x].attr)) {
945 if (win->_line[y].firstchar == _NOCHANGE)
946 win->_line[y].firstchar = x;
947
948 win->_line[y].lastchar = x;
949
950 win->_line[y].text[x].chars[0] = win->_line[y + n].text[x].chars[0];
951 win->_line[y].text[x].attr = win->_line[y + n].text[x].attr;
952 }
953 }
954 }
955
956 for (y = (win->_maxy+1 - n); y <= win->_maxy; y++) {
957 for (x = 0; x <= win->_maxx; x++) {
958 if ((win->_line[y].text[x].chars[0] != ' ') ||
959 (win->_line[y].text[x].attr != A_NORMAL)) {
960 if (win->_line[y].firstchar == _NOCHANGE)
961 win->_line[y].firstchar = x;
962
963 win->_line[y].lastchar = x;
964
965 win->_line[y].text[x].chars[0] = ' ';
966 win->_line[y].text[x].attr = A_NORMAL;
967 }
968 }
969 }
970
971 // _nc_scroll_window(win, n, win->_regtop, win->_regbottom, win->_nc_bkgd);
972 // _nc_synchook(win);
973
974 return OK;
975 }
wsetscrreg(WINDOW * win,int top,int bottom)976 int wsetscrreg(WINDOW *win, int top, int bottom)
977 {
978 if (top >= 0 && top <= win->_maxy && bottom >= 0 &&
979 bottom <= win->_maxy && bottom > top) {
980 win->_regtop = (NCURSES_SIZE_T) top;
981 win->_regbottom = (NCURSES_SIZE_T) bottom;
982 return OK;
983 }
984 return ERR;
985 }
986 // void wsyncdown (WINDOW *) {}
987 // void wsyncup (WINDOW *) {}
wtimeout(WINDOW * win,int _delay)988 /* D */ void wtimeout(WINDOW *win, int _delay) { win->_delay = _delay; }
wtouchln(WINDOW * win,int y,int n,int changed)989 /* D */ int wtouchln(WINDOW *win, int y, int n, int changed)
990 {
991 int i;
992
993 // if ((n < 0) || (y < 0) || (y > win->_maxy))
994 // return ERR;
995
996 for (i = y; i < y + n; i++) {
997 if (i > win->_maxy)
998 break;
999 win->_line[i].firstchar = changed ? 0 : _NOCHANGE;
1000 win->_line[i].lastchar = changed ? win->_maxx : _NOCHANGE;
1001 }
1002 return OK;
1003 }
1004 // int wvline (WINDOW *,chtype,int) {}
1005 // int tigetflag (NCURSES_CONST char *) {}
1006 // int tigetnum (NCURSES_CONST char *) {}
1007 // char *tigetstr (NCURSES_CONST char *) {}
1008 // int putp (const char *) {}
1009 // #if NCURSES_TPARM_VARARGS
1010 // char *tparm (NCURSES_CONST char *, ...) {}
1011 // #else
1012 // char *tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long) {}
1013 // char *tparm_varargs (NCURSES_CONST char *, ...) {}
1014 // #endif
1015