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