Fix code to allow usage of -Wall in libpayload and the sample (trivial).
[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  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 /*
31  * This is a tiny implementation of the (n)curses library intended to be
32  * used in embedded/firmware/BIOS code where no libc or operating system
33  * environment is available and code size is very important.
34  *
35  * Design goals:
36  *  - Small object code.
37  *  - Self-contained.
38  *    - Doesn't require a libc (no glibc/uclibc/dietlibc/klibc/newlib).
39  *    - Works without any other external libraries or header files.
40  *  - Works without an underlying operating system.
41  *    - Doesn't use files, signals, syscalls, ttys, library calls, etc.
42  *  - Doesn't do any dynamic memory allocation (no malloc() and friends).
43  *     - All data structures are statically allocated.
44  *  - Supports standard VGA console (80x25) and serial port console.
45  *     - This includes character output and keyboard input over serial.
46  *  - Supports beep() through a minimal PC speaker driver.
47  *
48  * Limitations:
49  *  - Only implements a small subset of the (n)curses functions.
50  *  - Only implements very few sanity checks (for smaller code).
51  *     - Thus: Don't do obviously stupid things in your code.
52  *  - Doesn't implement the 'form', 'panel', and 'menu' extentions.
53  *  - Only implements C bindings (no C++, Ada95, or others).
54  *  - Doesn't include wide character support.
55  */
56
57 #include "local.h"
58
59 #undef _XOPEN_SOURCE_EXTENDED
60 #define _XOPEN_SOURCE_EXTENDED 1
61
62 #define MAX_WINDOWS 3
63
64 /* Statically allocate all structures (no malloc())! */
65 static WINDOW window_list[MAX_WINDOWS];
66 static int window_count = 1;
67
68 // struct ldat foo;
69 static struct ldat ldat_list[3];
70 static int ldat_count = 0;
71
72 /* One item bigger than SCREEN_X to reverse place for a NUL byte. */
73 static NCURSES_CH_T linebuf_list[SCREEN_Y * MAX_WINDOWS][SCREEN_X + 1];
74 static int linebuf_count = 0;
75
76 /* Globals */
77 int COLORS;             /* Currently unused? */
78 int COLOR_PAIRS;
79 WINDOW *stdscr;
80 WINDOW *curscr;
81 WINDOW *newscr;
82 int LINES;
83 int COLS;
84 int TABSIZE;
85 int ESCDELAY;
86 // char ttytype[];
87 // cchar_t *_nc_wacs;
88 SCREEN *SP;
89 chtype acs_map[128];
90
91 // FIXME: Ugly (and insecure!) hack!
92 char sprintf_tmp[1024];
93
94
95 int curses_flags = (F_ENABLE_CONSOLE | F_ENABLE_SERIAL);
96
97 /* Return bit mask for clearing color pair number if given ch has color */
98 #define COLOR_MASK(ch) (~(attr_t)((ch) & A_COLOR ? A_COLOR : 0))
99
100 /* Compute a rendition of the given char correct for the current context. */
101 static inline NCURSES_CH_T render_char(WINDOW *win, NCURSES_CH_T ch)
102 {
103         /* TODO. */
104         return ch;
105 }
106
107 /* Make render_char() visible while still allowing us to inline it below. */
108 NCURSES_CH_T _nc_render(WINDOW *win, NCURSES_CH_T ch)
109 {
110         return render_char(win, ch);
111 }
112
113 /*
114  * Implementations of most functions marked 'implemented' in tinycurses.h:
115  */
116
117 // int baudrate(void) {}
118 int beep(void)
119 {
120         /* TODO: Flash the screen if beeping fails? */
121         speaker_tone(1760, 500);        /* 1760 == note A6 */
122         return OK;
123 }
124 // bool can_change_color(void) {}
125 int cbreak(void) { /* TODO */ return 0; }
126 /* D */ int clearok(WINDOW *win, bool flag) { win->_clear = flag; return OK; }
127 // int color_content(short color, short *r, short *g, short *b) {}
128 // int curs_set(int) {}
129 // int def_prog_mode(void) {}
130 // int def_shell_mode(void) {}
131 // int delay_output(int) {}
132 // void delscreen(SCREEN *) {}
133 int delwin(WINDOW *win)
134 {
135         /* TODO: Don't try to delete stdscr. */
136         /* TODO: Don't delete parent windows before subwindows. */
137
138         // if (win->_flags & _SUBWIN)
139         //      touchwin(win->_parent);
140         // else if (curscr != 0)
141         //      touchwin(curscr);
142
143         // return _nc_freewin(win);
144         return OK;
145 }
146 WINDOW *derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx)
147 {
148         WINDOW *win = NULL;
149         int i;
150         int flags = _SUBWIN;
151
152         /* Make sure window fits inside the original one. */
153         if (begy < 0 || begx < 0 || orig == 0 || num_lines < 0
154             || num_columns < 0)
155                 return NULL;
156
157         if (begy + num_lines > orig->_maxy + 1
158             || begx + num_columns > orig->_maxx + 1)
159                 return NULL;
160
161         if (num_lines == 0)
162                 num_lines = orig->_maxy + 1 - begy;
163
164         if (num_columns == 0)
165                 num_columns = orig->_maxx + 1 - begx;
166
167         if (orig->_flags & _ISPAD)
168                 flags |= _ISPAD;
169
170         // FIXME
171         //// if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy,
172         ////                        orig->_begx + begx, flags)) == 0)
173         ////     return NULL;
174
175         win->_pary = begy;
176         win->_parx = begx;
177         WINDOW_ATTRS(win) = WINDOW_ATTRS(orig);
178         win->_nc_bkgd = orig->_nc_bkgd;
179
180         for (i = 0; i < num_lines; i++)
181                 win->_line[i].text = &orig->_line[begy++].text[begx];
182
183         win->_parent = orig;
184
185         return win;
186 }
187 int doupdate(void) { /* TODO */ return(*(int *)0); }
188 // WINDOW * dupwin (WINDOW *) {}
189 /* D */ int echo(void) { SP->_echo = TRUE; return OK; }
190 int endwin(void)
191 {
192         if (!SP)
193                 return ERR;
194
195         SP->_endwin = TRUE;
196         SP->_mouse_wrap(SP);
197         // _nc_screen_wrap();
198         // _nc_mvcur_wrap();       /* wrap up cursor addressing */
199         // return reset_shell_mode();
200         return OK;      // FIXME
201 }
202 // char erasechar (void) {}
203 // void filter (void) {}
204 // int flash(void) {}
205 // int flushinp (void) {}
206 // WINDOW *getwin (FILE *) {}
207
208 bool has_colors (void) { /* TODO */ return(*(bool *)0); }
209 // bool has_ic (void) {}
210 // bool has_il (void) {}
211 // void idcok (WINDOW *, bool) {}
212 // int idlok (WINDOW *, bool) {}
213 void immedok(WINDOW *win, bool flag) { win->_immed = flag; }
214 /** Note: Must _not_ be called twice! */
215 WINDOW *initscr(void)
216 {
217         int x, y;
218
219         // newterm(name, stdout, stdin);
220         // def_prog_mode();
221
222         if (curses_flags & F_ENABLE_CONSOLE) {
223                 /* Clear the screen and kill the cursor. */
224                 vga_clear();
225                 vga_cursor_enable(0);
226         }
227
228         // Speaker init?
229
230         stdscr = newwin(SCREEN_Y, SCREEN_X + 1, 0, 0);
231         // TODO: curscr, newscr?
232
233         for (y = 0; y < stdscr->_maxy; y++) {
234                 for (x = 0; x < stdscr->_maxx; x++) {
235                         stdscr->_line[y].text[x].chars[0] = ' ';
236                         stdscr->_line[y].text[x].attr = A_NORMAL;
237                 }
238         }
239
240         return stdscr;
241 }
242
243 // int intrflush (WINDOW *,bool) {}
244 /* D */ bool isendwin(void) { return ((SP == NULL) ? FALSE : SP->_endwin); }
245 // bool is_linetouched (WINDOW *,int) {}
246 // bool is_wintouched (WINDOW *) {}
247 // NCURSES_CONST char * keyname (int) {}
248 int keypad (WINDOW *win, bool flag) { /* TODO */ return 0; }
249 // char killchar (void) {}
250 /* D */ int leaveok(WINDOW *win, bool flag) { win->_leaveok = flag; return OK; }
251 // char *longname (void) {}
252 // int meta (WINDOW *,bool) {}
253 // int mvcur (int,int,int,int) {}
254 // int mvderwin (WINDOW *, int, int) {}
255 int mvprintw(int y, int x, const char *fmt, ...)
256 {
257         va_list argp;
258         int code;
259
260         if (move(y, x) == ERR)
261                 return ERR;
262
263         va_start(argp, fmt);
264         code = vwprintw(stdscr, fmt, argp);
265         va_end(argp);
266
267         return code;
268 }
269 // int mvscanw (int,int, NCURSES_CONST char *,...) {}
270 // int mvwin (WINDOW *,int,int) {}
271 int mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...)
272 {
273         va_list argp;
274         int code;
275
276         if (wmove(win, y, x) == ERR)
277                 return ERR;
278
279         va_start(argp, fmt);
280         code = vwprintw(win, fmt, argp);
281         va_end(argp);
282
283         return code;
284 }
285 // int mvwscanw (WINDOW *,int,int, NCURSES_CONST char *,...) {}
286 // int napms (int) {}
287 // WINDOW *newpad (int,int) {}
288 // SCREEN *newterm (NCURSES_CONST char *,FILE *,FILE *) {}
289 WINDOW *newwin(int num_lines, int num_columns, int begy, int begx)
290 {
291         int i;
292
293         /* Use next statically allocated window. */
294         // TODO: Error handling.
295         // TODO: WINDOWLIST?
296         WINDOW *win = &window_list[window_count++];
297
298         // bool is_pad = (flags & _ISPAD);
299
300         // TODO: Checks.
301
302         win->_cury = 0;
303         win->_curx = 0;
304         win->_maxy = num_lines - 1;
305         win->_maxx = num_columns - 1;
306         win->_begy = begy;
307         win->_begx = begx;
308         // win->_yoffset = SP->_topstolen;
309
310         win->_line = &ldat_list[ldat_count++];
311
312         /* FIXME: Is this right? Should the window attributes be normal? */
313         win->_color = PAIR_NUMBER(0);
314         win->_attrs = A_NORMAL;
315
316         for (i = 0; i < num_lines; i++)
317                 win->_line[i].text =
318                      (NCURSES_CH_T *)&linebuf_list[linebuf_count++];
319
320         return win;
321 }
322 /* D */ int nl(void) { SP->_nl = TRUE; return OK; }
323 int nocbreak(void) { /* TODO */ return(*(int *)0); }
324
325 /* D */ int noecho(void) { SP->_echo = FALSE; return OK; }
326 /* D */ int nonl(void) { SP->_nl = FALSE; return OK; }
327 // void noqiflush (void) {}
328 // int noraw (void) {}
329 // int notimeout (WINDOW *,bool) {}
330 // int overlay (const WINDOW*,WINDOW *) {}
331 // int overwrite (const WINDOW*,WINDOW *) {}
332 // int pair_content (short,short*,short*) {}
333 // int pechochar (WINDOW *, const chtype) {}
334 // int pnoutrefresh (WINDOW*,int,int,int,int,int,int) {}
335 // int prefresh (WINDOW *,int,int,int,int,int,int) {}
336 int printw(const char *fmt, ...)
337 {
338         va_list argp;
339         int code;
340
341         va_start(argp, fmt);
342         code = vwprintw(stdscr, fmt, argp);
343         va_end(argp);
344
345         return code;
346 }
347 // int putwin (WINDOW *, FILE *) {}
348 // void qiflush (void) {}
349 // int raw (void) {}
350 // int resetty (void) {}
351 // int reset_prog_mode (void) {}
352 // int reset_shell_mode (void) {}
353 // int ripoffline (int, int (*)(WINDOW *, int)) {}
354 // int savetty (void) {}
355 // int scanw (NCURSES_CONST char *,...) {}
356 // int scr_dump (const char *) {}
357 // int scr_init (const char *) {}
358 /* D */ int scrollok(WINDOW *win, bool flag) { win->_scroll = flag; return OK; }
359 // int scr_restore (const char *) {}
360 // int scr_set (const char *) {}
361 // SCREEN *set_term (SCREEN *) {}
362 // int slk_attroff (const chtype) {}
363 // int slk_attron (const chtype) {}
364 // int slk_attrset (const chtype) {}
365 // attr_t slk_attr (void) {}
366 // int slk_attr_set (const attr_t,short,void*) {}
367 // int slk_clear (void) {}
368 // int slk_color (short) {}
369 // int slk_init (int) {}
370 /* D */ char *slk_label(int n)
371 {
372         // TODO: Needed?
373         // if (SP == NULL || SP->_slk == NULL || n < 1 || n > SP->_slk->labcnt)
374         //      return NULL;
375         return SP->_slk->ent[n - 1].ent_text;
376 }
377 // int slk_noutrefresh (void) {}
378 // int slk_refresh (void) {}
379 // int slk_restore (void) {}
380 // int slk_set (int,const char *,int) {}
381 // int slk_touch (void) {}
382
383 // WINDOW *subpad (WINDOW *, int, int, int, int) {}
384 WINDOW *subwin(WINDOW *w, int l, int c, int y, int x)
385 {
386         return derwin(w, l, c, y - w->_begy, x - w->_begx);
387 }
388 // int syncok (WINDOW *, bool) {}
389 // chtype termattrs (void) {}
390 // char *termname (void) {}
391 // int typeahead (int) {}
392 int ungetch(int ch) { /* TODO */ return ERR; }
393 // void use_env (bool) {}
394 // int vidattr (chtype) {}
395 // int vidputs (chtype, int (*)(int)) {}
396 int vwprintw(WINDOW *win, const char *fmt, va_list argp)
397 {
398         vsprintf((char *)&sprintf_tmp, fmt, argp);
399
400         /* TODO: Error handling? */
401         return waddstr(win, (char *)&sprintf_tmp);
402 }
403 // int vwscanw (WINDOW *, NCURSES_CONST char *,va_list) {}
404 // int waddch (WINDOW *, const chtype) {}
405 int waddch(WINDOW *win, const chtype ch)
406 {
407         int code = ERR;
408         // NCURSES_CH_T wch;
409         // SetChar2(wch, ch);
410
411         win->_line[win->_cury].text[win->_curx].chars[0] = ch;
412
413         /* Use the window attributes - perhaps we also pull attributes from
414            the ch itself, I don't know */
415
416         win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win);
417         win->_curx++;   // FIXME
418
419         // if (win && (waddch_nosync(win, wch) != ERR)) {
420         //      _nc_synchook(win);
421         //      code = OK;
422         // }
423
424         return code;
425 }
426 // int waddchnstr (WINDOW *,const chtype *,int) {}
427 int waddnstr(WINDOW *win, const char *astr, int n)
428 {
429         int code = OK;
430         const char *str = astr;
431
432         if (!str)
433                 return ERR;
434
435         if (n < 0)
436                 n = strlen(astr);
437
438         while ((n-- > 0) && (*str != '\0')) {
439         // while (*str != '\0') {
440                 win->_line[win->_cury].text[win->_curx].chars[0] = *str++;
441                 win->_line[win->_cury].text[win->_curx].attr = WINDOW_ATTRS(win)
442 ;
443                 win->_curx++;   // FIXME
444
445                 // NCURSES_CH_T ch;
446                 // SetChar(ch, UChar(*str++), A_NORMAL);
447                 // if (_nc_waddch_nosync(win, ch) == ERR) {
448                 //      code = ERR;
449                 //      break;
450                 // }
451         }
452         return code;
453 }
454 int wattr_on(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
455 {
456         if (at & A_COLOR)
457                 win->_color = PAIR_NUMBER(at);
458         // toggle_attr_on(WINDOW_ATTRS(win), at);
459         return OK;
460 }
461 int wattr_off(WINDOW *win, attr_t at, void *opts GCC_UNUSED)
462 {
463         if (at & A_COLOR)
464                 win->_color = 0;
465         // toggle_attr_off(WINDOW_ATTRS(win), at);
466         return 0;
467 }
468 // int wbkgd (WINDOW *, chtype) {}
469 void wbkgdset(WINDOW *win, chtype ch) { /* TODO */ }
470 // int wborder (WINDOW *,chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype) {}
471 // int wchgat (WINDOW *, int, attr_t, short, const void *) {}
472 /* D */ int wclear(WINDOW *win)
473 {
474         if (werase(win) == ERR)
475                 return ERR;
476         win->_clear = TRUE;
477         return OK;
478 }
479 // int wclrtobot (WINDOW *) {}
480 int wclrtoeol(WINDOW *win) { /* TODO */ return(*(int *)0); }
481 int wcolor_set(WINDOW *win, short color_pair_number, void *opts)
482 {
483         if (!opts && (color_pair_number >= 0)
484             && (color_pair_number < COLOR_PAIRS)) {
485                 SET_WINDOW_PAIR(win, color_pair_number);
486                 if_EXT_COLORS(win->_color = color_pair_number);
487                 return OK;
488         }
489         return ERR;
490 }
491 // void wcursyncup (WINDOW *) {}
492 // int wdelch (WINDOW *) {}
493 // int wechochar (WINDOW *, const chtype) {}
494 int werase(WINDOW *win)
495 {
496         int x, y;
497         for (y = 0; y < win->_maxy; y++) {
498                 for (x = 0; x < win->_maxx; x++) {
499                         win->_line[y].text[x].chars[0] = ' ';
500                         win->_line[y].text[x].attr = WINDOW_ATTRS(win);
501                 }
502         }
503         return OK;
504 }
505
506 // int wgetnstr (WINDOW *,char *,int) {}
507 int whline(WINDOW *win, chtype ch, int n)
508 {
509         NCURSES_SIZE_T start, end;
510         struct ldat *line = &(win->_line[win->_cury]);
511         NCURSES_CH_T wch;
512
513         start = win->_curx;
514         end = start + n - 1;
515         if (end > win->_maxx)
516                 end = win->_maxx;
517
518         CHANGED_RANGE(line, start, end);
519
520         //// TODO:
521         //// if (ch == 0)
522         ////     SetChar2(wch, ACS_HLINE);
523         //// else
524         ////     SetChar2(wch, ch);
525         // Ugly hack:
526         wch.chars[0] = ((ch) & (chtype)A_CHARTEXT);
527         wch.attr = ((ch) & (chtype)A_ATTRIBUTES);
528         wch = _nc_render(win, wch);
529
530         while (end >= start) {
531                 line->text[end] = wch;
532                 end--;
533         }
534
535         //// _nc_synchook(win);
536
537         return OK;
538 }
539 /* D */ chtype winch(WINDOW *win)
540 {
541         //// TODO
542         // return (CharOf(win->_line[win->_cury].text[win->_curx]) |
543         //         AttrOf(win->_line[win->_cury].text[win->_curx]));
544         return OK;      // FIXME
545 }
546 // int winchnstr (WINDOW *, chtype *, int) {}
547 // int winnstr (WINDOW *, char *, int) {}
548 // int winsch (WINDOW *, chtype) {}
549 // int winsdelln (WINDOW *,int) {}
550 // int winsnstr (WINDOW *, const char *,int) {}
551 /* D */ int wmove(WINDOW *win, int y, int x)
552 {
553         if (!LEGALYX(win, y, x))
554                 return ERR;
555         win->_curx = (NCURSES_SIZE_T) x;
556         win->_cury = (NCURSES_SIZE_T) y;
557         win->_flags &= ~_WRAPPED;
558         win->_flags |= _HASMOVED;
559         return OK;
560 }
561
562
563 int wnoutrefresh(WINDOW *win)
564 {
565         // FIXME.
566         int x, y;
567
568         for (y = 0; y < win->_maxy; y++) {
569                 for (x = 0; x < win->_maxx; x++) {
570                         if (curses_flags & F_ENABLE_SERIAL)
571                                 serial_putchar(win->_line[y].text[x].chars[0]);
572
573                         if (curses_flags & F_ENABLE_CONSOLE) {
574                                 attr_t attr = win->_line[y].text[x].attr;
575                                 unsigned int c =
576                                   ((int)color_pairs[PAIR_NUMBER(attr)]) << 8;
577
578                                 /* Handle some of the attributes. */
579                                 if (attr & A_BOLD)
580                                         c |= 0x0800;
581                                 if (attr & A_DIM)
582                                         c &= ~0x800;
583                                 if (attr & A_REVERSE) {
584                                         unsigned char tmp = (c >> 8) & 0xf;
585                                         c = (c >> 4) & 0xf00;
586                                         c |= tmp << 12;
587                                 }
588
589                                 c |= win->_line[y].text[x].chars[0];
590                                 vga_putc(y, x, c);
591                         }
592                 }
593         }
594
595         return OK;
596 }
597
598 int wprintw(WINDOW *win, const char *fmt, ...)
599 {
600         va_list argp;
601         int code;
602
603         va_start(argp, fmt);
604         code = vwprintw(win, fmt, argp);
605         va_end(argp);
606
607         return code;
608 }
609 // int wredrawln (WINDOW *,int,int) {}
610 int wrefresh(WINDOW *win)
611 {
612         // FIXME
613         return wnoutrefresh(win);
614
615         // XXX
616         int code;
617
618         if (win == curscr) {
619                 curscr->_clear = TRUE;
620                 // code = doupdate();
621         } else if ((code = wnoutrefresh(win)) == OK) {
622                 if (win->_clear)
623                         newscr->_clear = TRUE;
624                 // code = doupdate();
625                 /*
626                  * Reset the clearok() flag in case it was set for the special
627                  * case in hardscroll.c (if we don't reset it here, we'll get 2
628                  * refreshes because the flag is copied from stdscr to newscr).
629                  * Resetting the flag shouldn't do any harm, anyway.
630                  */
631                 win->_clear = FALSE;
632         }
633
634         return code;
635 }
636 // int wscanw (WINDOW *, NCURSES_CONST char *,...) {}
637 int wscrl(WINDOW *win, int n)
638 {
639         if (!win->_scroll)
640                 return ERR;
641
642         if (n != 0) {
643                 // _nc_scroll_window(win, n, win->_regtop, win->_regbottom, win->_nc_bkgd);
644                 // _nc_synchook(win);
645         }
646         return OK;
647 }
648 int wsetscrreg(WINDOW *win, int top, int bottom)
649 {
650         if (top >= 0 && top <= win->_maxy && bottom >= 0 &&
651             bottom <= win->_maxy && bottom > top) {
652                 win->_regtop = (NCURSES_SIZE_T) top;
653                 win->_regbottom = (NCURSES_SIZE_T) bottom;
654                 return OK;
655         }
656         return ERR;
657 }
658 // void wsyncdown (WINDOW *) {}
659 // void wsyncup (WINDOW *) {}
660 // void wtimeout (WINDOW *,int) {}
661 /* D */ int wtouchln(WINDOW *win, int y, int n, int changed)
662 {
663         int i;
664
665         // if ((n < 0) || (y < 0) || (y > win->_maxy))
666         //     return ERR;
667
668         for (i = y; i < y + n; i++) {
669                 if (i > win->_maxy)
670                         break;
671                 win->_line[i].firstchar = changed ? 0 : _NOCHANGE;
672                 win->_line[i].lastchar = changed ? win->_maxx : _NOCHANGE;
673         }
674         return OK;
675 }
676 // int wvline (WINDOW *,chtype,int) {}
677 // int tigetflag (NCURSES_CONST char *) {}
678 // int tigetnum (NCURSES_CONST char *) {}
679 // char *tigetstr (NCURSES_CONST char *) {}
680 // int putp (const char *) {}
681 // #if NCURSES_TPARM_VARARGS
682 // char *tparm (NCURSES_CONST char *, ...) {}
683 // #else
684 // char *tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long) {}
685 // char *tparm_varargs (NCURSES_CONST char *, ...) {}
686 // #endif