5 #include <sys/signal.h>
16 int height
, width
, top
, left
;
27 static struct Window windowStack
[20];
28 static struct Window
* currentWindow
= NULL
;
30 static char * helplineStack
[20];
31 static char ** currentHelpline
= NULL
;
33 static int cursorRow
, cursorCol
;
34 static int needResize
;
35 static int cursorOn
= 1;
37 static const char * defaultHelpLine
=
38 " <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen"
41 const struct newtColors newtDefaultColorPalette
= {
42 "white", "blue", /* root fg, bg */
43 "black", "lightgray", /* border fg, bg */
44 "black", "lightgray", /* window fg, bg */
45 "white", "black", /* shadow fg, bg */
46 "red", "lightgray", /* title fg, bg */
47 "lightgray", "red", /* button fg, bg */
48 "red", "lightgray", /* active button fg, bg */
49 "yellow", "blue", /* checkbox fg, bg */
50 "blue", "brown", /* active checkbox fg, bg */
51 "yellow", "blue", /* entry box fg, bg */
52 "blue", "lightgray", /* label fg, bg */
53 "black", "lightgray", /* listbox fg, bg */
54 "yellow", "blue", /* active listbox fg, bg */
55 "black", "lightgray", /* textbox fg, bg */
56 "lightgray", "black", /* active textbox fg, bg */
57 "white", "blue", /* help line */
58 "yellow", "blue", /* root text */
59 "blue", /* scale full */
60 "red", /* scale empty */
61 "blue", "lightgray", /* disabled entry fg, bg */
62 "white", "blue", /* compact button fg, bg */
63 "yellow", "red", /* active & sel listbox */
64 "black", "brown" /* selected listbox */
67 static const struct keymap keymap
[] = {
68 { "\033OA", NEWT_KEY_UP
, "kh" },
69 { "\033[A", NEWT_KEY_UP
, "ku" },
70 { "\033OB", NEWT_KEY_DOWN
, "kd" },
71 { "\033[B", NEWT_KEY_DOWN
, "kd" },
72 { "\033[C", NEWT_KEY_RIGHT
, "kr" },
73 { "\033OC", NEWT_KEY_RIGHT
, "kr" },
74 { "\033[D", NEWT_KEY_LEFT
, "kl" },
75 { "\033OD", NEWT_KEY_LEFT
, "kl" },
76 { "\033[H", NEWT_KEY_HOME
, "kh" },
77 { "\033[1~", NEWT_KEY_HOME
, "kh" },
78 { "\033Ow", NEWT_KEY_END
, "kH" },
79 { "\033[4~", NEWT_KEY_END
, "kH" },
81 { "\033[3~", NEWT_KEY_DELETE
, "kl" },
82 { "\033[2~", NEWT_KEY_INSERT
, NULL
},
84 { "\033\t", NEWT_KEY_UNTAB
, NULL
},
86 { "\033[5~", NEWT_KEY_PGUP
, NULL
},
87 { "\033[6~", NEWT_KEY_PGDN
, NULL
},
88 { "\033V", NEWT_KEY_PGUP
, "kH" },
89 { "\033v", NEWT_KEY_PGUP
, "kH" },
91 { "\033[[A", NEWT_KEY_F1
, NULL
},
92 { "\033[[B", NEWT_KEY_F2
, NULL
},
93 { "\033[[C", NEWT_KEY_F3
, NULL
},
94 { "\033[[D", NEWT_KEY_F4
, NULL
},
95 { "\033[[E", NEWT_KEY_F5
, NULL
},
97 { "\033OP", NEWT_KEY_F1
, NULL
},
98 { "\033OQ", NEWT_KEY_F2
, NULL
},
99 { "\033OR", NEWT_KEY_F3
, NULL
},
100 { "\033OS", NEWT_KEY_F4
, NULL
},
102 { "\033[11~", NEWT_KEY_F1
, NULL
},
103 { "\033[12~", NEWT_KEY_F2
, NULL
},
104 { "\033[13~", NEWT_KEY_F3
, NULL
},
105 { "\033[14~", NEWT_KEY_F4
, NULL
},
106 { "\033[15~", NEWT_KEY_F5
, NULL
},
107 { "\033[17~", NEWT_KEY_F6
, NULL
},
108 { "\033[18~", NEWT_KEY_F7
, NULL
},
109 { "\033[19~", NEWT_KEY_F8
, NULL
},
110 { "\033[20~", NEWT_KEY_F9
, NULL
},
111 { "\033[21~", NEWT_KEY_F10
, NULL
},
112 { "\033[23~", NEWT_KEY_F11
, NULL
},
113 { "\033[24~", NEWT_KEY_F12
, NULL
},
115 { NULL
, 0, NULL
}, /* LEAVE this one */
117 static char keyPrefix
= '\033';
119 static const char * version
= "Newt windowing library version " VERSION
120 " - (C) 1996-2000 Red Hat Software. "
121 "Redistributable under the term of the Library "
122 "GNU Public License. "
123 "Written by Erik Troan\n";
125 static newtSuspendCallback suspendCallback
= NULL
;
126 static void * suspendCallbackData
= NULL
;
128 void newtSetSuspendCallback(newtSuspendCallback cb
, void * data
) {
129 suspendCallback
= cb
;
130 suspendCallbackData
= data
;
133 static void handleSigwinch(int signum
) {
137 static int getkeyInterruptHook(void) {
141 void newtFlushInput(void) {
142 while (SLang_input_pending(0)) {
147 void newtRefresh(void) {
151 void newtSuspend(void) {
152 SLtt_set_cursor_visibility (1);
155 SLtt_set_cursor_visibility (cursorOn
);
158 void newtResume(void) {
161 SLang_init_tty(0, 0, 0);
165 SLsmg_set_color(NEWT_COLORSET_ROOT
);
172 void newtResizeScreen(int redraw
) {
173 newtPushHelpLine("");
175 SLtt_get_screen_size();
176 SLang_init_tty(0, 0, 0);
178 SLsmg_touch_lines (0, SLtt_Screen_Rows
- 1);
180 /* I don't know why I need this */
190 char * MonoValue
, * MonoEnv
= "NEWT_MONO";
192 /* initialize locale */
193 setlocale (LC_ALL
, "");
195 /* use the version variable just to be sure it gets included */
199 SLtt_get_screen_size();
201 MonoValue
= getenv(MonoEnv
);
202 if ( MonoValue
== NULL
) {
203 SLtt_Use_Ansi_Colors
= 1;
205 SLtt_Use_Ansi_Colors
= 0;
209 SLang_init_tty(0, 0, 0);
211 newtSetColors(newtDefaultColorPalette
);
215 /*memset(&sa, 0, sizeof(sa));
216 sa.sa_handler = handleSigwinch;
217 sigaction(SIGWINCH, &sa, NULL);*/
219 SLsignal_intr(SIGWINCH
, handleSigwinch
);
220 SLang_getkey_intr_hook
= getkeyInterruptHook
;
227 int newtFinished(void) {
228 SLsmg_gotorc(SLtt_Screen_Rows
- 1, 0);
237 void newtSetColors(struct newtColors colors
) {
238 SLtt_set_color(NEWT_COLORSET_ROOT
, "", colors
.rootFg
, colors
.rootBg
);
239 SLtt_set_color(NEWT_COLORSET_BORDER
, "", colors
.borderFg
, colors
.borderBg
);
240 SLtt_set_color(NEWT_COLORSET_WINDOW
, "", colors
.windowFg
, colors
.windowBg
);
241 SLtt_set_color(NEWT_COLORSET_SHADOW
, "", colors
.shadowFg
, colors
.shadowBg
);
242 SLtt_set_color(NEWT_COLORSET_TITLE
, "", colors
.titleFg
, colors
.titleBg
);
243 SLtt_set_color(NEWT_COLORSET_BUTTON
, "", colors
.buttonFg
, colors
.buttonBg
);
244 SLtt_set_color(NEWT_COLORSET_ACTBUTTON
, "", colors
.actButtonFg
,
246 SLtt_set_color(NEWT_COLORSET_CHECKBOX
, "", colors
.checkboxFg
,
248 SLtt_set_color(NEWT_COLORSET_ACTCHECKBOX
, "", colors
.actCheckboxFg
,
249 colors
.actCheckboxBg
);
250 SLtt_set_color(NEWT_COLORSET_ENTRY
, "", colors
.entryFg
, colors
.entryBg
);
251 SLtt_set_color(NEWT_COLORSET_LABEL
, "", colors
.labelFg
, colors
.labelBg
);
252 SLtt_set_color(NEWT_COLORSET_LISTBOX
, "", colors
.listboxFg
,
254 SLtt_set_color(NEWT_COLORSET_ACTLISTBOX
, "", colors
.actListboxFg
,
255 colors
.actListboxBg
);
256 SLtt_set_color(NEWT_COLORSET_TEXTBOX
, "", colors
.textboxFg
,
258 SLtt_set_color(NEWT_COLORSET_ACTTEXTBOX
, "", colors
.actTextboxFg
,
259 colors
.actTextboxBg
);
260 SLtt_set_color(NEWT_COLORSET_HELPLINE
, "", colors
.helpLineFg
,
262 SLtt_set_color(NEWT_COLORSET_ROOTTEXT
, "", colors
.rootTextFg
,
265 SLtt_set_color(NEWT_COLORSET_EMPTYSCALE
, "", "black",
267 SLtt_set_color(NEWT_COLORSET_FULLSCALE
, "", "black",
269 SLtt_set_color(NEWT_COLORSET_DISENTRY
, "", colors
.disabledEntryFg
,
270 colors
.disabledEntryBg
);
272 SLtt_set_color(NEWT_COLORSET_COMPACTBUTTON
, "", colors
.compactButtonFg
,
273 colors
.compactButtonBg
);
275 SLtt_set_color(NEWT_COLORSET_ACTSELLISTBOX
, "", colors
.actSelListboxFg
,
276 colors
.actSelListboxBg
);
277 SLtt_set_color(NEWT_COLORSET_SELLISTBOX
, "", colors
.selListboxFg
,
278 colors
.selListboxBg
);
281 int newtGetKey(void) {
283 char buf
[10], * chptr
= buf
;
284 const struct keymap
* curr
;
287 key
= SLang_getkey();
290 return NEWT_KEY_RESIZE
;
292 /* ignore other signals */
296 if (key
== NEWT_KEY_SUSPEND
&& suspendCallback
)
297 suspendCallback(suspendCallbackData
);
298 } while (key
== NEWT_KEY_SUSPEND
);
303 return NEWT_KEY_PGUP
;
306 return NEWT_KEY_PGDN
;
308 return NEWT_KEY_BKSPC
;
310 return NEWT_KEY_BKSPC
;
313 return NEWT_KEY_BKSPC
;
316 if (key
!= keyPrefix
) return key
;
319 memset(buf
, 0, sizeof(buf
));
322 while (SLang_input_pending(5)) {
323 key
= SLang_getkey();
324 if (key
== keyPrefix
) {
325 /* he hit unknown keys too many times -- start over */
326 memset(buf
, 0, sizeof(buf
));
332 /* this search should use bsearch(), but when we only look through
333 a list of 20 (or so) keymappings, it's probably faster just to
334 do a inline linear search */
336 for (curr
= keymap
; curr
->code
; curr
++) {
338 if (!strcmp(curr
->str
, buf
))
344 for (curr
= keymap
; curr
->code
; curr
++) {
346 if (!strcmp(curr
->str
, buf
))
351 /* Looks like we were a bit overzealous in reading characters. Return
352 just the first character, and put everything else back in the buffer
357 SLang_ungetkey(*chptr
--);
362 void newtWaitForKey(void) {
366 newtClearKeyBuffer();
369 void newtClearKeyBuffer(void) {
370 while (SLang_input_pending(1)) {
375 int newtOpenWindow(int left
, int top
, int width
, int height
,
376 const char * title
) {
383 if (!currentWindow
) {
384 currentWindow
= windowStack
;
389 currentWindow
->left
= left
;
390 currentWindow
->top
= top
;
391 currentWindow
->width
= width
;
392 currentWindow
->height
= height
;
393 currentWindow
->title
= title
? strdup(title
) : NULL
;
395 currentWindow
->buffer
= malloc(sizeof(short) * (width
+ 3) * (height
+ 3));
400 for (j
= 0; j
< height
+ 3; j
++, row
++) {
401 SLsmg_gotorc(row
, col
);
402 SLsmg_read_raw(currentWindow
->buffer
+ n
,
403 currentWindow
->width
+ 3);
404 n
+= currentWindow
->width
+ 3;
407 SLsmg_set_color(NEWT_COLORSET_BORDER
);
408 SLsmg_draw_box(top
- 1, left
- 1, height
+ 2, width
+ 2);
410 if (currentWindow
->title
) {
411 i
= strlen(currentWindow
->title
) + 4;
412 i
= ((width
- i
) / 2) + left
;
413 SLsmg_gotorc(top
- 1, i
);
414 SLsmg_set_char_set(1);
415 SLsmg_write_char(SLSMG_RTEE_CHAR
);
416 SLsmg_set_char_set(0);
417 SLsmg_write_char(' ');
418 SLsmg_set_color(NEWT_COLORSET_TITLE
);
419 SLsmg_write_string((char *)currentWindow
->title
);
420 SLsmg_set_color(NEWT_COLORSET_BORDER
);
421 SLsmg_write_char(' ');
422 SLsmg_set_char_set(1);
423 SLsmg_write_char(SLSMG_LTEE_CHAR
);
424 SLsmg_set_char_set(0);
427 SLsmg_set_color(NEWT_COLORSET_WINDOW
);
428 SLsmg_fill_region(top
, left
, height
, width
, ' ');
430 SLsmg_set_color(NEWT_COLORSET_SHADOW
);
431 SLsmg_fill_region(top
+ height
+ 1, left
, 1, width
+ 2, ' ');
432 SLsmg_fill_region(top
, left
+ width
+ 1, height
+ 1, 1, ' ');
434 for (i
= top
; i
< (top
+ height
+ 1); i
++) {
435 SLsmg_gotorc(i
, left
+ width
+ 1);
436 SLsmg_write_string(" ");
442 int newtCenteredWindow(int width
, int height
, const char * title
) {
445 top
= (SLtt_Screen_Rows
- height
) / 2;
447 /* I don't know why, but this seems to look better */
448 if ((SLtt_Screen_Rows
% 2) && (top
% 2)) top
--;
450 left
= (SLtt_Screen_Cols
- width
) / 2;
452 newtOpenWindow(left
, top
, width
, height
, title
);
457 void newtPopWindow(void) {
463 row
= currentWindow
->top
- 1;
464 col
= currentWindow
->left
- 1;
465 for (j
= 0; j
< currentWindow
->height
+ 3; j
++, row
++) {
466 SLsmg_gotorc(row
, col
);
467 SLsmg_write_raw(currentWindow
->buffer
+ n
,
468 currentWindow
->width
+ 3);
469 n
+= currentWindow
->width
+ 3;
472 free(currentWindow
->buffer
);
473 free(currentWindow
->title
);
475 if (currentWindow
== windowStack
)
476 currentWindow
= NULL
;
480 SLsmg_set_char_set(0);
485 void newtGetWindowPos(int * x
, int * y
) {
487 *x
= currentWindow
->left
;
488 *y
= currentWindow
->top
;
493 void newtGetrc(int * row
, int * col
) {
498 void newtGotorc(int newRow
, int newCol
) {
500 newRow
+= currentWindow
->top
;
501 newCol
+= currentWindow
->left
;
506 SLsmg_gotorc(cursorRow
, cursorCol
);
509 void newtDrawBox(int left
, int top
, int width
, int height
, int shadow
) {
511 top
+= currentWindow
->top
;
512 left
+= currentWindow
->left
;
515 SLsmg_draw_box(top
, left
, height
, width
);
518 SLsmg_set_color(NEWT_COLORSET_SHADOW
);
519 SLsmg_fill_region(top
+ height
, left
+ 1, 1, width
- 1, ' ');
520 SLsmg_fill_region(top
+ 1, left
+ width
, height
, 1, ' ');
524 void newtClearBox(int left
, int top
, int width
, int height
) {
526 top
+= currentWindow
->top
;
527 left
+= currentWindow
->left
;
530 SLsmg_fill_region(top
, left
, height
, width
, ' ');
534 /* This doesn't seem to work quite right. I don't know why not, but when
535 I rsh from an rxvt into a box and run this code, the machine returns
536 console key's (\033[B) rather then xterm ones (\033OB). */
537 static void initKeymap(void) {
538 struct keymap
* curr
;
540 for (curr
= keymap
; curr
->code
; curr
++) {
542 curr
->str
= SLtt_tgetstr(curr
->tc
);
545 /* Newt's keymap handling is a bit broken. It assumes that any extended
546 keystrokes begin with ESC. If you're using a homebrek terminal you
547 will probably need to fix this, or just yell at me and I'll be so
548 ashamed of myself for doing it this way I'll fix it */
550 keyPrefix
= 0x1b; /* ESC */
554 void newtDelay(int usecs
) {
560 tv
.tv_sec
= usecs
/ 1000000;
561 tv
.tv_usec
= usecs
% 1000000;
563 select(0, &set
, &set
, &set
, &tv
);
566 struct eventResult
newtDefaultEventHandler(newtComponent c
,
568 struct eventResult er
;
570 er
.result
= ER_IGNORED
;
574 void newtRedrawHelpLine(void) {
577 SLsmg_set_color(NEWT_COLORSET_HELPLINE
);
579 buf
= alloca(SLtt_Screen_Cols
+ 1);
580 memset(buf
, ' ', SLtt_Screen_Cols
);
581 buf
[SLtt_Screen_Cols
] = '\0';
584 memcpy(buf
, *currentHelpline
, strlen(*currentHelpline
));
586 SLsmg_gotorc(SLtt_Screen_Rows
- 1, 0);
587 SLsmg_write_string(buf
);
590 void newtPushHelpLine(const char * text
) {
592 text
= defaultHelpLine
;
595 (*(++currentHelpline
)) = strdup(text
);
597 currentHelpline
= helplineStack
;
598 *currentHelpline
= strdup(text
);
601 newtRedrawHelpLine();
604 void newtPopHelpLine(void) {
605 if (!currentHelpline
) return;
607 free(*currentHelpline
);
608 if (currentHelpline
== helplineStack
)
609 currentHelpline
= NULL
;
613 newtRedrawHelpLine();
616 void newtDrawRootText(int col
, int row
, const char * text
) {
617 SLsmg_set_color(NEWT_COLORSET_ROOTTEXT
);
620 col
= SLtt_Screen_Cols
+ col
;
624 row
= SLtt_Screen_Rows
+ row
;
627 SLsmg_gotorc(row
, col
);
628 SLsmg_write_string((char *)text
);
631 int newtSetFlags(int oldFlags
, int newFlags
, enum newtFlagsSense sense
) {
634 return oldFlags
| newFlags
;
636 case NEWT_FLAGS_RESET
:
637 return oldFlags
& (~newFlags
);
639 case NEWT_FLAGS_TOGGLE
:
640 return oldFlags
^ newFlags
;
652 void newtGetScreenSize(int * cols
, int * rows
) {
653 if (rows
) *rows
= SLtt_Screen_Rows
;
654 if (cols
) *cols
= SLtt_Screen_Cols
;
657 void newtDefaultPlaceHandler(newtComponent c
, int newLeft
, int newTop
) {
662 void newtDefaultMappedHandler(newtComponent c
, int isMapped
) {
663 c
->isMapped
= isMapped
;
666 void newtCursorOff(void) {
668 SLtt_set_cursor_visibility (cursorOn
);
671 void newtCursorOn(void) {
673 SLtt_set_cursor_visibility (cursorOn
);