5 #include <sys/signal.h>
15 int height
, width
, top
, left
;
26 static struct Window windowStack
[20];
27 static struct Window
* currentWindow
= NULL
;
29 static char * helplineStack
[20];
30 static char ** currentHelpline
= NULL
;
32 static int cursorRow
, cursorCol
;
33 static int needResize
;
34 static int cursorOn
= 1;
35 static int trashScreen
= 0;
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 #if defined(THIS_DOESNT_WORK)
173 void newtResizeScreen(int redraw
) {
174 newtPushHelpLine("");
176 SLtt_get_screen_size();
177 SLang_init_tty(0, 0, 0);
179 SLsmg_touch_lines (0, SLtt_Screen_Rows
- 1);
181 /* I don't know why I need this */
192 char * MonoValue
, * MonoEnv
= "NEWT_MONO", * lang
;
194 lang
= getenv ("LANG");
195 if (lang
&& !strcasecmp (lang
, "ja_JP.eucJP"))
198 /* use the version variable just to be sure it gets included */
202 SLtt_get_screen_size();
204 MonoValue
= getenv(MonoEnv
);
205 if ( MonoValue
== NULL
) {
206 SLtt_Use_Ansi_Colors
= 1;
208 SLtt_Use_Ansi_Colors
= 0;
212 SLang_init_tty(0, 0, 0);
214 newtSetColors(newtDefaultColorPalette
);
218 /*memset(&sa, 0, sizeof(sa));
219 sa.sa_handler = handleSigwinch;
220 sigaction(SIGWINCH, &sa, NULL);*/
222 SLsignal_intr(SIGWINCH
, handleSigwinch
);
223 SLang_getkey_intr_hook
= getkeyInterruptHook
;
230 int newtFinished(void) {
231 SLsmg_gotorc(SLtt_Screen_Rows
- 1, 0);
240 void newtSetColors(struct newtColors colors
) {
241 SLtt_set_color(NEWT_COLORSET_ROOT
, "", colors
.rootFg
, colors
.rootBg
);
242 SLtt_set_color(NEWT_COLORSET_BORDER
, "", colors
.borderFg
, colors
.borderBg
);
243 SLtt_set_color(NEWT_COLORSET_WINDOW
, "", colors
.windowFg
, colors
.windowBg
);
244 SLtt_set_color(NEWT_COLORSET_SHADOW
, "", colors
.shadowFg
, colors
.shadowBg
);
245 SLtt_set_color(NEWT_COLORSET_TITLE
, "", colors
.titleFg
, colors
.titleBg
);
246 SLtt_set_color(NEWT_COLORSET_BUTTON
, "", colors
.buttonFg
, colors
.buttonBg
);
247 SLtt_set_color(NEWT_COLORSET_ACTBUTTON
, "", colors
.actButtonFg
,
249 SLtt_set_color(NEWT_COLORSET_CHECKBOX
, "", colors
.checkboxFg
,
251 SLtt_set_color(NEWT_COLORSET_ACTCHECKBOX
, "", colors
.actCheckboxFg
,
252 colors
.actCheckboxBg
);
253 SLtt_set_color(NEWT_COLORSET_ENTRY
, "", colors
.entryFg
, colors
.entryBg
);
254 SLtt_set_color(NEWT_COLORSET_LABEL
, "", colors
.labelFg
, colors
.labelBg
);
255 SLtt_set_color(NEWT_COLORSET_LISTBOX
, "", colors
.listboxFg
,
257 SLtt_set_color(NEWT_COLORSET_ACTLISTBOX
, "", colors
.actListboxFg
,
258 colors
.actListboxBg
);
259 SLtt_set_color(NEWT_COLORSET_TEXTBOX
, "", colors
.textboxFg
,
261 SLtt_set_color(NEWT_COLORSET_ACTTEXTBOX
, "", colors
.actTextboxFg
,
262 colors
.actTextboxBg
);
263 SLtt_set_color(NEWT_COLORSET_HELPLINE
, "", colors
.helpLineFg
,
265 SLtt_set_color(NEWT_COLORSET_ROOTTEXT
, "", colors
.rootTextFg
,
268 SLtt_set_color(NEWT_COLORSET_EMPTYSCALE
, "", "black",
270 SLtt_set_color(NEWT_COLORSET_FULLSCALE
, "", "black",
272 SLtt_set_color(NEWT_COLORSET_DISENTRY
, "", colors
.disabledEntryFg
,
273 colors
.disabledEntryBg
);
275 SLtt_set_color(NEWT_COLORSET_COMPACTBUTTON
, "", colors
.compactButtonFg
,
276 colors
.compactButtonBg
);
278 SLtt_set_color(NEWT_COLORSET_ACTSELLISTBOX
, "", colors
.actSelListboxFg
,
279 colors
.actSelListboxBg
);
280 SLtt_set_color(NEWT_COLORSET_SELLISTBOX
, "", colors
.selListboxFg
,
281 colors
.selListboxBg
);
284 int newtGetKey(void) {
286 char buf
[10], * chptr
= buf
;
287 const struct keymap
* curr
;
290 key
= SLang_getkey();
293 return NEWT_KEY_RESIZE
;
295 /* ignore other signals */
299 if (key
== NEWT_KEY_SUSPEND
&& suspendCallback
)
300 suspendCallback(suspendCallbackData
);
301 } while (key
== NEWT_KEY_SUSPEND
);
306 return NEWT_KEY_PGUP
;
309 return NEWT_KEY_PGDN
;
311 return NEWT_KEY_BKSPC
;
313 return NEWT_KEY_BKSPC
;
316 return NEWT_KEY_BKSPC
;
319 if (key
!= keyPrefix
) return key
;
322 memset(buf
, 0, sizeof(buf
));
325 while (SLang_input_pending(5)) {
326 key
= SLang_getkey();
327 if (key
== keyPrefix
) {
328 /* he hit unknown keys too many times -- start over */
329 memset(buf
, 0, sizeof(buf
));
335 /* this search should use bsearch(), but when we only look through
336 a list of 20 (or so) keymappings, it's probably faster just to
337 do a inline linear search */
339 for (curr
= keymap
; curr
->code
; curr
++) {
341 if (!strcmp(curr
->str
, buf
))
347 for (curr
= keymap
; curr
->code
; curr
++) {
349 if (!strcmp(curr
->str
, buf
))
354 /* Looks like we were a bit overzealous in reading characters. Return
355 just the first character, and put everything else back in the buffer
360 SLang_ungetkey(*chptr
--);
365 void newtWaitForKey(void) {
369 newtClearKeyBuffer();
372 void newtClearKeyBuffer(void) {
373 while (SLang_input_pending(1)) {
378 int newtOpenWindow(int left
, int top
, int width
, int height
,
379 const char * title
) {
386 if (!currentWindow
) {
387 currentWindow
= windowStack
;
392 currentWindow
->left
= left
;
393 currentWindow
->top
= top
;
394 currentWindow
->width
= width
;
395 currentWindow
->height
= height
;
396 currentWindow
->title
= title
? strdup(title
) : NULL
;
398 currentWindow
->buffer
= malloc(sizeof(short) * (width
+ 3) * (height
+ 3));
402 /* clip to the current screen bounds - msw */
407 if (left
+ width
> SLtt_Screen_Cols
)
408 width
= SLtt_Screen_Cols
- left
;
409 if (top
+ height
> SLtt_Screen_Rows
)
410 height
= SLtt_Screen_Rows
- top
;
412 for (j
= 0; j
< height
+ 3; j
++, row
++) {
413 SLsmg_gotorc(row
, col
);
414 SLsmg_read_raw(currentWindow
->buffer
+ n
,
415 currentWindow
->width
+ 3);
416 n
+= currentWindow
->width
+ 3;
421 SLsmg_set_color(NEWT_COLORSET_BORDER
);
422 SLsmg_draw_box(top
- 1, left
- 1, height
+ 2, width
+ 2);
424 if (currentWindow
->title
) {
425 i
= strlen(currentWindow
->title
) + 4;
426 i
= ((width
- i
) / 2) + left
;
427 SLsmg_gotorc(top
- 1, i
);
428 SLsmg_set_char_set(1);
429 SLsmg_write_char(SLSMG_RTEE_CHAR
);
430 SLsmg_set_char_set(0);
431 SLsmg_write_char(' ');
432 SLsmg_set_color(NEWT_COLORSET_TITLE
);
433 SLsmg_write_string((char *)currentWindow
->title
);
434 SLsmg_set_color(NEWT_COLORSET_BORDER
);
435 SLsmg_write_char(' ');
436 SLsmg_set_char_set(1);
437 SLsmg_write_char(SLSMG_LTEE_CHAR
);
438 SLsmg_set_char_set(0);
441 SLsmg_set_color(NEWT_COLORSET_WINDOW
);
442 SLsmg_fill_region(top
, left
, height
, width
, ' ');
444 SLsmg_set_color(NEWT_COLORSET_SHADOW
);
445 SLsmg_fill_region(top
+ height
+ 1, left
, 1, width
+ 2, ' ');
446 SLsmg_fill_region(top
, left
+ width
+ 1, height
+ 1, 1, ' ');
448 for (i
= top
; i
< (top
+ height
+ 1); i
++) {
449 SLsmg_gotorc(i
, left
+ width
+ 1);
450 SLsmg_write_string(" ");
456 int newtCenteredWindow(int width
, int height
, const char * title
) {
459 top
= (SLtt_Screen_Rows
- height
) / 2;
461 /* I don't know why, but this seems to look better */
462 if ((SLtt_Screen_Rows
% 2) && (top
% 2)) top
--;
464 left
= (SLtt_Screen_Cols
- width
) / 2;
466 newtOpenWindow(left
, top
, width
, height
, title
);
471 void newtPopWindow(void) {
477 row
= currentWindow
->top
- 1;
478 col
= currentWindow
->left
- 1;
483 for (j
= 0; j
< currentWindow
->height
+ 3; j
++, row
++) {
484 SLsmg_gotorc(row
, col
);
485 SLsmg_write_raw(currentWindow
->buffer
+ n
,
486 currentWindow
->width
+ 3);
487 n
+= currentWindow
->width
+ 3;
490 free(currentWindow
->buffer
);
491 free(currentWindow
->title
);
493 if (currentWindow
== windowStack
)
494 currentWindow
= NULL
;
498 SLsmg_set_char_set(0);
505 void newtGetWindowPos(int * x
, int * y
) {
507 *x
= currentWindow
->left
;
508 *y
= currentWindow
->top
;
513 void newtGetrc(int * row
, int * col
) {
518 void newtGotorc(int newRow
, int newCol
) {
520 newRow
+= currentWindow
->top
;
521 newCol
+= currentWindow
->left
;
526 SLsmg_gotorc(cursorRow
, cursorCol
);
529 void newtDrawBox(int left
, int top
, int width
, int height
, int shadow
) {
531 top
+= currentWindow
->top
;
532 left
+= currentWindow
->left
;
535 SLsmg_draw_box(top
, left
, height
, width
);
538 SLsmg_set_color(NEWT_COLORSET_SHADOW
);
539 SLsmg_fill_region(top
+ height
, left
+ 1, 1, width
- 1, ' ');
540 SLsmg_fill_region(top
+ 1, left
+ width
, height
, 1, ' ');
544 void newtClearBox(int left
, int top
, int width
, int height
) {
546 top
+= currentWindow
->top
;
547 left
+= currentWindow
->left
;
550 SLsmg_fill_region(top
, left
, height
, width
, ' ');
554 /* This doesn't seem to work quite right. I don't know why not, but when
555 I rsh from an rxvt into a box and run this code, the machine returns
556 console key's (\033[B) rather then xterm ones (\033OB). */
557 static void initKeymap(void) {
558 struct keymap
* curr
;
560 for (curr
= keymap
; curr
->code
; curr
++) {
562 curr
->str
= SLtt_tgetstr(curr
->tc
);
565 /* Newt's keymap handling is a bit broken. It assumes that any extended
566 keystrokes begin with ESC. If you're using a homebrek terminal you
567 will probably need to fix this, or just yell at me and I'll be so
568 ashamed of myself for doing it this way I'll fix it */
570 keyPrefix
= 0x1b; /* ESC */
574 void newtDelay(int usecs
) {
580 tv
.tv_sec
= usecs
/ 1000000;
581 tv
.tv_usec
= usecs
% 1000000;
583 select(0, &set
, &set
, &set
, &tv
);
586 struct eventResult
newtDefaultEventHandler(newtComponent c
,
588 struct eventResult er
;
590 er
.result
= ER_IGNORED
;
594 void newtRedrawHelpLine(void) {
597 SLsmg_set_color(NEWT_COLORSET_HELPLINE
);
599 buf
= alloca(SLtt_Screen_Cols
+ 1);
600 memset(buf
, ' ', SLtt_Screen_Cols
);
601 buf
[SLtt_Screen_Cols
] = '\0';
603 if (currentHelpline
) {
604 int len
= strlen(*currentHelpline
);
605 if (SLtt_Screen_Cols
< len
)
606 len
= SLtt_Screen_Cols
;
607 memcpy(buf
, *currentHelpline
, len
);
609 SLsmg_gotorc(SLtt_Screen_Rows
- 1, 0);
610 SLsmg_write_string(buf
);
613 void newtPushHelpLine(const char * text
) {
615 text
= defaultHelpLine
;
618 (*(++currentHelpline
)) = strdup(text
);
620 currentHelpline
= helplineStack
;
621 *currentHelpline
= strdup(text
);
624 newtRedrawHelpLine();
627 void newtPopHelpLine(void) {
628 if (!currentHelpline
) return;
630 free(*currentHelpline
);
631 if (currentHelpline
== helplineStack
)
632 currentHelpline
= NULL
;
636 newtRedrawHelpLine();
639 void newtDrawRootText(int col
, int row
, const char * text
) {
640 SLsmg_set_color(NEWT_COLORSET_ROOTTEXT
);
643 col
= SLtt_Screen_Cols
+ col
;
647 row
= SLtt_Screen_Rows
+ row
;
650 SLsmg_gotorc(row
, col
);
651 SLsmg_write_string((char *)text
);
654 int newtSetFlags(int oldFlags
, int newFlags
, enum newtFlagsSense sense
) {
657 return oldFlags
| newFlags
;
659 case NEWT_FLAGS_RESET
:
660 return oldFlags
& (~newFlags
);
662 case NEWT_FLAGS_TOGGLE
:
663 return oldFlags
^ newFlags
;
675 void newtGetScreenSize(int * cols
, int * rows
) {
676 if (rows
) *rows
= SLtt_Screen_Rows
;
677 if (cols
) *cols
= SLtt_Screen_Cols
;
680 void newtDefaultPlaceHandler(newtComponent c
, int newLeft
, int newTop
) {
685 void newtDefaultMappedHandler(newtComponent c
, int isMapped
) {
686 c
->isMapped
= isMapped
;
689 void newtCursorOff(void) {
691 SLtt_set_cursor_visibility (cursorOn
);
694 void newtCursorOn(void) {
696 SLtt_set_cursor_visibility (cursorOn
);
699 void newtTrashScreen(void) {
701 SLsmg_touch_lines (0, SLtt_Screen_Rows
- 1);