7 #include <sys/signal.h>
21 int height
, width
, top
, left
;
22 SLsmg_Char_Type
* buffer
;
32 static struct Window windowStack
[20];
33 static struct Window
* currentWindow
= NULL
;
35 static char * helplineStack
[20];
36 static char ** currentHelpline
= NULL
;
38 static int cursorRow
, cursorCol
;
39 static int needResize
;
40 static int cursorOn
= 1;
41 static int trashScreen
= 0;
43 static const char * defaultHelpLine
=
44 " <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen"
47 const struct newtColors newtDefaultColorPalette
= {
48 "white", "blue", /* root fg, bg */
49 "black", "lightgray", /* border fg, bg */
50 "black", "lightgray", /* window fg, bg */
51 "white", "black", /* shadow fg, bg */
52 "red", "lightgray", /* title fg, bg */
53 "lightgray", "red", /* button fg, bg */
54 "red", "lightgray", /* active button fg, bg */
55 "yellow", "blue", /* checkbox fg, bg */
56 "blue", "brown", /* active checkbox fg, bg */
57 "yellow", "blue", /* entry box fg, bg */
58 "blue", "lightgray", /* label fg, bg */
59 "black", "lightgray", /* listbox fg, bg */
60 "yellow", "blue", /* active listbox fg, bg */
61 "black", "lightgray", /* textbox fg, bg */
62 "lightgray", "black", /* active textbox fg, bg */
63 "white", "blue", /* help line */
64 "yellow", "blue", /* root text */
65 "blue", /* scale full */
66 "red", /* scale empty */
67 "blue", "lightgray", /* disabled entry fg, bg */
68 "white", "blue", /* compact button fg, bg */
69 "yellow", "red", /* active & sel listbox */
70 "black", "brown" /* selected listbox */
73 static const struct keymap keymap
[] = {
74 { "\033OA", NEWT_KEY_UP
, "kh" },
75 { "\033[A", NEWT_KEY_UP
, "ku" },
76 { "\033OB", NEWT_KEY_DOWN
, "kd" },
77 { "\033[B", NEWT_KEY_DOWN
, "kd" },
78 { "\033[C", NEWT_KEY_RIGHT
, "kr" },
79 { "\033OC", NEWT_KEY_RIGHT
, "kr" },
80 { "\033[D", NEWT_KEY_LEFT
, "kl" },
81 { "\033OD", NEWT_KEY_LEFT
, "kl" },
82 { "\033[H", NEWT_KEY_HOME
, "kh" },
83 { "\033[1~", NEWT_KEY_HOME
, "kh" },
84 { "\033Ow", NEWT_KEY_END
, "kH" },
85 { "\033[4~", NEWT_KEY_END
, "kH" },
87 { "\033[3~", NEWT_KEY_DELETE
, "kl" },
88 { "\033[2~", NEWT_KEY_INSERT
, NULL
},
90 { "\033\t", NEWT_KEY_UNTAB
, NULL
},
92 { "\033[5~", NEWT_KEY_PGUP
, NULL
},
93 { "\033[6~", NEWT_KEY_PGDN
, NULL
},
94 { "\033V", NEWT_KEY_PGUP
, "kH" },
95 { "\033v", NEWT_KEY_PGUP
, "kH" },
97 { "\033[[A", NEWT_KEY_F1
, NULL
},
98 { "\033[[B", NEWT_KEY_F2
, NULL
},
99 { "\033[[C", NEWT_KEY_F3
, NULL
},
100 { "\033[[D", NEWT_KEY_F4
, NULL
},
101 { "\033[[E", NEWT_KEY_F5
, NULL
},
103 { "\033OP", NEWT_KEY_F1
, NULL
},
104 { "\033OQ", NEWT_KEY_F2
, NULL
},
105 { "\033OR", NEWT_KEY_F3
, NULL
},
106 { "\033OS", NEWT_KEY_F4
, NULL
},
108 { "\033[11~", NEWT_KEY_F1
, NULL
},
109 { "\033[12~", NEWT_KEY_F2
, NULL
},
110 { "\033[13~", NEWT_KEY_F3
, NULL
},
111 { "\033[14~", NEWT_KEY_F4
, NULL
},
112 { "\033[15~", NEWT_KEY_F5
, NULL
},
113 { "\033[17~", NEWT_KEY_F6
, NULL
},
114 { "\033[18~", NEWT_KEY_F7
, NULL
},
115 { "\033[19~", NEWT_KEY_F8
, NULL
},
116 { "\033[20~", NEWT_KEY_F9
, NULL
},
117 { "\033[21~", NEWT_KEY_F10
, NULL
},
118 { "\033[23~", NEWT_KEY_F11
, NULL
},
119 { "\033[24~", NEWT_KEY_F12
, NULL
},
120 { "\033", NEWT_KEY_ESCAPE
, NULL
},
122 { NULL
, 0, NULL
}, /* LEAVE this one */
124 static char keyPrefix
= '\033';
126 static const char * version
= "Newt windowing library version " VERSION
127 " - (C) 1996-2000 Red Hat Software. "
128 "Redistributable under the term of the Library "
129 "GNU Public License. "
130 "Written by Erik Troan\n";
132 static newtSuspendCallback suspendCallback
= NULL
;
133 static void * suspendCallbackData
= NULL
;
135 void newtSetSuspendCallback(newtSuspendCallback cb
, void * data
) {
136 suspendCallback
= cb
;
137 suspendCallbackData
= data
;
140 static void handleSigwinch(int signum
) {
144 static int getkeyInterruptHook(void) {
148 void newtFlushInput(void) {
149 while (SLang_input_pending(0)) {
154 void newtRefresh(void) {
158 void newtSuspend(void) {
159 SLtt_set_cursor_visibility (1);
162 SLtt_set_cursor_visibility (cursorOn
);
165 void newtResume(void) {
168 SLang_init_tty(0, 0, 0);
172 SLsmg_set_color(NEWT_COLORSET_ROOT
);
179 #if defined(THIS_DOESNT_WORK)
180 void newtResizeScreen(int redraw
) {
181 newtPushHelpLine("");
183 SLtt_get_screen_size();
184 SLang_init_tty(0, 0, 0);
186 SLsmg_touch_lines (0, SLtt_Screen_Rows
- 1);
188 /* I don't know why I need this */
199 char * MonoValue
, * MonoEnv
= "NEWT_MONO", * lang
;
201 lang
= getenv ("LANG");
202 if (lang
&& !strcasecmp (lang
, "ja_JP.eucJP"))
205 /* use the version variable just to be sure it gets included */
209 SLtt_get_screen_size();
211 MonoValue
= getenv(MonoEnv
);
212 if ( MonoValue
== NULL
) {
213 SLtt_Use_Ansi_Colors
= 1;
215 SLtt_Use_Ansi_Colors
= 0;
219 SLang_init_tty(0, 0, 0);
221 newtSetColors(newtDefaultColorPalette
);
225 /*memset(&sa, 0, sizeof(sa));
226 sa.sa_handler = handleSigwinch;
227 sigaction(SIGWINCH, &sa, NULL);*/
229 SLsignal_intr(SIGWINCH
, handleSigwinch
);
230 SLang_getkey_intr_hook
= getkeyInterruptHook
;
237 int newtFinished(void) {
238 SLsmg_gotorc(SLtt_Screen_Rows
- 1, 0);
247 void newtSetColors(struct newtColors colors
) {
248 SLtt_set_color(NEWT_COLORSET_ROOT
, "", colors
.rootFg
, colors
.rootBg
);
249 SLtt_set_color(NEWT_COLORSET_BORDER
, "", colors
.borderFg
, colors
.borderBg
);
250 SLtt_set_color(NEWT_COLORSET_WINDOW
, "", colors
.windowFg
, colors
.windowBg
);
251 SLtt_set_color(NEWT_COLORSET_SHADOW
, "", colors
.shadowFg
, colors
.shadowBg
);
252 SLtt_set_color(NEWT_COLORSET_TITLE
, "", colors
.titleFg
, colors
.titleBg
);
253 SLtt_set_color(NEWT_COLORSET_BUTTON
, "", colors
.buttonFg
, colors
.buttonBg
);
254 SLtt_set_color(NEWT_COLORSET_ACTBUTTON
, "", colors
.actButtonFg
,
256 SLtt_set_color(NEWT_COLORSET_CHECKBOX
, "", colors
.checkboxFg
,
258 SLtt_set_color(NEWT_COLORSET_ACTCHECKBOX
, "", colors
.actCheckboxFg
,
259 colors
.actCheckboxBg
);
260 SLtt_set_color(NEWT_COLORSET_ENTRY
, "", colors
.entryFg
, colors
.entryBg
);
261 SLtt_set_color(NEWT_COLORSET_LABEL
, "", colors
.labelFg
, colors
.labelBg
);
262 SLtt_set_color(NEWT_COLORSET_LISTBOX
, "", colors
.listboxFg
,
264 SLtt_set_color(NEWT_COLORSET_ACTLISTBOX
, "", colors
.actListboxFg
,
265 colors
.actListboxBg
);
266 SLtt_set_color(NEWT_COLORSET_TEXTBOX
, "", colors
.textboxFg
,
268 SLtt_set_color(NEWT_COLORSET_ACTTEXTBOX
, "", colors
.actTextboxFg
,
269 colors
.actTextboxBg
);
270 SLtt_set_color(NEWT_COLORSET_HELPLINE
, "", colors
.helpLineFg
,
272 SLtt_set_color(NEWT_COLORSET_ROOTTEXT
, "", colors
.rootTextFg
,
275 SLtt_set_color(NEWT_COLORSET_EMPTYSCALE
, "", "white",
277 SLtt_set_color(NEWT_COLORSET_FULLSCALE
, "", "white",
279 SLtt_set_color(NEWT_COLORSET_DISENTRY
, "", colors
.disabledEntryFg
,
280 colors
.disabledEntryBg
);
282 SLtt_set_color(NEWT_COLORSET_COMPACTBUTTON
, "", colors
.compactButtonFg
,
283 colors
.compactButtonBg
);
285 SLtt_set_color(NEWT_COLORSET_ACTSELLISTBOX
, "", colors
.actSelListboxFg
,
286 colors
.actSelListboxBg
);
287 SLtt_set_color(NEWT_COLORSET_SELLISTBOX
, "", colors
.selListboxFg
,
288 colors
.selListboxBg
);
291 int newtGetKey(void) {
293 char buf
[10], * chptr
= buf
;
294 const struct keymap
* curr
;
297 key
= SLang_getkey();
300 return NEWT_KEY_RESIZE
;
302 /* ignore other signals */
306 if (key
== NEWT_KEY_SUSPEND
&& suspendCallback
)
307 suspendCallback(suspendCallbackData
);
308 } while (key
== NEWT_KEY_SUSPEND
);
313 return NEWT_KEY_PGUP
;
316 return NEWT_KEY_PGDN
;
318 return NEWT_KEY_BKSPC
;
320 return NEWT_KEY_BKSPC
;
323 return NEWT_KEY_BKSPC
;
326 if (key
!= keyPrefix
) return key
;
329 memset(buf
, 0, sizeof(buf
));
332 while (SLang_input_pending(5)) {
333 key
= SLang_getkey();
334 if (key
== keyPrefix
) {
335 /* he hit unknown keys too many times -- start over */
336 memset(buf
, 0, sizeof(buf
));
342 /* this search should use bsearch(), but when we only look through
343 a list of 20 (or so) keymappings, it's probably faster just to
344 do a inline linear search */
346 for (curr
= keymap
; curr
->code
; curr
++) {
348 if (!strcmp(curr
->str
, buf
))
354 for (curr
= keymap
; curr
->code
; curr
++) {
356 if (!strcmp(curr
->str
, buf
))
361 /* Looks like we were a bit overzealous in reading characters. Return
362 just the first character, and put everything else back in the buffer
367 SLang_ungetkey(*chptr
--);
372 void newtWaitForKey(void) {
376 newtClearKeyBuffer();
379 void newtClearKeyBuffer(void) {
380 while (SLang_input_pending(1)) {
385 int newtOpenWindow(int left
, int top
, int width
, int height
,
386 const char * title
) {
393 if (!currentWindow
) {
394 currentWindow
= windowStack
;
399 currentWindow
->left
= left
;
400 currentWindow
->top
= top
;
401 currentWindow
->width
= width
;
402 currentWindow
->height
= height
;
403 currentWindow
->title
= title
? strdup(title
) : NULL
;
405 currentWindow
->buffer
= malloc(sizeof(SLsmg_Char_Type
) * (width
+ 3) * (height
+ 3));
409 /* clip to the current screen bounds - msw */
414 if (left
+ width
> SLtt_Screen_Cols
)
415 width
= SLtt_Screen_Cols
- left
;
416 if (top
+ height
> SLtt_Screen_Rows
)
417 height
= SLtt_Screen_Rows
- top
;
419 for (j
= 0; j
< height
+ 3; j
++, row
++) {
420 SLsmg_gotorc(row
, col
);
421 SLsmg_read_raw(currentWindow
->buffer
+ n
,
422 currentWindow
->width
+ 3);
423 n
+= currentWindow
->width
+ 3;
428 SLsmg_set_color(NEWT_COLORSET_BORDER
);
429 SLsmg_draw_box(top
- 1, left
- 1, height
+ 2, width
+ 2);
431 if (currentWindow
->title
) {
432 i
= strlen(currentWindow
->title
) + 4;
433 i
= ((width
- i
) / 2) + left
;
434 SLsmg_gotorc(top
- 1, i
);
435 SLsmg_set_char_set(1);
436 SLsmg_write_char(SLSMG_RTEE_CHAR
);
437 SLsmg_set_char_set(0);
438 SLsmg_write_char(' ');
439 SLsmg_set_color(NEWT_COLORSET_TITLE
);
440 SLsmg_write_string((char *)currentWindow
->title
);
441 SLsmg_set_color(NEWT_COLORSET_BORDER
);
442 SLsmg_write_char(' ');
443 SLsmg_set_char_set(1);
444 SLsmg_write_char(SLSMG_LTEE_CHAR
);
445 SLsmg_set_char_set(0);
448 SLsmg_set_color(NEWT_COLORSET_WINDOW
);
449 SLsmg_fill_region(top
, left
, height
, width
, ' ');
451 SLsmg_set_color(NEWT_COLORSET_SHADOW
);
452 SLsmg_fill_region(top
+ height
+ 1, left
, 1, width
+ 2, ' ');
453 SLsmg_fill_region(top
, left
+ width
+ 1, height
+ 1, 1, ' ');
455 for (i
= top
; i
< (top
+ height
+ 1); i
++) {
456 SLsmg_gotorc(i
, left
+ width
+ 1);
457 SLsmg_write_string(" ");
463 int newtCenteredWindow(int width
, int height
, const char * title
) {
466 top
= (SLtt_Screen_Rows
- height
) / 2;
468 /* I don't know why, but this seems to look better */
469 if ((SLtt_Screen_Rows
% 2) && (top
% 2)) top
--;
471 left
= (SLtt_Screen_Cols
- width
) / 2;
473 newtOpenWindow(left
, top
, width
, height
, title
);
478 void newtPopWindow(void) {
484 row
= currentWindow
->top
- 1;
485 col
= currentWindow
->left
- 1;
490 for (j
= 0; j
< currentWindow
->height
+ 3; j
++, row
++) {
491 SLsmg_gotorc(row
, col
);
492 SLsmg_write_raw(currentWindow
->buffer
+ n
,
493 currentWindow
->width
+ 3);
494 n
+= currentWindow
->width
+ 3;
497 free(currentWindow
->buffer
);
498 free(currentWindow
->title
);
500 if (currentWindow
== windowStack
)
501 currentWindow
= NULL
;
505 SLsmg_set_char_set(0);
512 void newtGetWindowPos(int * x
, int * y
) {
514 *x
= currentWindow
->left
;
515 *y
= currentWindow
->top
;
520 void newtGetrc(int * row
, int * col
) {
525 void newtGotorc(int newRow
, int newCol
) {
527 newRow
+= currentWindow
->top
;
528 newCol
+= currentWindow
->left
;
533 SLsmg_gotorc(cursorRow
, cursorCol
);
536 void newtDrawBox(int left
, int top
, int width
, int height
, int shadow
) {
538 top
+= currentWindow
->top
;
539 left
+= currentWindow
->left
;
542 SLsmg_draw_box(top
, left
, height
, width
);
545 SLsmg_set_color(NEWT_COLORSET_SHADOW
);
546 SLsmg_fill_region(top
+ height
, left
+ 1, 1, width
- 1, ' ');
547 SLsmg_fill_region(top
+ 1, left
+ width
, height
, 1, ' ');
551 void newtClearBox(int left
, int top
, int width
, int height
) {
553 top
+= currentWindow
->top
;
554 left
+= currentWindow
->left
;
557 SLsmg_fill_region(top
, left
, height
, width
, ' ');
561 /* This doesn't seem to work quite right. I don't know why not, but when
562 I rsh from an rxvt into a box and run this code, the machine returns
563 console key's (\033[B) rather then xterm ones (\033OB). */
564 static void initKeymap(void) {
565 struct keymap
* curr
;
567 for (curr
= keymap
; curr
->code
; curr
++) {
569 curr
->str
= SLtt_tgetstr(curr
->tc
);
572 /* Newt's keymap handling is a bit broken. It assumes that any extended
573 keystrokes begin with ESC. If you're using a homebrek terminal you
574 will probably need to fix this, or just yell at me and I'll be so
575 ashamed of myself for doing it this way I'll fix it */
577 keyPrefix
= 0x1b; /* ESC */
581 void newtDelay(int usecs
) {
587 tv
.tv_sec
= usecs
/ 1000000;
588 tv
.tv_usec
= usecs
% 1000000;
590 select(0, &set
, &set
, &set
, &tv
);
593 struct eventResult
newtDefaultEventHandler(newtComponent c
,
595 struct eventResult er
;
597 er
.result
= ER_IGNORED
;
601 void newtRedrawHelpLine(void) {
604 SLsmg_set_color(NEWT_COLORSET_HELPLINE
);
606 buf
= alloca(SLtt_Screen_Cols
+ 1);
607 memset(buf
, ' ', SLtt_Screen_Cols
);
608 buf
[SLtt_Screen_Cols
] = '\0';
610 if (currentHelpline
) {
611 int len
= strlen(*currentHelpline
);
612 if (SLtt_Screen_Cols
< len
)
613 len
= SLtt_Screen_Cols
;
614 memcpy(buf
, *currentHelpline
, len
);
616 SLsmg_gotorc(SLtt_Screen_Rows
- 1, 0);
617 SLsmg_write_string(buf
);
620 void newtPushHelpLine(const char * text
) {
622 text
= defaultHelpLine
;
625 (*(++currentHelpline
)) = strdup(text
);
627 currentHelpline
= helplineStack
;
628 *currentHelpline
= strdup(text
);
631 newtRedrawHelpLine();
634 void newtPopHelpLine(void) {
635 if (!currentHelpline
) return;
637 free(*currentHelpline
);
638 if (currentHelpline
== helplineStack
)
639 currentHelpline
= NULL
;
643 newtRedrawHelpLine();
646 void newtDrawRootText(int col
, int row
, const char * text
) {
647 SLsmg_set_color(NEWT_COLORSET_ROOTTEXT
);
650 col
= SLtt_Screen_Cols
+ col
;
654 row
= SLtt_Screen_Rows
+ row
;
657 SLsmg_gotorc(row
, col
);
658 SLsmg_write_string((char *)text
);
661 int newtSetFlags(int oldFlags
, int newFlags
, enum newtFlagsSense sense
) {
664 return oldFlags
| newFlags
;
666 case NEWT_FLAGS_RESET
:
667 return oldFlags
& (~newFlags
);
669 case NEWT_FLAGS_TOGGLE
:
670 return oldFlags
^ newFlags
;
682 void newtGetScreenSize(int * cols
, int * rows
) {
683 if (rows
) *rows
= SLtt_Screen_Rows
;
684 if (cols
) *cols
= SLtt_Screen_Cols
;
687 void newtDefaultPlaceHandler(newtComponent c
, int newLeft
, int newTop
) {
692 void newtDefaultMappedHandler(newtComponent c
, int isMapped
) {
693 c
->isMapped
= isMapped
;
696 void newtCursorOff(void) {
698 SLtt_set_cursor_visibility (cursorOn
);
701 void newtCursorOn(void) {
703 SLtt_set_cursor_visibility (cursorOn
);
706 void newtTrashScreen(void) {
708 SLsmg_touch_lines (0, SLtt_Screen_Rows
- 1);