]> git.ipfire.org Git - thirdparty/newt.git/blob - newt.c
merged in and munged patches from #117464
[thirdparty/newt.git] / newt.c
1 #include "config.h"
2
3 #include <slang.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/signal.h>
8 #include <sys/time.h>
9 #include <sys/types.h>
10 #include <termios.h>
11 #include <unistd.h>
12 #include <wchar.h>
13
14 #ifdef HAVE_ALLOCA_H
15 #include <alloca.h>
16 #endif
17
18 #include "newt.h"
19 #include "newt_pr.h"
20
21 struct Window {
22 int height, width, top, left;
23 SLsmg_Char_Type * buffer;
24 char * title;
25 };
26
27 struct keymap {
28 char * str;
29 int code;
30 char * tc;
31 };
32
33 static struct Window windowStack[20];
34 static struct Window * currentWindow = NULL;
35
36 static char * helplineStack[20];
37 static char ** currentHelpline = NULL;
38
39 static int cursorRow, cursorCol;
40 static int needResize = 0;
41 static int cursorOn = 1;
42 static int trashScreen = 0;
43
44 static const char * defaultHelpLine =
45 " <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen"
46 ;
47
48 const struct newtColors newtDefaultColorPalette = {
49 "white", "blue", /* root fg, bg */
50 "black", "lightgray", /* border fg, bg */
51 "black", "lightgray", /* window fg, bg */
52 "white", "black", /* shadow fg, bg */
53 "red", "lightgray", /* title fg, bg */
54 "lightgray", "red", /* button fg, bg */
55 "red", "lightgray", /* active button fg, bg */
56 "yellow", "blue", /* checkbox fg, bg */
57 "blue", "brown", /* active checkbox fg, bg */
58 "yellow", "blue", /* entry box fg, bg */
59 "blue", "lightgray", /* label fg, bg */
60 "black", "lightgray", /* listbox fg, bg */
61 "yellow", "blue", /* active listbox fg, bg */
62 "black", "lightgray", /* textbox fg, bg */
63 "lightgray", "black", /* active textbox fg, bg */
64 "white", "blue", /* help line */
65 "yellow", "blue", /* root text */
66 "blue", /* scale full */
67 "red", /* scale empty */
68 "blue", "lightgray", /* disabled entry fg, bg */
69 "white", "blue", /* compact button fg, bg */
70 "yellow", "red", /* active & sel listbox */
71 "black", "brown" /* selected listbox */
72 };
73
74 static const struct keymap keymap[] = {
75 { "\033OA", NEWT_KEY_UP, "kh" },
76 { "\033[A", NEWT_KEY_UP, "ku" },
77 { "\033OB", NEWT_KEY_DOWN, "kd" },
78 { "\033[B", NEWT_KEY_DOWN, "kd" },
79 { "\033[C", NEWT_KEY_RIGHT, "kr" },
80 { "\033OC", NEWT_KEY_RIGHT, "kr" },
81 { "\033[D", NEWT_KEY_LEFT, "kl" },
82 { "\033OD", NEWT_KEY_LEFT, "kl" },
83 { "\033[H", NEWT_KEY_HOME, "kh" },
84 { "\033[1~", NEWT_KEY_HOME, "kh" },
85 { "\033Ow", NEWT_KEY_END, "kH" },
86 { "\033[4~", NEWT_KEY_END, "kH" },
87
88 { "\033[3~", NEWT_KEY_DELETE, "kl" },
89 { "\033[2~", NEWT_KEY_INSERT, NULL },
90
91 { "\033\t", NEWT_KEY_UNTAB, NULL },
92
93 { "\033[5~", NEWT_KEY_PGUP, NULL },
94 { "\033[6~", NEWT_KEY_PGDN, NULL },
95 { "\033V", NEWT_KEY_PGUP, "kH" },
96 { "\033v", NEWT_KEY_PGUP, "kH" },
97
98 { "\033[[A", NEWT_KEY_F1, NULL },
99 { "\033[[B", NEWT_KEY_F2, NULL },
100 { "\033[[C", NEWT_KEY_F3, NULL },
101 { "\033[[D", NEWT_KEY_F4, NULL },
102 { "\033[[E", NEWT_KEY_F5, NULL },
103
104 { "\033OP", NEWT_KEY_F1, NULL },
105 { "\033OQ", NEWT_KEY_F2, NULL },
106 { "\033OR", NEWT_KEY_F3, NULL },
107 { "\033OS", NEWT_KEY_F4, NULL },
108
109 { "\033[11~", NEWT_KEY_F1, NULL },
110 { "\033[12~", NEWT_KEY_F2, NULL },
111 { "\033[13~", NEWT_KEY_F3, NULL },
112 { "\033[14~", NEWT_KEY_F4, NULL },
113 { "\033[15~", NEWT_KEY_F5, NULL },
114 { "\033[17~", NEWT_KEY_F6, NULL },
115 { "\033[18~", NEWT_KEY_F7, NULL },
116 { "\033[19~", NEWT_KEY_F8, NULL },
117 { "\033[20~", NEWT_KEY_F9, NULL },
118 { "\033[21~", NEWT_KEY_F10, NULL },
119 { "\033[23~", NEWT_KEY_F11, NULL },
120 { "\033[24~", NEWT_KEY_F12, NULL },
121 { "\033", NEWT_KEY_ESCAPE, NULL },
122
123 { 0 }, /* LEAVE this one */
124 };
125 static char keyPrefix = '\033';
126
127 static const char ident[] = // ident friendly
128 "$Version: Newt windowing library v" VERSION " $"
129 "$Copyright: (C) 1996-2003 Red Hat, Inc. Written by Erik Troan $"
130 "$License: Lesser GNU Public License. $";
131
132 static newtSuspendCallback suspendCallback = NULL;
133 static void * suspendCallbackData = NULL;
134
135 void newtSetSuspendCallback(newtSuspendCallback cb, void * data) {
136 suspendCallback = cb;
137 suspendCallbackData = data;
138 }
139
140 static void handleSigwinch(int signum) {
141 needResize = 1;
142 }
143
144 static int getkeyInterruptHook(void) {
145 return -1;
146 }
147
148 int wstrlen(const char *str, int len) {
149 mbstate_t ps;
150 wchar_t tmp;
151 int nchars = 0;
152
153 if (!str) return 0;
154 if (!len) return 0;
155 if (len < 0) len = strlen(str);
156 memset(&ps,0,sizeof(mbstate_t));
157 while (len > 0) {
158 int x,y;
159
160 x = mbrtowc(&tmp,str,len,&ps);
161 if (x >0) {
162 str += x;
163 len -= x;
164 y = wcwidth(tmp);
165 if (y>0)
166 nchars+=y;
167 } else break;
168 }
169 return nchars;
170 }
171
172 static int getkey() {
173 int c;
174
175 while ((c = SLang_getkey()) == '\xC') { /* if Ctrl-L redraw whole screen */
176 SLsmg_touch_lines (0, SLtt_Screen_Rows - 1);
177 SLsmg_refresh();
178 }
179 return c;
180
181 }
182
183 void newtFlushInput(void) {
184 while (SLang_input_pending(0)) {
185 getkey();
186 }
187 }
188
189 void newtRefresh(void) {
190 SLsmg_refresh();
191 }
192
193 void newtSuspend(void) {
194 SLtt_set_cursor_visibility (1);
195 SLsmg_suspend_smg();
196 SLang_reset_tty();
197 SLtt_set_cursor_visibility (cursorOn);
198 }
199
200 int newtResume(void) {
201 SLsmg_resume_smg ();
202 SLsmg_refresh();
203 return SLang_init_tty(0, 0, 0);
204 }
205
206 void newtCls(void) {
207 SLsmg_set_color(NEWT_COLORSET_ROOT);
208 SLsmg_gotorc(0, 0);
209 SLsmg_erase_eos();
210
211 newtRefresh();
212 }
213
214 void newtResizeScreen(int redraw) {
215 SLtt_get_screen_size();
216 SLsmg_reinit_smg();
217 if (redraw) {
218 SLsmg_touch_lines (0, SLtt_Screen_Rows - 1);
219 newtRefresh();
220 }
221 }
222
223 int newtInit(void) {
224 char * MonoValue, * MonoEnv = "NEWT_MONO";
225 const char *lang;
226 int ret;
227
228 if ((lang = getenv("LC_ALL")) == NULL)
229 if ((lang = getenv("LC_CTYPE")) == NULL)
230 if ((lang = getenv("LANG")) == NULL)
231 lang = "";
232 if (strstr (lang, ".euc") != NULL)
233 trashScreen = 1;
234
235 (void) strlen(ident);
236
237 SLtt_get_terminfo();
238 SLtt_get_screen_size();
239
240 MonoValue = getenv(MonoEnv);
241 if ( MonoValue == NULL ) {
242 SLtt_Use_Ansi_Colors = 1;
243 } else {
244 SLtt_Use_Ansi_Colors = 0;
245 }
246
247 if ((ret = SLsmg_init_smg()) < 0)
248 return ret;
249 if ((ret = SLang_init_tty(0, 0, 0)) < 0)
250 return ret;
251
252 newtSetColors(newtDefaultColorPalette);
253 newtCursorOff();
254 /*initKeymap();*/
255
256 /*memset(&sa, 0, sizeof(sa));
257 sa.sa_handler = handleSigwinch;
258 sigaction(SIGWINCH, &sa, NULL);*/
259
260 SLsignal_intr(SIGWINCH, handleSigwinch);
261 SLang_getkey_intr_hook = getkeyInterruptHook;
262
263 return 0;
264 }
265
266 int newtFinished(void) {
267 SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
268 newtCursorOn();
269 SLsmg_refresh();
270 SLsmg_reset_smg();
271 SLang_reset_tty();
272
273 return 0;
274 }
275
276 void newtSetColors(struct newtColors colors) {
277 if (!SLtt_Use_Ansi_Colors) {
278 int i;
279
280 for (i = 2; i < 25; i++)
281 SLtt_set_mono(i, NULL, 0);
282
283 SLtt_set_mono(NEWT_COLORSET_SELLISTBOX, NULL, SLTT_BOLD_MASK);
284
285 SLtt_set_mono(NEWT_COLORSET_ACTBUTTON, NULL, SLTT_REV_MASK);
286 SLtt_set_mono(NEWT_COLORSET_ACTCHECKBOX, NULL, SLTT_REV_MASK);
287 SLtt_set_mono(NEWT_COLORSET_ACTLISTBOX, NULL, SLTT_REV_MASK);
288 SLtt_set_mono(NEWT_COLORSET_ACTTEXTBOX, NULL, SLTT_REV_MASK);
289
290 SLtt_set_mono(NEWT_COLORSET_ACTSELLISTBOX, NULL, SLTT_REV_MASK | SLTT_BOLD_MASK);
291
292 SLtt_set_mono(NEWT_COLORSET_DISENTRY, NULL, 0); // FIXME
293 SLtt_set_mono(NEWT_COLORSET_FULLSCALE, NULL, SLTT_ULINE_MASK | SLTT_REV_MASK);
294 SLtt_set_mono(NEWT_COLORSET_EMPTYSCALE, NULL, SLTT_ULINE_MASK);
295 return;
296 }
297 SLtt_set_color(NEWT_COLORSET_ROOT, "", colors.rootFg, colors.rootBg);
298 SLtt_set_color(NEWT_COLORSET_BORDER, "", colors.borderFg, colors.borderBg);
299 SLtt_set_color(NEWT_COLORSET_WINDOW, "", colors.windowFg, colors.windowBg);
300 SLtt_set_color(NEWT_COLORSET_SHADOW, "", colors.shadowFg, colors.shadowBg);
301 SLtt_set_color(NEWT_COLORSET_TITLE, "", colors.titleFg, colors.titleBg);
302 SLtt_set_color(NEWT_COLORSET_BUTTON, "", colors.buttonFg, colors.buttonBg);
303 SLtt_set_color(NEWT_COLORSET_ACTBUTTON, "", colors.actButtonFg,
304 colors.actButtonBg);
305 SLtt_set_color(NEWT_COLORSET_CHECKBOX, "", colors.checkboxFg,
306 colors.checkboxBg);
307 SLtt_set_color(NEWT_COLORSET_ACTCHECKBOX, "", colors.actCheckboxFg,
308 colors.actCheckboxBg);
309 SLtt_set_color(NEWT_COLORSET_ENTRY, "", colors.entryFg, colors.entryBg);
310 SLtt_set_color(NEWT_COLORSET_LABEL, "", colors.labelFg, colors.labelBg);
311 SLtt_set_color(NEWT_COLORSET_LISTBOX, "", colors.listboxFg,
312 colors.listboxBg);
313 SLtt_set_color(NEWT_COLORSET_ACTLISTBOX, "", colors.actListboxFg,
314 colors.actListboxBg);
315 SLtt_set_color(NEWT_COLORSET_TEXTBOX, "", colors.textboxFg,
316 colors.textboxBg);
317 SLtt_set_color(NEWT_COLORSET_ACTTEXTBOX, "", colors.actTextboxFg,
318 colors.actTextboxBg);
319 SLtt_set_color(NEWT_COLORSET_HELPLINE, "", colors.helpLineFg,
320 colors.helpLineBg);
321 SLtt_set_color(NEWT_COLORSET_ROOTTEXT, "", colors.rootTextFg,
322 colors.rootTextBg);
323
324 SLtt_set_color(NEWT_COLORSET_EMPTYSCALE, "", "white",
325 colors.emptyScale);
326 SLtt_set_color(NEWT_COLORSET_FULLSCALE, "", "white",
327 colors.fullScale);
328 SLtt_set_color(NEWT_COLORSET_DISENTRY, "", colors.disabledEntryFg,
329 colors.disabledEntryBg);
330
331 SLtt_set_color(NEWT_COLORSET_COMPACTBUTTON, "", colors.compactButtonFg,
332 colors.compactButtonBg);
333
334 SLtt_set_color(NEWT_COLORSET_ACTSELLISTBOX, "", colors.actSelListboxFg,
335 colors.actSelListboxBg);
336 SLtt_set_color(NEWT_COLORSET_SELLISTBOX, "", colors.selListboxFg,
337 colors.selListboxBg);
338 }
339
340 int newtGetKey(void) {
341 int key;
342 char buf[10], * chptr = buf;
343 const struct keymap * curr;
344
345 do {
346 key = getkey();
347 if (key == 0xFFFF) {
348 if (needResize) {
349 needResize = 0;
350 return NEWT_KEY_RESIZE;
351 }
352
353 /* ignore other signals */
354 continue;
355 }
356
357 if (key == NEWT_KEY_SUSPEND && suspendCallback)
358 suspendCallback(suspendCallbackData);
359 } while (key == NEWT_KEY_SUSPEND);
360
361 switch (key) {
362 case 'v' | 0x80:
363 case 'V' | 0x80:
364 return NEWT_KEY_PGUP;
365
366 case 22:
367 return NEWT_KEY_PGDN;
368
369 return NEWT_KEY_BKSPC;
370 case 0x7f:
371 return NEWT_KEY_BKSPC;
372
373 case 0x08:
374 return NEWT_KEY_BKSPC;
375
376 default:
377 if (key != keyPrefix) return key;
378 }
379
380 memset(buf, 0, sizeof(buf));
381
382 *chptr++ = key;
383 while (SLang_input_pending(5)) {
384 key = getkey();
385 if (key == keyPrefix) {
386 /* he hit unknown keys too many times -- start over */
387 memset(buf, 0, sizeof(buf));
388 chptr = buf;
389 }
390
391 *chptr++ = key;
392
393 /* this search should use bsearch(), but when we only look through
394 a list of 20 (or so) keymappings, it's probably faster just to
395 do a inline linear search */
396
397 for (curr = keymap; curr->code; curr++) {
398 if (curr->str) {
399 if (!strcmp(curr->str, buf))
400 return curr->code;
401 }
402 }
403 }
404
405 for (curr = keymap; curr->code; curr++) {
406 if (curr->str) {
407 if (!strcmp(curr->str, buf))
408 return curr->code;
409 }
410 }
411
412 /* Looks like we were a bit overzealous in reading characters. Return
413 just the first character, and put everything else back in the buffer
414 for later */
415
416 chptr--;
417 while (chptr > buf)
418 SLang_ungetkey(*chptr--);
419
420 return *chptr;
421 }
422
423 void newtWaitForKey(void) {
424 newtRefresh();
425
426 getkey();
427 newtClearKeyBuffer();
428 }
429
430 void newtClearKeyBuffer(void) {
431 while (SLang_input_pending(1)) {
432 getkey();
433 }
434 }
435
436 int newtOpenWindow(unsigned left, unsigned top, unsigned width, unsigned height,
437 const char * title) {
438 int j, row, col;
439 int n;
440 int i;
441
442 newtFlushInput();
443
444 if (!currentWindow) {
445 currentWindow = windowStack;
446 } else {
447 currentWindow++;
448 }
449
450 currentWindow->left = left;
451 currentWindow->top = top;
452 currentWindow->width = width;
453 currentWindow->height = height;
454 currentWindow->title = title ? strdup(title) : NULL;
455
456 currentWindow->buffer = malloc(sizeof(SLsmg_Char_Type) * (width + 3) * (height + 3));
457
458 row = top - 1;
459 col = left - 1;
460 /* clip to the current screen bounds - msw */
461 if (row < 0)
462 row = 0;
463 if (col < 0)
464 col = 0;
465 if (left + width > SLtt_Screen_Cols)
466 width = SLtt_Screen_Cols - left;
467 if (top + height > SLtt_Screen_Rows)
468 height = SLtt_Screen_Rows - top;
469 n = 0;
470 for (j = 0; j < height + 3; j++, row++) {
471 SLsmg_gotorc(row, col);
472 SLsmg_read_raw(currentWindow->buffer + n,
473 currentWindow->width + 3);
474 n += currentWindow->width + 3;
475 }
476
477 newtTrashScreen();
478
479 SLsmg_set_color(NEWT_COLORSET_BORDER);
480 SLsmg_draw_box(top - 1, left - 1, height + 2, width + 2);
481
482 if (currentWindow->title) {
483 i = wstrlen(currentWindow->title,-1) + 4;
484 i = ((width - i) / 2) + left;
485 SLsmg_gotorc(top - 1, i);
486 SLsmg_set_char_set(1);
487 SLsmg_write_char(SLSMG_RTEE_CHAR);
488 SLsmg_set_char_set(0);
489 SLsmg_write_char(' ');
490 SLsmg_set_color(NEWT_COLORSET_TITLE);
491 SLsmg_write_string((char *)currentWindow->title);
492 SLsmg_set_color(NEWT_COLORSET_BORDER);
493 SLsmg_write_char(' ');
494 SLsmg_set_char_set(1);
495 SLsmg_write_char(SLSMG_LTEE_CHAR);
496 SLsmg_set_char_set(0);
497 }
498
499 SLsmg_set_color(NEWT_COLORSET_WINDOW);
500 SLsmg_fill_region(top, left, height, width, ' ');
501
502 SLsmg_set_color(NEWT_COLORSET_SHADOW);
503 SLsmg_fill_region(top + height + 1, left, 1, width + 2, ' ');
504 SLsmg_fill_region(top, left + width + 1, height + 1, 1, ' ');
505
506 for (i = top; i < (top + height + 1); i++) {
507 SLsmg_gotorc(i, left + width + 1);
508 SLsmg_write_string(" ");
509 }
510
511 return 0;
512 }
513
514 int newtCenteredWindow(unsigned width, unsigned height, const char * title) {
515 unsigned top, left;
516
517 top = (SLtt_Screen_Rows - height) / 2;
518
519 /* I don't know why, but this seems to look better */
520 if ((SLtt_Screen_Rows % 2) && (top % 2)) top--;
521
522 left = (SLtt_Screen_Cols - width) / 2;
523
524 newtOpenWindow(left, top, width, height, title);
525
526 return 0;
527 }
528
529 void newtPopWindow(void) {
530 int j, row, col;
531 int n = 0;
532
533 row = col = 0;
534
535 row = currentWindow->top - 1;
536 col = currentWindow->left - 1;
537 if (row < 0)
538 row = 0;
539 if (col < 0)
540 col = 0;
541 for (j = 0; j < currentWindow->height + 3; j++, row++) {
542 SLsmg_gotorc(row, col);
543 SLsmg_write_raw(currentWindow->buffer + n,
544 currentWindow->width + 3);
545 n += currentWindow->width + 3;
546 }
547
548 free(currentWindow->buffer);
549 free(currentWindow->title);
550
551 if (currentWindow == windowStack)
552 currentWindow = NULL;
553 else
554 currentWindow--;
555
556 SLsmg_set_char_set(0);
557
558 newtTrashScreen();
559
560 newtRefresh();
561 }
562
563 void newtGetWindowPos(int * x, int * y) {
564 if (currentWindow) {
565 *x = currentWindow->left;
566 *y = currentWindow->top;
567 } else
568 *x = *y = 0;
569 }
570
571 void newtGetrc(int * row, int * col) {
572 *row = cursorRow;
573 *col = cursorCol;
574 }
575
576 void newtGotorc(int newRow, int newCol) {
577 if (currentWindow) {
578 newRow += currentWindow->top;
579 newCol += currentWindow->left;
580 }
581
582 cursorRow = newRow;
583 cursorCol = newCol;
584 SLsmg_gotorc(cursorRow, cursorCol);
585 }
586
587 void newtDrawBox(int left, int top, int width, int height, int shadow) {
588 if (currentWindow) {
589 top += currentWindow->top;
590 left += currentWindow->left;
591 }
592
593 SLsmg_draw_box(top, left, height, width);
594
595 if (shadow) {
596 SLsmg_set_color(NEWT_COLORSET_SHADOW);
597 SLsmg_fill_region(top + height, left + 1, 1, width - 1, ' ');
598 SLsmg_fill_region(top + 1, left + width, height, 1, ' ');
599 }
600 }
601
602 void newtClearBox(int left, int top, int width, int height) {
603 if (currentWindow) {
604 top += currentWindow->top;
605 left += currentWindow->left;
606 }
607
608 SLsmg_fill_region(top, left, height, width, ' ');
609 }
610
611 #if 0
612 /* This doesn't seem to work quite right. I don't know why not, but when
613 I rsh from an rxvt into a box and run this code, the machine returns
614 console key's (\033[B) rather then xterm ones (\033OB). */
615 static void initKeymap(void) {
616 struct keymap * curr;
617
618 for (curr = keymap; curr->code; curr++) {
619 if (!curr->str)
620 curr->str = SLtt_tgetstr(curr->tc);
621 }
622
623 /* Newt's keymap handling is a bit broken. It assumes that any extended
624 keystrokes begin with ESC. If you're using a homebrek terminal you
625 will probably need to fix this, or just yell at me and I'll be so
626 ashamed of myself for doing it this way I'll fix it */
627
628 keyPrefix = 0x1b; /* ESC */
629 }
630 #endif
631
632 void newtDelay(unsigned usecs) {
633 fd_set set;
634 struct timeval tv;
635
636 FD_ZERO(&set);
637
638 tv.tv_sec = usecs / 1000000;
639 tv.tv_usec = usecs % 1000000;
640
641 select(0, &set, &set, &set, &tv);
642 }
643
644 struct eventResult newtDefaultEventHandler(newtComponent c,
645 struct event ev) {
646 struct eventResult er;
647
648 er.result = ER_IGNORED;
649 return er;
650 }
651
652 void newtRedrawHelpLine(void) {
653 char * buf;
654
655 SLsmg_set_color(NEWT_COLORSET_HELPLINE);
656
657 if (currentHelpline) {
658 /* buffer size needs to be wide enough to hold all the multibyte
659 currentHelpline + all the single byte ' ' to fill the line */
660 int wlen = wstrlen(*currentHelpline, -1);
661 int len;
662
663 if (wlen > SLtt_Screen_Cols)
664 wlen = SLtt_Screen_Cols;
665 len = strlen(*currentHelpline) + (SLtt_Screen_Cols - wlen);
666 buf = alloca(len + 1);
667 memset(buf, ' ', len);
668 memcpy(buf, *currentHelpline, strlen(*currentHelpline));
669 buf[len] = '\0';
670 } else {
671 buf = alloca(SLtt_Screen_Cols + 1);
672 memset(buf, ' ', SLtt_Screen_Cols);
673 buf[SLtt_Screen_Cols] = '\0';
674 }
675 SLsmg_gotorc(SLtt_Screen_Rows - 1, 0);
676 SLsmg_write_string(buf);
677 }
678
679 void newtPushHelpLine(const char * text) {
680 if (!text)
681 text = defaultHelpLine;
682
683 if (currentHelpline)
684 (*(++currentHelpline)) = strdup(text);
685 else {
686 currentHelpline = helplineStack;
687 *currentHelpline = strdup(text);
688 }
689
690 newtRedrawHelpLine();
691 }
692
693 void newtPopHelpLine(void) {
694 if (!currentHelpline) return;
695
696 free(*currentHelpline);
697 if (currentHelpline == helplineStack)
698 currentHelpline = NULL;
699 else
700 currentHelpline--;
701
702 newtRedrawHelpLine();
703 }
704
705 void newtDrawRootText(int col, int row, const char * text) {
706 SLsmg_set_color(NEWT_COLORSET_ROOTTEXT);
707
708 if (col < 0) {
709 col = SLtt_Screen_Cols + col;
710 }
711
712 if (row < 0) {
713 row = SLtt_Screen_Rows + row;
714 }
715
716 SLsmg_gotorc(row, col);
717 SLsmg_write_string((char *)text);
718 }
719
720 int newtSetFlags(int oldFlags, int newFlags, enum newtFlagsSense sense) {
721 switch (sense) {
722 case NEWT_FLAGS_SET:
723 return oldFlags | newFlags;
724
725 case NEWT_FLAGS_RESET:
726 return oldFlags & (~newFlags);
727
728 case NEWT_FLAGS_TOGGLE:
729 return oldFlags ^ newFlags;
730
731 default:
732 return oldFlags;
733 }
734 }
735
736 void newtBell(void)
737 {
738 SLtt_beep();
739 }
740
741 void newtGetScreenSize(int * cols, int * rows) {
742 if (rows) *rows = SLtt_Screen_Rows;
743 if (cols) *cols = SLtt_Screen_Cols;
744 }
745
746 void newtDefaultPlaceHandler(newtComponent c, int newLeft, int newTop) {
747 c->left = newLeft;
748 c->top = newTop;
749 }
750
751 void newtDefaultMappedHandler(newtComponent c, int isMapped) {
752 c->isMapped = isMapped;
753 }
754
755 void newtCursorOff(void) {
756 cursorOn = 0;
757 SLtt_set_cursor_visibility (cursorOn);
758 }
759
760 void newtCursorOn(void) {
761 cursorOn = 1;
762 SLtt_set_cursor_visibility (cursorOn);
763 }
764
765 void newtTrashScreen(void) {
766 if (trashScreen)
767 SLsmg_touch_lines (0, SLtt_Screen_Rows - 1);
768 }
769