libpayload: Don't declare mouse support in tinycurses
[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 #ifdef NCURSES_MOUSE_VERSION
290         SP->_mouse_wrap(SP);
291 #endif
292         // _nc_screen_wrap();
293         // _nc_mvcur_wrap();       /* wrap up cursor addressing */
294         // return reset_shell_mode();
295         return OK;      // FIXME
296 }
297 // char erasechar (void) {}
298 // void filter (void) {}
299 // int flash(void) {}
300 int flushinp(void) { /* TODO */ return 0; }
301 // WINDOW *getwin (FILE *) {}
302 bool has_colors (void) { return(TRUE); }
303 // bool has_ic (void) {}
304 // bool has_il (void) {}
305 // void idcok (WINDOW *, bool) {}
306 // int idlok (WINDOW *, bool) {}
307 void immedok(WINDOW *win, bool flag) { win->_immed = flag; }
308 /** Note: Must _not_ be called twice! */
309 WINDOW *initscr(void)
310 {
311         int i;
312
313         // newterm(name, stdout, stdin);
314         // def_prog_mode();
315
316         for (i = 0; i < 128; i++)
317           acs_map[i] = (chtype) i | A_ALTCHARSET;
318 #ifdef CONFIG_SERIAL_CONSOLE
319         if (curses_flags & F_ENABLE_SERIAL) {
320                 serial_clear();
321         }
322 #endif
323 #ifdef CONFIG_VIDEO_CONSOLE
324         if (curses_flags & F_ENABLE_CONSOLE) {
325                 /* Clear the screen and kill the cursor */
326
327                 video_console_clear();
328                 video_console_cursor_enable(0);
329         }
330 #endif
331
332         // Speaker init?
333
334         stdscr = newwin(SCREEN_Y, SCREEN_X, 0, 0);
335         // TODO: curscr, newscr?
336
337         werase(stdscr);
338
339         return stdscr;
340 }
341 // int intrflush (WINDOW *,bool) {}
342 /* D */ bool isendwin(void) { return ((SP == NULL) ? FALSE : SP->_endwin); }
343 // bool is_linetouched (WINDOW *,int) {}
344 // bool is_wintouched (WINDOW *) {}
345 // NCURSES_CONST char * keyname (int) {}
346 int keypad (WINDOW *win, bool flag) { /* TODO */ return 0; }
347 // char killchar (void) {}
348 /* D */ int leaveok(WINDOW *win, bool flag) { win->_leaveok = flag; return OK; }
349 // char *longname (void) {}
350 // int meta (WINDOW *,bool) {}
351 // int mvcur (int,int,int,int) {}
352 // int mvderwin (WINDOW *, int, int) {}
353 int mvprintw(int y, int x, const char *fmt, ...)
354 {
355         va_list argp;
356         int code;
357
358         if (move(y, x) == ERR)
359                 return ERR;
360
361         va_start(argp, fmt);
362         code = vwprintw(stdscr, fmt, argp);
363         va_end(argp);
364
365         return code;
366 }
367 // int mvscanw (int,int, NCURSES_CONST char *,...) {}
368 // int mvwin (WINDOW *,int,int) {}
369 int mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...)
370 {
371         va_list argp;
372         int code;
373
374         if (wmove(win, y, x) == ERR)
375                 return ERR;
376
377         va_start(argp, fmt);
378         code = vwprintw(win, fmt, argp);
379         va_end(argp);
380
381         return code;
382 }
383 // int mvwscanw (WINDOW *,int,int, NCURSES_CONST char *,...) {}
384 // int napms (int) {}
385 // WINDOW *newpad (int,int) {}
386 // SCREEN *newterm (NCURSES_CONST char *,FILE *,FILE *) {}
387 WINDOW *newwin(int num_lines, int num_columns, int begy, int begx)
388 {
389         int i;
390
391         /* Use next statically allocated window. */
392         // TODO: Error handling.
393         // TODO: WINDOWLIST?
394         WINDOW *win = &window_list[window_count++];
395
396         // bool is_pad = (flags & _ISPAD);
397
398         // TODO: Checks.
399
400         win->_cury = 0;
401         win->_curx = 0;
402         win->_maxy = num_lines - 1;
403         win->_maxx = num_columns - 1;
404         win->_begy = begy;
405         win->_begx = begx;
406         // win->_yoffset = SP->_topstolen;
407
408         win->_line = ldat_list[ldat_count++];
409
410         /* FIXME: Is this right? Should the window attributes be normal? */
411         win->_color = PAIR_NUMBER(0);
412         win->_attrs = A_NORMAL;
413
414         for (i = 0; i < num_lines; i++)
415                 win->_line[i].text =
416                      (NCURSES_CH_T *)&linebuf_list[linebuf_count++];
417
418         return win;
419 }
420 /* D */ int nl(void) { SP->_nl = TRUE; return OK; }
421 /* D */ int noecho(void) { SP->_echo = FALSE; return OK; }
422 /* D */ int nonl(void) { SP->_nl = FALSE; return OK; }
423 // void noqiflush (void) {}
424 // int noraw (void) {}
425 /* D */ int notimeout (WINDOW *win, bool f) { win->_notimeout = f; return OK; }
426 // int overlay (const WINDOW*,WINDOW *) {}
427 // int overwrite (const WINDOW*,WINDOW *) {}
428 // int pair_content (short,short*,short*) {}
429 // int pechochar (WINDOW *, const chtype) {}
430 // int pnoutrefresh (WINDOW*,int,int,int,int,int,int) {}
431 // int prefresh (WINDOW *,int,int,int,int,int,int) {}
432 int printw(const char *fmt, ...)
433 {
434         va_list argp;
435         int code;
436
437         va_start(argp, fmt);
438         code = vwprintw(stdscr, fmt, argp);
439         va_end(argp);
440
441         return code;
442 }
443 // int putwin (WINDOW *, FILE *) {}
444 // void qiflush (void) {}
445 // int raw (void) {}
446 // int resetty (void) {}
447 // int reset_prog_mode (void) {}
448 // int reset_shell_mode (void) {}
449 // int ripoffline (int, int (*)(WINDOW *, int)) {}
450 // int savetty (void) {}
451 // int scanw (NCURSES_CONST char *,...) {}
452 // int scr_dump (const char *) {}
453 // int scr_init (const char *) {}
454 /* D */ int scrollok(WINDOW *win, bool flag) { win->_scroll = flag; return OK; }
455 // int scr_restore (const char *) {}
456 // int scr_set (const char *) {}
457 // SCREEN *set_term (SCREEN *) {}
458 // int slk_attroff (const chtype) {}
459 // int slk_attron (const chtype) {}
460 // int slk_attrset (const chtype) {}
461 // attr_t slk_attr (void) {}
462 // int slk_attr_set (const attr_t,short,void*) {}
463 // int slk_clear (void) {}
464 // int slk_color (short) {}
465 // int slk_init (int) {}
466 /* D */ char *slk_label(int n)
467 {
468         // TODO: Needed?
469         // if (SP == NULL || SP->_slk == NULL || n < 1 || n > SP->_slk->labcnt)
470         //      return NULL;
471         return SP->_slk->ent[n - 1].ent_text;
472 }
473 // int slk_noutrefresh (void) {}
474 // int slk_refresh (void) {}
475 // int slk_restore (void) {}
476 // int slk_set (int,const char *,int) {}
477 // int slk_touch (void) {}
478
479 // WINDOW *subpad (WINDOW *, int, int, int, int) {}
480 WINDOW *subwin(WINDOW *w, int l, int c, int y, int x)
481 {
482         return derwin(w, l, c, y - w->_begy, x - w->_begx);
483 }
484 // int syncok (WINDOW *, bool) {}
485 // chtype termattrs (void) {}
486 // char *termname (void) {}
487 // int typeahead (int) {}
488 int ungetch(int ch) { /* TODO */ return ERR; }
489 // void use_env (bool) {}
490 // int vidattr (chtype) {}
491 // int vidputs (chtype, int (*)(int)) {}
492 int vwprintw(WINDOW *win, const char *fmt, va_list argp)
493 {
494         vsprintf((char *)&sprintf_tmp, fmt, argp);
495
496         /* TODO: Error handling? */
497         return waddstr(win, (char *)&sprintf_tmp);
498 }
499 // int vwscanw (WINDOW *, NCURSES_CONST char *,va_list) {}
500 int waddch(WINDOW *win, const chtype ch)
501 {
502         int code = ERR;
503         // NCURSES_CH_T wch;
504         // SetChar2(wch, ch);
505
506         if (win->_line[win->_cury].firstchar == _NOCHANGE ||
507                         win->_line[win->_cury].firstchar > win->_curx)
508                 win->_line[win->_cury].firstchar = win->_curx;
509
510         win->_line[win->_cury].text[win->_curx].chars[0] =
511                 ((ch) & (chtype)A_CHARTEXT);
512
513         win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win);
514         win->_line[win->_cury].text[win->_curx].attr |=
515                 ((ch) & (chtype)A_ATTRIBUTES);
516
517         if (win->_line[win->_cury].lastchar == _NOCHANGE ||
518                         win->_line[win->_cury].lastchar < win->_curx)
519                 win->_line[win->_cury].lastchar = win->_curx;
520
521         win->_curx++;   // FIXME
522
523         // if (win && (waddch_nosync(win, wch) != ERR)) {
524         //      _nc_synchook(win);
525         //      code = OK;
526         // }
527
528         return code;
529 }
530 // int waddchnstr (WINDOW *,const chtype *,int) {}
531 int waddnstr(WINDOW *win, const char *astr, int n)
532 {
533         int code = OK;
534         const char *str = astr;
535
536         if (!str)
537                 return ERR;
538
539         if (n < 0)
540                 n = strlen(astr);
541
542         if (win->_line[win->_cury].firstchar == _NOCHANGE ||
543                         win->_line[win->_cury].firstchar > win->_curx)
544                 win->_line[win->_cury].firstchar = win->_curx;
545
546         while ((n-- > 0) && (*str != '\0')) {
547         // while (*str != '\0') {
548                 win->_line[win->_cury].text[win->_curx].chars[0] = *str++;
549                 win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win)
550 ;
551                 win->_curx++;   // FIXME
552
553                 // NCURSES_CH_T ch;
554                 // SetChar(ch, UChar(*str++), A_NORMAL);
555                 // if (_nc_waddch_nosync(win, ch) == ERR) {
556                 //      code = ERR;
557                 //      break;
558                 // }
559         }
560
561         if (win->_line[win->_cury].lastchar == _NOCHANGE ||
562                         win->_line[win->_cury].lastchar < win->_curx)
563                 win->_line[win->_cury].lastchar = win->_curx;
564
565         return code;
566 }
567 int wattr_on(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
568 {
569         if (at & A_COLOR)
570                 win->_color = PAIR_NUMBER(at);
571         // toggle_attr_on(WINDOW_ATTRS(win), at);
572         return OK;
573 }
574 int wattr_off(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
575 {
576         if (at & A_COLOR)
577                 win->_color = 0;
578         // toggle_attr_off(WINDOW_ATTRS(win), at);
579         return 0;
580 }
581 // int wbkgd (WINDOW *, chtype) {}
582 void wbkgdset(WINDOW *win, chtype ch) { /* TODO */ }
583
584 int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts, chtype bs,
585                 chtype tl, chtype tr, chtype bl, chtype br)
586 {
587         int x, y;
588
589         if (ls == 0) ls = ACS_VLINE;
590         if (rs == 0) rs = ACS_VLINE;
591         if (ts == 0) ts = ACS_HLINE;
592         if (bs == 0) bs = ACS_HLINE;
593         if (tl == 0) tl = ACS_ULCORNER;
594         if (tr == 0) tr = ACS_URCORNER;
595         if (bl == 0) bl = ACS_LLCORNER;
596         if (br == 0) br = ACS_LRCORNER;
597
598         for(y = 0; y <= win->_maxy; y++) {
599
600                 if (y == 0) {
601                          mvwaddch(win, y, 0, tl);
602
603                         for(x = 1; x < win->_maxx; x++)
604                                 mvwaddch(win, y, x, ts);
605
606                         mvwaddch(win, y, win->_maxx, tr);
607                 }
608                 else if (y == win->_maxy) {
609                         mvwaddch(win, y, 0, bl);
610
611                         for(x = 1; x < win->_maxx; x++)
612                                 mvwaddch(win, y, x, bs);
613
614                         mvwaddch(win, y, win->_maxx, br);
615                 }
616                 else {
617                         mvwaddch(win, y, 0, ls);
618                         mvwaddch(win, y, win->_maxx, rs);
619                 }
620         }
621
622         return OK;
623 }
624
625 // int wchgat (WINDOW *, int, attr_t, short, const void *) {}
626 /* D */ int wclear(WINDOW *win)
627 {
628         if (werase(win) == ERR)
629                 return ERR;
630         win->_clear = TRUE;
631         return OK;
632 }
633 // int wclrtobot (WINDOW *) {}
634 int wclrtoeol(WINDOW *win) { /* TODO */ return ERR; }
635 int wcolor_set(WINDOW *win, short color_pair_number, void *opts)
636 {
637         if (!opts && (color_pair_number >= 0)
638             && (color_pair_number < COLOR_PAIRS)) {
639                 SET_WINDOW_PAIR(win, color_pair_number);
640                 if_EXT_COLORS(win->_color = color_pair_number);
641                 return OK;
642         }
643         return ERR;
644 }
645 // void wcursyncup (WINDOW *) {}
646 // int wdelch (WINDOW *) {}
647 // int wechochar (WINDOW *, const chtype) {}
648 int werase(WINDOW *win)
649 {
650         int x, y;
651         for (y = 0; y <= win->_maxy; y++) {
652                 for (x = 0; x <= win->_maxx; x++) {
653                         win->_line[y].text[x].chars[0] = ' ';
654                         win->_line[y].text[x].attr = WINDOW_ATTRS(win);
655                 }
656                 // Should we check instead?
657                 win->_line[y].firstchar = 0;
658                 win->_line[y].lastchar = win->_maxx;
659         }
660         return OK;
661 }
662 // int wgetnstr (WINDOW *,char *,int) {}
663 int whline(WINDOW *win, chtype ch, int n)
664 {
665         NCURSES_SIZE_T start, end;
666         struct ldat *line = &(win->_line[win->_cury]);
667         NCURSES_CH_T wch;
668
669         start = win->_curx;
670         end = start + n - 1;
671         if (end > win->_maxx)
672                 end = win->_maxx;
673
674         CHANGED_RANGE(line, start, end);
675
676         //// TODO:
677         //// if (ch == 0)
678         ////     SetChar2(wch, ACS_HLINE);
679         //// else
680         ////     SetChar2(wch, ch);
681         // Ugly hack:
682         wch.chars[0] = ((ch) & (chtype)A_CHARTEXT);
683         wch.attr = ((ch) & (chtype)A_ATTRIBUTES);
684         wch = _nc_render(win, wch);
685
686         while (end >= start) {
687                 line->text[end] = wch;
688                 end--;
689         }
690
691         //// _nc_synchook(win);
692
693         return OK;
694 }
695 /* D */ chtype winch(WINDOW *win)
696 {
697         //// TODO
698         // return (CharOf(win->_line[win->_cury].text[win->_curx]) |
699         //         AttrOf(win->_line[win->_cury].text[win->_curx]));
700         return OK;      // FIXME
701 }
702 // int winchnstr (WINDOW *, chtype *, int) {}
703 // int winnstr (WINDOW *, char *, int) {}
704 // int winsch (WINDOW *, chtype) {}
705 // int winsdelln (WINDOW *,int) {}
706 // int winsnstr (WINDOW *, const char *,int) {}
707 /* D */ int wmove(WINDOW *win, int y, int x)
708 {
709         if (!LEGALYX(win, y, x))
710                 return ERR;
711         win->_curx = (NCURSES_SIZE_T) x;
712         win->_cury = (NCURSES_SIZE_T) y;
713         win->_flags &= ~_WRAPPED;
714         win->_flags |= _HASMOVED;
715         return OK;
716 }
717
718 #define SWAP_RED_BLUE(c) \
719         (((c) & 0x4400) >> 2) | ((c) & 0xAA00) | (((c) & 0x1100) << 2)
720 int wnoutrefresh(WINDOW *win)
721 {
722 #ifdef CONFIG_SERIAL_CONSOLE
723         // FIXME.
724         int serial_is_bold = 0;
725         int serial_is_reverse = 0;
726         int serial_is_altcharset = 0;
727         int serial_cur_pair = 0;
728
729         int need_altcharset;
730         short fg, bg;
731 #endif
732         int x, y;
733         chtype ch;
734
735 #ifdef CONFIG_SERIAL_CONSOLE
736         serial_end_bold();
737         serial_end_altcharset();
738 #endif
739
740         for (y = 0; y <= win->_maxy; y++) {
741
742                 if (win->_line[y].firstchar == _NOCHANGE)
743                         continue;
744
745                 /* Position the serial cursor */
746
747 #ifdef CONFIG_SERIAL_CONSOLE
748                 if (curses_flags & F_ENABLE_SERIAL)
749                         serial_set_cursor(win->_begy + y, win->_begx +
750                                         win->_line[y].firstchar);
751 #endif
752
753                 for (x = win->_line[y].firstchar; x <= win->_line[y].lastchar; x++) {
754                         attr_t attr = win->_line[y].text[x].attr;
755
756 #ifdef CONFIG_SERIAL_CONSOLE
757                         if (curses_flags & F_ENABLE_SERIAL) {
758                                 ch = win->_line[y].text[x].chars[0];
759
760                                 if (attr & A_BOLD) {
761                                         if (!serial_is_bold) {
762                                                 serial_start_bold();
763                                                 serial_is_bold = 1;
764                                         }
765                                 } else {
766                                         if (serial_is_bold) {
767                                                 serial_end_bold();
768                                                 serial_is_bold = 0;
769                                                 /* work around serial.c
770                                                  * shortcoming:
771                                                  */
772                                                 serial_is_reverse = 0;
773                                                 serial_cur_pair = 0;
774                                         }
775                                 }
776
777                                 if (attr & A_REVERSE) {
778                                         if (!serial_is_reverse) {
779                                                 serial_start_reverse();
780                                                 serial_is_reverse = 1;
781                                         }
782                                 } else {
783                                         if (serial_is_reverse) {
784                                                 serial_end_reverse();
785                                                 serial_is_reverse = 0;
786                                                 /* work around serial.c
787                                                  * shortcoming:
788                                                  */
789                                                 serial_is_bold = 0;
790                                                 serial_cur_pair = 0;
791                                         }
792                                 }
793
794                                 need_altcharset = 0;
795                                 if (attr & A_ALTCHARSET) {
796                                         if (serial_acs_map[ch & 0x7f]) {
797                                                 ch = serial_acs_map[ch & 0x7f];
798                                                 need_altcharset = 1;
799                                         } else
800                                                 ch = fallback_acs_map[ch & 0x7f];
801                                 }
802                                 if (need_altcharset && !serial_is_altcharset) {
803                                         serial_start_altcharset();
804                                         serial_is_altcharset = 1;
805                                 }
806                                 if (!need_altcharset && serial_is_altcharset) {
807                                         serial_end_altcharset();
808                                         serial_is_altcharset = 0;
809                                 }
810
811                                 if (serial_cur_pair != PAIR_NUMBER(attr)) {
812                                         pair_content(PAIR_NUMBER(attr),
813                                                      &fg, &bg);
814                                         serial_set_color(fg, bg);
815                                         serial_cur_pair = PAIR_NUMBER(attr);
816                                 }
817
818                                 serial_putchar(ch);
819
820                         }
821 #endif
822 #ifdef CONFIG_VIDEO_CONSOLE
823                         unsigned int c =
824                                 ((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
825
826                         c = SWAP_RED_BLUE(c);
827
828                         if (curses_flags & F_ENABLE_CONSOLE) {
829                                 ch = win->_line[y].text[x].chars[0];
830
831                                 /* Handle some of the attributes. */
832                                 if (attr & A_BOLD)
833                                         c |= 0x0800;
834                                 if (attr & A_DIM)
835                                         c &= ~0x800;
836                                 if (attr & A_REVERSE) {
837                                         unsigned char tmp = (c >> 8) & 0xf;
838                                         c = (c >> 4) & 0xf00;
839                                         c |= tmp << 12;
840                                 }
841                                 if (attr & A_ALTCHARSET) {
842                                         if (console_acs_map[ch & 0x7f])
843                                                 ch = console_acs_map[ch & 0x7f];
844                                         else
845                                                 ch = fallback_acs_map[ch & 0x7f];
846                                 }
847
848                                 /*
849                                  * FIXME: Somewhere along the line, the
850                                  * character value is getting sign-extented.
851                                  * For now grab just the 8 bit character,
852                                  * but this will break wide characters!
853                                  */
854                                 c |= (chtype) (ch & 0xff);
855                                 video_console_putc(win->_begy + y, win->_begx + x, c);
856                         }
857 #endif
858                 }
859                 win->_line[y].firstchar = _NOCHANGE;
860                 win->_line[y].lastchar = _NOCHANGE;
861         }
862
863 #ifdef CONFIG_SERIAL_CONSOLE
864         if (curses_flags & F_ENABLE_SERIAL)
865                 serial_set_cursor(win->_begy + win->_cury, win->_begx + win->_curx);
866 #endif
867
868 #ifdef CONFIG_VIDEO_CONSOLE
869         if (curses_flags & F_ENABLE_CONSOLE)
870                 video_console_set_cursor(win->_begx + win->_curx, win->_begy + win->_cury);
871 #endif
872
873         return OK;
874 }
875 int wprintw(WINDOW *win, const char *fmt, ...)
876 {
877         va_list argp;
878         int code;
879
880         va_start(argp, fmt);
881         code = vwprintw(win, fmt, argp);
882         va_end(argp);
883
884         return code;
885 }
886
887 int wredrawln (WINDOW *win, int beg_line, int num_lines)
888 {
889         int i;
890
891         for (i = beg_line; i < beg_line + num_lines; i++) {
892                 win->_line[i].firstchar = 0;
893                 win->_line[i].lastchar = win->_maxx;
894         }
895
896         return OK;
897 }
898
899 int wrefresh(WINDOW *win)
900 {
901         // FIXME
902         return wnoutrefresh(win);
903
904         // XXX
905         int code;
906
907         if (win == curscr) {
908                 curscr->_clear = TRUE;
909                 // code = doupdate();
910         } else if ((code = wnoutrefresh(win)) == OK) {
911                 if (win->_clear)
912                         newscr->_clear = TRUE;
913                 // code = doupdate();
914                 /*
915                  * Reset the clearok() flag in case it was set for the special
916                  * case in hardscroll.c (if we don't reset it here, we'll get 2
917                  * refreshes because the flag is copied from stdscr to newscr).
918                  * Resetting the flag shouldn't do any harm, anyway.
919                  */
920                 win->_clear = FALSE;
921         }
922
923         return code;
924 }
925 // int wscanw (WINDOW *, NCURSES_CONST char *,...) {}
926 int wscrl(WINDOW *win, int n)
927 {
928         int x, y;
929
930         if (!win->_scroll)
931                 return ERR;
932
933         if (n == 0)
934                 return OK;
935
936         for (y = 0; y <= (win->_maxy - n); y++) {
937                 win->_line[y].firstchar = win->_line[y + n].firstchar;
938                 win->_line[y].lastchar = win->_line[y + n].lastchar;
939                 for (x = 0; x <= win->_maxx; x++) {
940                         if ((win->_line[y].text[x].chars[0] != win->_line[y + n].text[x].chars[0]) ||
941                                         (win->_line[y].text[x].attr != win->_line[y + n].text[x].attr)) {
942                                 if (win->_line[y].firstchar == _NOCHANGE)
943                                         win->_line[y].firstchar = x;
944
945                                 win->_line[y].lastchar = x;
946
947                                 win->_line[y].text[x].chars[0] = win->_line[y + n].text[x].chars[0];
948                                 win->_line[y].text[x].attr = win->_line[y + n].text[x].attr;
949                         }
950                 }
951         }
952
953         for (y = (win->_maxy+1 - n); y <= win->_maxy; y++) {
954                 for (x = 0; x <= win->_maxx; x++) {
955                         if ((win->_line[y].text[x].chars[0] != ' ') ||
956                                         (win->_line[y].text[x].attr != A_NORMAL)) {
957                                 if (win->_line[y].firstchar == _NOCHANGE)
958                                         win->_line[y].firstchar = x;
959
960                                 win->_line[y].lastchar = x;
961
962                                 win->_line[y].text[x].chars[0] = ' ';
963                                 win->_line[y].text[x].attr = A_NORMAL;
964                         }
965                 }
966         }
967
968         // _nc_scroll_window(win, n, win->_regtop, win->_regbottom, win->_nc_bkgd);
969         // _nc_synchook(win);
970
971         return OK;
972 }
973 int wsetscrreg(WINDOW *win, int top, int bottom)
974 {
975         if (top >= 0 && top <= win->_maxy && bottom >= 0 &&
976             bottom <= win->_maxy && bottom > top) {
977                 win->_regtop = (NCURSES_SIZE_T) top;
978                 win->_regbottom = (NCURSES_SIZE_T) bottom;
979                 return OK;
980         }
981         return ERR;
982 }
983 // void wsyncdown (WINDOW *) {}
984 // void wsyncup (WINDOW *) {}
985 /* D */ void wtimeout(WINDOW *win, int _delay) { win->_delay = _delay; }
986 /* D */ int wtouchln(WINDOW *win, int y, int n, int changed)
987 {
988         int i;
989
990         // if ((n < 0) || (y < 0) || (y > win->_maxy))
991         //     return ERR;
992
993         for (i = y; i < y + n; i++) {
994                 if (i > win->_maxy)
995                         break;
996                 win->_line[i].firstchar = changed ? 0 : _NOCHANGE;
997                 win->_line[i].lastchar = changed ? win->_maxx : _NOCHANGE;
998         }
999         return OK;
1000 }
1001 // int wvline (WINDOW *,chtype,int) {}
1002 // int tigetflag (NCURSES_CONST char *) {}
1003 // int tigetnum (NCURSES_CONST char *) {}
1004 // char *tigetstr (NCURSES_CONST char *) {}
1005 // int putp (const char *) {}
1006 // #if NCURSES_TPARM_VARARGS
1007 // char *tparm (NCURSES_CONST char *, ...) {}
1008 // #else
1009 // char *tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long) {}
1010 // char *tparm_varargs (NCURSES_CONST char *, ...) {}
1011 // #endif