7 #include <sys/signal.h>
22 int height
, width
, top
, left
;
23 SLsmg_Char_Type
* buffer
;
33 static struct Window windowStack
[20];
34 static struct Window
* currentWindow
= NULL
;
36 static char * helplineStack
[20];
37 static char ** currentHelpline
= NULL
;
39 static int cursorRow
, cursorCol
;
40 static int needResize
= 0;
41 static int cursorOn
= 1;
42 static int trashScreen
= 0;
44 static const char * defaultHelpLine
=
45 " <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen"
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 */
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" },
88 { "\033[3~", NEWT_KEY_DELETE
, "kl" },
89 { "\033[2~", NEWT_KEY_INSERT
, NULL
},
91 { "\033\t", NEWT_KEY_UNTAB
, NULL
},
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" },
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
},
104 { "\033OP", NEWT_KEY_F1
, NULL
},
105 { "\033OQ", NEWT_KEY_F2
, NULL
},
106 { "\033OR", NEWT_KEY_F3
, NULL
},
107 { "\033OS", NEWT_KEY_F4
, NULL
},
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
},
123 { 0 }, /* LEAVE this one */
125 static char keyPrefix
= '\033';
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. $";
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 int wstrlen(const char *str
, int len
) {
155 if (len
< 0) len
= strlen(str
);
156 memset(&ps
,0,sizeof(mbstate_t));
160 x
= mbrtowc(&tmp
,str
,len
,&ps
);
172 static int getkey() {
175 while ((c
= SLang_getkey()) == '\xC') { /* if Ctrl-L redraw whole screen */
176 SLsmg_touch_lines (0, SLtt_Screen_Rows
- 1);
183 void newtFlushInput(void) {
184 while (SLang_input_pending(0)) {
189 void newtRefresh(void) {
193 void newtSuspend(void) {
194 SLtt_set_cursor_visibility (1);
197 SLtt_set_cursor_visibility (cursorOn
);
200 int newtResume(void) {
203 return SLang_init_tty(0, 0, 0);
207 SLsmg_set_color(NEWT_COLORSET_ROOT
);
214 void newtResizeScreen(int redraw
) {
215 SLtt_get_screen_size();
218 SLsmg_touch_lines (0, SLtt_Screen_Rows
- 1);
224 char * MonoValue
, * MonoEnv
= "NEWT_MONO";
228 if ((lang
= getenv("LC_ALL")) == NULL
)
229 if ((lang
= getenv("LC_CTYPE")) == NULL
)
230 if ((lang
= getenv("LANG")) == NULL
)
232 if (strstr (lang
, ".euc") != NULL
)
235 (void) strlen(ident
);
238 SLtt_get_screen_size();
240 MonoValue
= getenv(MonoEnv
);
241 if ( MonoValue
== NULL
) {
242 SLtt_Use_Ansi_Colors
= 1;
244 SLtt_Use_Ansi_Colors
= 0;
247 if ((ret
= SLsmg_init_smg()) < 0)
249 if ((ret
= SLang_init_tty(0, 0, 0)) < 0)
252 newtSetColors(newtDefaultColorPalette
);
256 /*memset(&sa, 0, sizeof(sa));
257 sa.sa_handler = handleSigwinch;
258 sigaction(SIGWINCH, &sa, NULL);*/
260 SLsignal_intr(SIGWINCH
, handleSigwinch
);
261 SLang_getkey_intr_hook
= getkeyInterruptHook
;
266 int newtFinished(void) {
267 SLsmg_gotorc(SLtt_Screen_Rows
- 1, 0);
276 void newtSetColors(struct newtColors colors
) {
277 if (!SLtt_Use_Ansi_Colors
) {
280 for (i
= 2; i
< 25; i
++)
281 SLtt_set_mono(i
, NULL
, 0);
283 SLtt_set_mono(NEWT_COLORSET_SELLISTBOX
, NULL
, SLTT_BOLD_MASK
);
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
);
290 SLtt_set_mono(NEWT_COLORSET_ACTSELLISTBOX
, NULL
, SLTT_REV_MASK
| SLTT_BOLD_MASK
);
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
);
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
,
305 SLtt_set_color(NEWT_COLORSET_CHECKBOX
, "", colors
.checkboxFg
,
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
,
313 SLtt_set_color(NEWT_COLORSET_ACTLISTBOX
, "", colors
.actListboxFg
,
314 colors
.actListboxBg
);
315 SLtt_set_color(NEWT_COLORSET_TEXTBOX
, "", colors
.textboxFg
,
317 SLtt_set_color(NEWT_COLORSET_ACTTEXTBOX
, "", colors
.actTextboxFg
,
318 colors
.actTextboxBg
);
319 SLtt_set_color(NEWT_COLORSET_HELPLINE
, "", colors
.helpLineFg
,
321 SLtt_set_color(NEWT_COLORSET_ROOTTEXT
, "", colors
.rootTextFg
,
324 SLtt_set_color(NEWT_COLORSET_EMPTYSCALE
, "", "white",
326 SLtt_set_color(NEWT_COLORSET_FULLSCALE
, "", "white",
328 SLtt_set_color(NEWT_COLORSET_DISENTRY
, "", colors
.disabledEntryFg
,
329 colors
.disabledEntryBg
);
331 SLtt_set_color(NEWT_COLORSET_COMPACTBUTTON
, "", colors
.compactButtonFg
,
332 colors
.compactButtonBg
);
334 SLtt_set_color(NEWT_COLORSET_ACTSELLISTBOX
, "", colors
.actSelListboxFg
,
335 colors
.actSelListboxBg
);
336 SLtt_set_color(NEWT_COLORSET_SELLISTBOX
, "", colors
.selListboxFg
,
337 colors
.selListboxBg
);
340 int newtGetKey(void) {
342 char buf
[10], * chptr
= buf
;
343 const struct keymap
* curr
;
350 return NEWT_KEY_RESIZE
;
353 /* ignore other signals */
357 if (key
== NEWT_KEY_SUSPEND
&& suspendCallback
)
358 suspendCallback(suspendCallbackData
);
359 } while (key
== NEWT_KEY_SUSPEND
);
364 return NEWT_KEY_PGUP
;
367 return NEWT_KEY_PGDN
;
369 return NEWT_KEY_BKSPC
;
371 return NEWT_KEY_BKSPC
;
374 return NEWT_KEY_BKSPC
;
377 if (key
!= keyPrefix
) return key
;
380 memset(buf
, 0, sizeof(buf
));
383 while (SLang_input_pending(5)) {
385 if (key
== keyPrefix
) {
386 /* he hit unknown keys too many times -- start over */
387 memset(buf
, 0, sizeof(buf
));
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 */
397 for (curr
= keymap
; curr
->code
; curr
++) {
399 if (!strcmp(curr
->str
, buf
))
405 for (curr
= keymap
; curr
->code
; curr
++) {
407 if (!strcmp(curr
->str
, buf
))
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
418 SLang_ungetkey(*chptr
--);
423 void newtWaitForKey(void) {
427 newtClearKeyBuffer();
430 void newtClearKeyBuffer(void) {
431 while (SLang_input_pending(1)) {
436 int newtOpenWindow(unsigned left
, unsigned top
, unsigned width
, unsigned height
,
437 const char * title
) {
444 if (!currentWindow
) {
445 currentWindow
= windowStack
;
450 currentWindow
->left
= left
;
451 currentWindow
->top
= top
;
452 currentWindow
->width
= width
;
453 currentWindow
->height
= height
;
454 currentWindow
->title
= title
? strdup(title
) : NULL
;
456 currentWindow
->buffer
= malloc(sizeof(SLsmg_Char_Type
) * (width
+ 3) * (height
+ 3));
460 /* clip to the current screen bounds - msw */
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
;
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;
479 SLsmg_set_color(NEWT_COLORSET_BORDER
);
480 SLsmg_draw_box(top
- 1, left
- 1, height
+ 2, width
+ 2);
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);
499 SLsmg_set_color(NEWT_COLORSET_WINDOW
);
500 SLsmg_fill_region(top
, left
, height
, width
, ' ');
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, ' ');
506 for (i
= top
; i
< (top
+ height
+ 1); i
++) {
507 SLsmg_gotorc(i
, left
+ width
+ 1);
508 SLsmg_write_string(" ");
514 int newtCenteredWindow(unsigned width
, unsigned height
, const char * title
) {
517 top
= (SLtt_Screen_Rows
- height
) / 2;
519 /* I don't know why, but this seems to look better */
520 if ((SLtt_Screen_Rows
% 2) && (top
% 2)) top
--;
522 left
= (SLtt_Screen_Cols
- width
) / 2;
524 newtOpenWindow(left
, top
, width
, height
, title
);
529 void newtPopWindow(void) {
535 row
= currentWindow
->top
- 1;
536 col
= currentWindow
->left
- 1;
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;
548 free(currentWindow
->buffer
);
549 free(currentWindow
->title
);
551 if (currentWindow
== windowStack
)
552 currentWindow
= NULL
;
556 SLsmg_set_char_set(0);
563 void newtGetWindowPos(int * x
, int * y
) {
565 *x
= currentWindow
->left
;
566 *y
= currentWindow
->top
;
571 void newtGetrc(int * row
, int * col
) {
576 void newtGotorc(int newRow
, int newCol
) {
578 newRow
+= currentWindow
->top
;
579 newCol
+= currentWindow
->left
;
584 SLsmg_gotorc(cursorRow
, cursorCol
);
587 void newtDrawBox(int left
, int top
, int width
, int height
, int shadow
) {
589 top
+= currentWindow
->top
;
590 left
+= currentWindow
->left
;
593 SLsmg_draw_box(top
, left
, height
, width
);
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, ' ');
602 void newtClearBox(int left
, int top
, int width
, int height
) {
604 top
+= currentWindow
->top
;
605 left
+= currentWindow
->left
;
608 SLsmg_fill_region(top
, left
, height
, width
, ' ');
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
;
618 for (curr
= keymap
; curr
->code
; curr
++) {
620 curr
->str
= SLtt_tgetstr(curr
->tc
);
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 */
628 keyPrefix
= 0x1b; /* ESC */
632 void newtDelay(unsigned usecs
) {
638 tv
.tv_sec
= usecs
/ 1000000;
639 tv
.tv_usec
= usecs
% 1000000;
641 select(0, &set
, &set
, &set
, &tv
);
644 struct eventResult
newtDefaultEventHandler(newtComponent c
,
646 struct eventResult er
;
648 er
.result
= ER_IGNORED
;
652 void newtRedrawHelpLine(void) {
655 SLsmg_set_color(NEWT_COLORSET_HELPLINE
);
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);
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
));
671 buf
= alloca(SLtt_Screen_Cols
+ 1);
672 memset(buf
, ' ', SLtt_Screen_Cols
);
673 buf
[SLtt_Screen_Cols
] = '\0';
675 SLsmg_gotorc(SLtt_Screen_Rows
- 1, 0);
676 SLsmg_write_string(buf
);
679 void newtPushHelpLine(const char * text
) {
681 text
= defaultHelpLine
;
684 (*(++currentHelpline
)) = strdup(text
);
686 currentHelpline
= helplineStack
;
687 *currentHelpline
= strdup(text
);
690 newtRedrawHelpLine();
693 void newtPopHelpLine(void) {
694 if (!currentHelpline
) return;
696 free(*currentHelpline
);
697 if (currentHelpline
== helplineStack
)
698 currentHelpline
= NULL
;
702 newtRedrawHelpLine();
705 void newtDrawRootText(int col
, int row
, const char * text
) {
706 SLsmg_set_color(NEWT_COLORSET_ROOTTEXT
);
709 col
= SLtt_Screen_Cols
+ col
;
713 row
= SLtt_Screen_Rows
+ row
;
716 SLsmg_gotorc(row
, col
);
717 SLsmg_write_string((char *)text
);
720 int newtSetFlags(int oldFlags
, int newFlags
, enum newtFlagsSense sense
) {
723 return oldFlags
| newFlags
;
725 case NEWT_FLAGS_RESET
:
726 return oldFlags
& (~newFlags
);
728 case NEWT_FLAGS_TOGGLE
:
729 return oldFlags
^ newFlags
;
741 void newtGetScreenSize(int * cols
, int * rows
) {
742 if (rows
) *rows
= SLtt_Screen_Rows
;
743 if (cols
) *cols
= SLtt_Screen_Cols
;
746 void newtDefaultPlaceHandler(newtComponent c
, int newLeft
, int newTop
) {
751 void newtDefaultMappedHandler(newtComponent c
, int isMapped
) {
752 c
->isMapped
= isMapped
;
755 void newtCursorOff(void) {
757 SLtt_set_cursor_visibility (cursorOn
);
760 void newtCursorOn(void) {
762 SLtt_set_cursor_visibility (cursorOn
);
765 void newtTrashScreen(void) {
767 SLsmg_touch_lines (0, SLtt_Screen_Rows
- 1);