kconfig/lxdialog/util.c
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
parent 943 1cca90ce0481
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

Signed-off-by: "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
yann@1
     1
/*
yann@1
     2
 *  util.c
yann@1
     3
 *
yann@1
     4
 *  ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
yann@1
     5
 *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
yann@1
     6
 *
yann@1
     7
 *  This program is free software; you can redistribute it and/or
yann@1
     8
 *  modify it under the terms of the GNU General Public License
yann@1
     9
 *  as published by the Free Software Foundation; either version 2
yann@1
    10
 *  of the License, or (at your option) any later version.
yann@1
    11
 *
yann@1
    12
 *  This program is distributed in the hope that it will be useful,
yann@1
    13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
yann@1
    14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
yann@1
    15
 *  GNU General Public License for more details.
yann@1
    16
 *
yann@1
    17
 *  You should have received a copy of the GNU General Public License
yann@1
    18
 *  along with this program; if not, write to the Free Software
yann@1
    19
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
yann@1
    20
 */
yann@1
    21
yann@2448
    22
#include <stdarg.h>
yann@2448
    23
yann@1
    24
#include "dialog.h"
yann@1
    25
yann@1
    26
struct dialog_info dlg;
yann@1
    27
yann@1
    28
static void set_mono_theme(void)
yann@1
    29
{
yann@1
    30
	dlg.screen.atr = A_NORMAL;
yann@1
    31
	dlg.shadow.atr = A_NORMAL;
yann@1
    32
	dlg.dialog.atr = A_NORMAL;
yann@1
    33
	dlg.title.atr = A_BOLD;
yann@1
    34
	dlg.border.atr = A_NORMAL;
yann@1
    35
	dlg.button_active.atr = A_REVERSE;
yann@1
    36
	dlg.button_inactive.atr = A_DIM;
yann@1
    37
	dlg.button_key_active.atr = A_REVERSE;
yann@1
    38
	dlg.button_key_inactive.atr = A_BOLD;
yann@1
    39
	dlg.button_label_active.atr = A_REVERSE;
yann@1
    40
	dlg.button_label_inactive.atr = A_NORMAL;
yann@1
    41
	dlg.inputbox.atr = A_NORMAL;
yann@1
    42
	dlg.inputbox_border.atr = A_NORMAL;
yann@1
    43
	dlg.searchbox.atr = A_NORMAL;
yann@1
    44
	dlg.searchbox_title.atr = A_BOLD;
yann@1
    45
	dlg.searchbox_border.atr = A_NORMAL;
yann@1
    46
	dlg.position_indicator.atr = A_BOLD;
yann@1
    47
	dlg.menubox.atr = A_NORMAL;
yann@1
    48
	dlg.menubox_border.atr = A_NORMAL;
yann@1
    49
	dlg.item.atr = A_NORMAL;
yann@1
    50
	dlg.item_selected.atr = A_REVERSE;
yann@1
    51
	dlg.tag.atr = A_BOLD;
yann@1
    52
	dlg.tag_selected.atr = A_REVERSE;
yann@1
    53
	dlg.tag_key.atr = A_BOLD;
yann@1
    54
	dlg.tag_key_selected.atr = A_REVERSE;
yann@1
    55
	dlg.check.atr = A_BOLD;
yann@1
    56
	dlg.check_selected.atr = A_REVERSE;
yann@1
    57
	dlg.uarrow.atr = A_BOLD;
yann@1
    58
	dlg.darrow.atr = A_BOLD;
yann@1
    59
}
yann@1
    60
yann@1
    61
#define DLG_COLOR(dialog, f, b, h) \
yann@1
    62
do {                               \
yann@1
    63
	dlg.dialog.fg = (f);       \
yann@1
    64
	dlg.dialog.bg = (b);       \
yann@1
    65
	dlg.dialog.hl = (h);       \
yann@1
    66
} while (0)
yann@1
    67
yann@1
    68
static void set_classic_theme(void)
yann@1
    69
{
yann@1
    70
	DLG_COLOR(screen,                COLOR_CYAN,   COLOR_BLUE,   true);
yann@1
    71
	DLG_COLOR(shadow,                COLOR_BLACK,  COLOR_BLACK,  true);
yann@1
    72
	DLG_COLOR(dialog,                COLOR_BLACK,  COLOR_WHITE,  false);
yann@1
    73
	DLG_COLOR(title,                 COLOR_YELLOW, COLOR_WHITE,  true);
yann@1
    74
	DLG_COLOR(border,                COLOR_WHITE,  COLOR_WHITE,  true);
yann@1
    75
	DLG_COLOR(button_active,         COLOR_WHITE,  COLOR_BLUE,   true);
yann@1
    76
	DLG_COLOR(button_inactive,       COLOR_BLACK,  COLOR_WHITE,  false);
yann@1
    77
	DLG_COLOR(button_key_active,     COLOR_WHITE,  COLOR_BLUE,   true);
yann@1
    78
	DLG_COLOR(button_key_inactive,   COLOR_RED,    COLOR_WHITE,  false);
yann@1
    79
	DLG_COLOR(button_label_active,   COLOR_YELLOW, COLOR_BLUE,   true);
yann@1
    80
	DLG_COLOR(button_label_inactive, COLOR_BLACK,  COLOR_WHITE,  true);
yann@1
    81
	DLG_COLOR(inputbox,              COLOR_BLACK,  COLOR_WHITE,  false);
yann@1
    82
	DLG_COLOR(inputbox_border,       COLOR_BLACK,  COLOR_WHITE,  false);
yann@1
    83
	DLG_COLOR(searchbox,             COLOR_BLACK,  COLOR_WHITE,  false);
yann@1
    84
	DLG_COLOR(searchbox_title,       COLOR_YELLOW, COLOR_WHITE,  true);
yann@1
    85
	DLG_COLOR(searchbox_border,      COLOR_WHITE,  COLOR_WHITE,  true);
yann@1
    86
	DLG_COLOR(position_indicator,    COLOR_YELLOW, COLOR_WHITE,  true);
yann@1
    87
	DLG_COLOR(menubox,               COLOR_BLACK,  COLOR_WHITE,  false);
yann@1
    88
	DLG_COLOR(menubox_border,        COLOR_WHITE,  COLOR_WHITE,  true);
yann@1
    89
	DLG_COLOR(item,                  COLOR_BLACK,  COLOR_WHITE,  false);
yann@1
    90
	DLG_COLOR(item_selected,         COLOR_WHITE,  COLOR_BLUE,   true);
yann@1
    91
	DLG_COLOR(tag,                   COLOR_YELLOW, COLOR_WHITE,  true);
yann@1
    92
	DLG_COLOR(tag_selected,          COLOR_YELLOW, COLOR_BLUE,   true);
yann@1
    93
	DLG_COLOR(tag_key,               COLOR_YELLOW, COLOR_WHITE,  true);
yann@1
    94
	DLG_COLOR(tag_key_selected,      COLOR_YELLOW, COLOR_BLUE,   true);
yann@1
    95
	DLG_COLOR(check,                 COLOR_BLACK,  COLOR_WHITE,  false);
yann@1
    96
	DLG_COLOR(check_selected,        COLOR_WHITE,  COLOR_BLUE,   true);
yann@1
    97
	DLG_COLOR(uarrow,                COLOR_GREEN,  COLOR_WHITE,  true);
yann@1
    98
	DLG_COLOR(darrow,                COLOR_GREEN,  COLOR_WHITE,  true);
yann@1
    99
}
yann@1
   100
yann@1
   101
static void set_blackbg_theme(void)
yann@1
   102
{
yann@1
   103
	DLG_COLOR(screen, COLOR_RED,   COLOR_BLACK, true);
yann@1
   104
	DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
yann@1
   105
	DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
yann@1
   106
	DLG_COLOR(title,  COLOR_RED,   COLOR_BLACK, false);
yann@1
   107
	DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
yann@1
   108
yann@1
   109
	DLG_COLOR(button_active,         COLOR_YELLOW, COLOR_RED,   false);
yann@1
   110
	DLG_COLOR(button_inactive,       COLOR_YELLOW, COLOR_BLACK, false);
yann@1
   111
	DLG_COLOR(button_key_active,     COLOR_YELLOW, COLOR_RED,   true);
yann@1
   112
	DLG_COLOR(button_key_inactive,   COLOR_RED,    COLOR_BLACK, false);
yann@1
   113
	DLG_COLOR(button_label_active,   COLOR_WHITE,  COLOR_RED,   false);
yann@1
   114
	DLG_COLOR(button_label_inactive, COLOR_BLACK,  COLOR_BLACK, true);
yann@1
   115
yann@1
   116
	DLG_COLOR(inputbox,         COLOR_YELLOW, COLOR_BLACK, false);
yann@1
   117
	DLG_COLOR(inputbox_border,  COLOR_YELLOW, COLOR_BLACK, false);
yann@1
   118
yann@1
   119
	DLG_COLOR(searchbox,        COLOR_YELLOW, COLOR_BLACK, false);
yann@1
   120
	DLG_COLOR(searchbox_title,  COLOR_YELLOW, COLOR_BLACK, true);
yann@1
   121
	DLG_COLOR(searchbox_border, COLOR_BLACK,  COLOR_BLACK, true);
yann@1
   122
yann@1
   123
	DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK,  false);
yann@1
   124
yann@1
   125
	DLG_COLOR(menubox,          COLOR_YELLOW, COLOR_BLACK, false);
yann@1
   126
	DLG_COLOR(menubox_border,   COLOR_BLACK,  COLOR_BLACK, true);
yann@1
   127
yann@1
   128
	DLG_COLOR(item,             COLOR_WHITE, COLOR_BLACK, false);
yann@1
   129
	DLG_COLOR(item_selected,    COLOR_WHITE, COLOR_RED,   false);
yann@1
   130
yann@1
   131
	DLG_COLOR(tag,              COLOR_RED,    COLOR_BLACK, false);
yann@1
   132
	DLG_COLOR(tag_selected,     COLOR_YELLOW, COLOR_RED,   true);
yann@1
   133
	DLG_COLOR(tag_key,          COLOR_RED,    COLOR_BLACK, false);
yann@1
   134
	DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED,   true);
yann@1
   135
yann@1
   136
	DLG_COLOR(check,            COLOR_YELLOW, COLOR_BLACK, false);
yann@1
   137
	DLG_COLOR(check_selected,   COLOR_YELLOW, COLOR_RED,   true);
yann@1
   138
yann@1
   139
	DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
yann@1
   140
	DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
yann@1
   141
}
yann@1
   142
yann@1
   143
static void set_bluetitle_theme(void)
yann@1
   144
{
yann@1
   145
	set_classic_theme();
yann@1
   146
	DLG_COLOR(title,               COLOR_BLUE,   COLOR_WHITE, true);
yann@1
   147
	DLG_COLOR(button_key_active,   COLOR_YELLOW, COLOR_BLUE,  true);
yann@1
   148
	DLG_COLOR(button_label_active, COLOR_WHITE,  COLOR_BLUE,  true);
yann@1
   149
	DLG_COLOR(searchbox_title,     COLOR_BLUE,   COLOR_WHITE, true);
yann@1
   150
	DLG_COLOR(position_indicator,  COLOR_BLUE,   COLOR_WHITE, true);
yann@1
   151
	DLG_COLOR(tag,                 COLOR_BLUE,   COLOR_WHITE, true);
yann@1
   152
	DLG_COLOR(tag_key,             COLOR_BLUE,   COLOR_WHITE, true);
yann@1
   153
yann@1
   154
}
yann@1
   155
yann@1
   156
/*
yann@1
   157
 * Select color theme
yann@1
   158
 */
yann@1
   159
static int set_theme(const char *theme)
yann@1
   160
{
yann@1
   161
	int use_color = 1;
yann@1
   162
	if (!theme)
yann@1
   163
		set_bluetitle_theme();
yann@1
   164
	else if (strcmp(theme, "classic") == 0)
yann@1
   165
		set_classic_theme();
yann@1
   166
	else if (strcmp(theme, "bluetitle") == 0)
yann@1
   167
		set_bluetitle_theme();
yann@1
   168
	else if (strcmp(theme, "blackbg") == 0)
yann@1
   169
		set_blackbg_theme();
yann@1
   170
	else if (strcmp(theme, "mono") == 0)
yann@1
   171
		use_color = 0;
yann@1
   172
yann@1
   173
	return use_color;
yann@1
   174
}
yann@1
   175
yann@1
   176
static void init_one_color(struct dialog_color *color)
yann@1
   177
{
yann@1
   178
	static int pair = 0;
yann@1
   179
yann@1
   180
	pair++;
yann@1
   181
	init_pair(pair, color->fg, color->bg);
yann@1
   182
	if (color->hl)
yann@1
   183
		color->atr = A_BOLD | COLOR_PAIR(pair);
yann@1
   184
	else
yann@1
   185
		color->atr = COLOR_PAIR(pair);
yann@1
   186
}
yann@1
   187
yann@1
   188
static void init_dialog_colors(void)
yann@1
   189
{
yann@1
   190
	init_one_color(&dlg.screen);
yann@1
   191
	init_one_color(&dlg.shadow);
yann@1
   192
	init_one_color(&dlg.dialog);
yann@1
   193
	init_one_color(&dlg.title);
yann@1
   194
	init_one_color(&dlg.border);
yann@1
   195
	init_one_color(&dlg.button_active);
yann@1
   196
	init_one_color(&dlg.button_inactive);
yann@1
   197
	init_one_color(&dlg.button_key_active);
yann@1
   198
	init_one_color(&dlg.button_key_inactive);
yann@1
   199
	init_one_color(&dlg.button_label_active);
yann@1
   200
	init_one_color(&dlg.button_label_inactive);
yann@1
   201
	init_one_color(&dlg.inputbox);
yann@1
   202
	init_one_color(&dlg.inputbox_border);
yann@1
   203
	init_one_color(&dlg.searchbox);
yann@1
   204
	init_one_color(&dlg.searchbox_title);
yann@1
   205
	init_one_color(&dlg.searchbox_border);
yann@1
   206
	init_one_color(&dlg.position_indicator);
yann@1
   207
	init_one_color(&dlg.menubox);
yann@1
   208
	init_one_color(&dlg.menubox_border);
yann@1
   209
	init_one_color(&dlg.item);
yann@1
   210
	init_one_color(&dlg.item_selected);
yann@1
   211
	init_one_color(&dlg.tag);
yann@1
   212
	init_one_color(&dlg.tag_selected);
yann@1
   213
	init_one_color(&dlg.tag_key);
yann@1
   214
	init_one_color(&dlg.tag_key_selected);
yann@1
   215
	init_one_color(&dlg.check);
yann@1
   216
	init_one_color(&dlg.check_selected);
yann@1
   217
	init_one_color(&dlg.uarrow);
yann@1
   218
	init_one_color(&dlg.darrow);
yann@1
   219
}
yann@1
   220
yann@1
   221
/*
yann@1
   222
 * Setup for color display
yann@1
   223
 */
yann@1
   224
static void color_setup(const char *theme)
yann@1
   225
{
yann@943
   226
	int use_color;
yann@943
   227
yann@943
   228
	use_color = set_theme(theme);
yann@943
   229
	if (use_color && has_colors()) {
yann@943
   230
		start_color();
yann@943
   231
		init_dialog_colors();
yann@943
   232
	} else
yann@1
   233
		set_mono_theme();
yann@1
   234
}
yann@1
   235
yann@1
   236
/*
yann@1
   237
 * Set window to attribute 'attr'
yann@1
   238
 */
yann@1
   239
void attr_clear(WINDOW * win, int height, int width, chtype attr)
yann@1
   240
{
yann@1
   241
	int i, j;
yann@1
   242
yann@1
   243
	wattrset(win, attr);
yann@1
   244
	for (i = 0; i < height; i++) {
yann@1
   245
		wmove(win, i, 0);
yann@1
   246
		for (j = 0; j < width; j++)
yann@1
   247
			waddch(win, ' ');
yann@1
   248
	}
yann@1
   249
	touchwin(win);
yann@1
   250
}
yann@1
   251
yann@1
   252
void dialog_clear(void)
yann@1
   253
{
yann@1
   254
	attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
yann@1
   255
	/* Display background title if it exists ... - SLH */
yann@1
   256
	if (dlg.backtitle != NULL) {
yann@1
   257
		int i;
yann@1
   258
yann@1
   259
		wattrset(stdscr, dlg.screen.atr);
yann@1
   260
		mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
yann@1
   261
		wmove(stdscr, 1, 1);
yann@1
   262
		for (i = 1; i < COLS - 1; i++)
yann@1
   263
			waddch(stdscr, ACS_HLINE);
yann@1
   264
	}
yann@1
   265
	wnoutrefresh(stdscr);
yann@1
   266
}
yann@1
   267
yann@1
   268
/*
yann@1
   269
 * Do some initialization for dialog
yann@1
   270
 */
yann@943
   271
int init_dialog(const char *backtitle)
yann@1
   272
{
yann@943
   273
	int height, width;
yann@943
   274
yann@943
   275
	initscr();		/* Init curses */
yann@943
   276
	getmaxyx(stdscr, height, width);
yann@943
   277
	if (height < 19 || width < 80) {
yann@943
   278
		endwin();
yann@943
   279
		return -ERRDISPLAYTOOSMALL;
yann@943
   280
	}
yann@943
   281
yann@1
   282
	dlg.backtitle = backtitle;
yann@1
   283
	color_setup(getenv("MENUCONFIG_COLOR"));
yann@1
   284
yann@1
   285
	keypad(stdscr, TRUE);
yann@1
   286
	cbreak();
yann@1
   287
	noecho();
yann@1
   288
	dialog_clear();
yann@943
   289
yann@943
   290
	return 0;
yann@943
   291
}
yann@943
   292
yann@943
   293
void set_dialog_backtitle(const char *backtitle)
yann@943
   294
{
yann@943
   295
	dlg.backtitle = backtitle;
yann@1
   296
}
yann@1
   297
yann@1
   298
/*
yann@1
   299
 * End using dialog functions.
yann@1
   300
 */
yann@943
   301
void end_dialog(int x, int y)
yann@1
   302
{
yann@943
   303
	/* move cursor back to original position */
yann@943
   304
	move(y, x);
yann@943
   305
	refresh();
yann@1
   306
	endwin();
yann@1
   307
}
yann@1
   308
yann@1
   309
/* Print the title of the dialog. Center the title and truncate
yann@1
   310
 * tile if wider than dialog (- 2 chars).
yann@1
   311
 **/
yann@1
   312
void print_title(WINDOW *dialog, const char *title, int width)
yann@1
   313
{
yann@1
   314
	if (title) {
yann@1
   315
		int tlen = MIN(width - 2, strlen(title));
yann@1
   316
		wattrset(dialog, dlg.title.atr);
yann@1
   317
		mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
yann@1
   318
		mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
yann@1
   319
		waddch(dialog, ' ');
yann@1
   320
	}
yann@1
   321
}
yann@1
   322
yann@1
   323
/*
yann@1
   324
 * Print a string of text in a window, automatically wrap around to the
yann@1
   325
 * next line if the string is too long to fit on one line. Newline
yann@1
   326
 * characters '\n' are replaced by spaces.  We start on a new line
yann@1
   327
 * if there is no room for at least 4 nonblanks following a double-space.
yann@1
   328
 */
yann@1
   329
void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x)
yann@1
   330
{
yann@1
   331
	int newl, cur_x, cur_y;
yann@1
   332
	int i, prompt_len, room, wlen;
yann@1
   333
	char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
yann@1
   334
yann@1
   335
	strcpy(tempstr, prompt);
yann@1
   336
yann@1
   337
	prompt_len = strlen(tempstr);
yann@1
   338
yann@1
   339
	/*
yann@1
   340
	 * Remove newlines
yann@1
   341
	 */
yann@1
   342
	for (i = 0; i < prompt_len; i++) {
yann@1
   343
		if (tempstr[i] == '\n')
yann@1
   344
			tempstr[i] = ' ';
yann@1
   345
	}
yann@1
   346
yann@1
   347
	if (prompt_len <= width - x * 2) {	/* If prompt is short */
yann@1
   348
		wmove(win, y, (width - prompt_len) / 2);
yann@1
   349
		waddstr(win, tempstr);
yann@1
   350
	} else {
yann@1
   351
		cur_x = x;
yann@1
   352
		cur_y = y;
yann@1
   353
		newl = 1;
yann@1
   354
		word = tempstr;
yann@1
   355
		while (word && *word) {
yann@943
   356
			sp = strchr(word, ' ');
yann@1
   357
			if (sp)
yann@1
   358
				*sp++ = 0;
yann@1
   359
yann@1
   360
			/* Wrap to next line if either the word does not fit,
yann@1
   361
			   or it is the first word of a new sentence, and it is
yann@1
   362
			   short, and the next word does not fit. */
yann@1
   363
			room = width - cur_x;
yann@1
   364
			wlen = strlen(word);
yann@1
   365
			if (wlen > room ||
yann@1
   366
			    (newl && wlen < 4 && sp
yann@1
   367
			     && wlen + 1 + strlen(sp) > room
yann@943
   368
			     && (!(sp2 = strchr(sp, ' '))
yann@1
   369
				 || wlen + 1 + (sp2 - sp) > room))) {
yann@1
   370
				cur_y++;
yann@1
   371
				cur_x = x;
yann@1
   372
			}
yann@1
   373
			wmove(win, cur_y, cur_x);
yann@1
   374
			waddstr(win, word);
yann@1
   375
			getyx(win, cur_y, cur_x);
yann@1
   376
			cur_x++;
yann@1
   377
			if (sp && *sp == ' ') {
yann@1
   378
				cur_x++;	/* double space */
yann@1
   379
				while (*++sp == ' ') ;
yann@1
   380
				newl = 1;
yann@1
   381
			} else
yann@1
   382
				newl = 0;
yann@1
   383
			word = sp;
yann@1
   384
		}
yann@1
   385
	}
yann@1
   386
}
yann@1
   387
yann@1
   388
/*
yann@1
   389
 * Print a button
yann@1
   390
 */
yann@1
   391
void print_button(WINDOW * win, const char *label, int y, int x, int selected)
yann@1
   392
{
yann@1
   393
	int i, temp;
yann@1
   394
yann@1
   395
	wmove(win, y, x);
yann@1
   396
	wattrset(win, selected ? dlg.button_active.atr
yann@1
   397
		 : dlg.button_inactive.atr);
yann@1
   398
	waddstr(win, "<");
yann@1
   399
	temp = strspn(label, " ");
yann@1
   400
	label += temp;
yann@1
   401
	wattrset(win, selected ? dlg.button_label_active.atr
yann@1
   402
		 : dlg.button_label_inactive.atr);
yann@1
   403
	for (i = 0; i < temp; i++)
yann@1
   404
		waddch(win, ' ');
yann@1
   405
	wattrset(win, selected ? dlg.button_key_active.atr
yann@1
   406
		 : dlg.button_key_inactive.atr);
yann@1
   407
	waddch(win, label[0]);
yann@1
   408
	wattrset(win, selected ? dlg.button_label_active.atr
yann@1
   409
		 : dlg.button_label_inactive.atr);
yann@1
   410
	waddstr(win, (char *)label + 1);
yann@1
   411
	wattrset(win, selected ? dlg.button_active.atr
yann@1
   412
		 : dlg.button_inactive.atr);
yann@1
   413
	waddstr(win, ">");
yann@1
   414
	wmove(win, y, x + temp + 1);
yann@1
   415
}
yann@1
   416
yann@1
   417
/*
yann@1
   418
 * Draw a rectangular box with line drawing characters
yann@1
   419
 */
yann@1
   420
void
yann@1
   421
draw_box(WINDOW * win, int y, int x, int height, int width,
yann@1
   422
	 chtype box, chtype border)
yann@1
   423
{
yann@1
   424
	int i, j;
yann@1
   425
yann@1
   426
	wattrset(win, 0);
yann@1
   427
	for (i = 0; i < height; i++) {
yann@1
   428
		wmove(win, y + i, x);
yann@1
   429
		for (j = 0; j < width; j++)
yann@1
   430
			if (!i && !j)
yann@1
   431
				waddch(win, border | ACS_ULCORNER);
yann@1
   432
			else if (i == height - 1 && !j)
yann@1
   433
				waddch(win, border | ACS_LLCORNER);
yann@1
   434
			else if (!i && j == width - 1)
yann@1
   435
				waddch(win, box | ACS_URCORNER);
yann@1
   436
			else if (i == height - 1 && j == width - 1)
yann@1
   437
				waddch(win, box | ACS_LRCORNER);
yann@1
   438
			else if (!i)
yann@1
   439
				waddch(win, border | ACS_HLINE);
yann@1
   440
			else if (i == height - 1)
yann@1
   441
				waddch(win, box | ACS_HLINE);
yann@1
   442
			else if (!j)
yann@1
   443
				waddch(win, border | ACS_VLINE);
yann@1
   444
			else if (j == width - 1)
yann@1
   445
				waddch(win, box | ACS_VLINE);
yann@1
   446
			else
yann@1
   447
				waddch(win, box | ' ');
yann@1
   448
	}
yann@1
   449
}
yann@1
   450
yann@1
   451
/*
yann@1
   452
 * Draw shadows along the right and bottom edge to give a more 3D look
yann@1
   453
 * to the boxes
yann@1
   454
 */
yann@1
   455
void draw_shadow(WINDOW * win, int y, int x, int height, int width)
yann@1
   456
{
yann@1
   457
	int i;
yann@1
   458
yann@1
   459
	if (has_colors()) {	/* Whether terminal supports color? */
yann@1
   460
		wattrset(win, dlg.shadow.atr);
yann@1
   461
		wmove(win, y + height, x + 2);
yann@1
   462
		for (i = 0; i < width; i++)
yann@1
   463
			waddch(win, winch(win) & A_CHARTEXT);
yann@1
   464
		for (i = y + 1; i < y + height + 1; i++) {
yann@1
   465
			wmove(win, i, x + width);
yann@1
   466
			waddch(win, winch(win) & A_CHARTEXT);
yann@1
   467
			waddch(win, winch(win) & A_CHARTEXT);
yann@1
   468
		}
yann@1
   469
		wnoutrefresh(win);
yann@1
   470
	}
yann@1
   471
}
yann@1
   472
yann@1
   473
/*
yann@1
   474
 *  Return the position of the first alphabetic character in a string.
yann@1
   475
 */
yann@1
   476
int first_alpha(const char *string, const char *exempt)
yann@1
   477
{
yann@1
   478
	int i, in_paren = 0, c;
yann@1
   479
yann@1
   480
	for (i = 0; i < strlen(string); i++) {
yann@1
   481
		c = tolower(string[i]);
yann@1
   482
yann@1
   483
		if (strchr("<[(", c))
yann@1
   484
			++in_paren;
yann@1
   485
		if (strchr(">])", c) && in_paren > 0)
yann@1
   486
			--in_paren;
yann@1
   487
yann@1
   488
		if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0)
yann@1
   489
			return i;
yann@1
   490
	}
yann@1
   491
yann@1
   492
	return 0;
yann@1
   493
}
yann@1
   494
yann@1
   495
/*
yann@1
   496
 * ncurses uses ESC to detect escaped char sequences. This resutl in
yann@1
   497
 * a small timeout before ESC is actually delivered to the application.
yann@1
   498
 * lxdialog suggest <ESC> <ESC> which is correctly translated to two
yann@1
   499
 * times esc. But then we need to ignore the second esc to avoid stepping
yann@1
   500
 * out one menu too much. Filter away all escaped key sequences since
yann@1
   501
 * keypad(FALSE) turn off ncurses support for escape sequences - and thats
yann@1
   502
 * needed to make notimeout() do as expected.
yann@1
   503
 */
yann@1
   504
int on_key_esc(WINDOW *win)
yann@1
   505
{
yann@1
   506
	int key;
yann@1
   507
	int key2;
yann@1
   508
	int key3;
yann@1
   509
yann@1
   510
	nodelay(win, TRUE);
yann@1
   511
	keypad(win, FALSE);
yann@1
   512
	key = wgetch(win);
yann@1
   513
	key2 = wgetch(win);
yann@1
   514
	do {
yann@1
   515
		key3 = wgetch(win);
yann@1
   516
	} while (key3 != ERR);
yann@1
   517
	nodelay(win, FALSE);
yann@1
   518
	keypad(win, TRUE);
yann@1
   519
	if (key == KEY_ESC && key2 == ERR)
yann@1
   520
		return KEY_ESC;
yann@1
   521
	else if (key != ERR && key != KEY_ESC && key2 == ERR)
yann@1
   522
		ungetch(key);
yann@1
   523
yann@1
   524
	return -1;
yann@1
   525
}
yann@1
   526
yann@1
   527
/* redraw screen in new size */
yann@1
   528
int on_key_resize(void)
yann@1
   529
{
yann@1
   530
	dialog_clear();
yann@1
   531
	return KEY_RESIZE;
yann@1
   532
}
yann@1
   533
yann@1
   534
struct dialog_list *item_cur;
yann@1
   535
struct dialog_list item_nil;
yann@1
   536
struct dialog_list *item_head;
yann@1
   537
yann@1
   538
void item_reset(void)
yann@1
   539
{
yann@1
   540
	struct dialog_list *p, *next;
yann@1
   541
yann@1
   542
	for (p = item_head; p; p = next) {
yann@1
   543
		next = p->next;
yann@1
   544
		free(p);
yann@1
   545
	}
yann@1
   546
	item_head = NULL;
yann@1
   547
	item_cur = &item_nil;
yann@1
   548
}
yann@1
   549
yann@1
   550
void item_make(const char *fmt, ...)
yann@1
   551
{
yann@1
   552
	va_list ap;
yann@1
   553
	struct dialog_list *p = malloc(sizeof(*p));
yann@1
   554
yann@1
   555
	if (item_head)
yann@1
   556
		item_cur->next = p;
yann@1
   557
	else
yann@1
   558
		item_head = p;
yann@1
   559
	item_cur = p;
yann@1
   560
	memset(p, 0, sizeof(*p));
yann@1
   561
yann@1
   562
	va_start(ap, fmt);
yann@1
   563
	vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
yann@1
   564
	va_end(ap);
yann@1
   565
}
yann@1
   566
yann@1
   567
void item_add_str(const char *fmt, ...)
yann@1
   568
{
yann@1
   569
	va_list ap;
yann@1
   570
        size_t avail;
yann@1
   571
yann@1
   572
	avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
yann@1
   573
yann@1
   574
	va_start(ap, fmt);
yann@1
   575
	vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
yann@1
   576
		  avail, fmt, ap);
yann@1
   577
	item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
yann@1
   578
	va_end(ap);
yann@1
   579
}
yann@1
   580
yann@1
   581
void item_set_tag(char tag)
yann@1
   582
{
yann@1
   583
	item_cur->node.tag = tag;
yann@1
   584
}
yann@1
   585
void item_set_data(void *ptr)
yann@1
   586
{
yann@1
   587
	item_cur->node.data = ptr;
yann@1
   588
}
yann@1
   589
yann@1
   590
void item_set_selected(int val)
yann@1
   591
{
yann@1
   592
	item_cur->node.selected = val;
yann@1
   593
}
yann@1
   594
yann@1
   595
int item_activate_selected(void)
yann@1
   596
{
yann@1
   597
	item_foreach()
yann@1
   598
		if (item_is_selected())
yann@1
   599
			return 1;
yann@1
   600
	return 0;
yann@1
   601
}
yann@1
   602
yann@1
   603
void *item_data(void)
yann@1
   604
{
yann@1
   605
	return item_cur->node.data;
yann@1
   606
}
yann@1
   607
yann@1
   608
char item_tag(void)
yann@1
   609
{
yann@1
   610
	return item_cur->node.tag;
yann@1
   611
}
yann@1
   612
yann@1
   613
int item_count(void)
yann@1
   614
{
yann@1
   615
	int n = 0;
yann@1
   616
	struct dialog_list *p;
yann@1
   617
yann@1
   618
	for (p = item_head; p; p = p->next)
yann@1
   619
		n++;
yann@1
   620
	return n;
yann@1
   621
}
yann@1
   622
yann@1
   623
void item_set(int n)
yann@1
   624
{
yann@1
   625
	int i = 0;
yann@1
   626
	item_foreach()
yann@1
   627
		if (i++ == n)
yann@1
   628
			return;
yann@1
   629
}
yann@1
   630
yann@1
   631
int item_n(void)
yann@1
   632
{
yann@1
   633
	int n = 0;
yann@1
   634
	struct dialog_list *p;
yann@1
   635
yann@1
   636
	for (p = item_head; p; p = p->next) {
yann@1
   637
		if (p == item_cur)
yann@1
   638
			return n;
yann@1
   639
		n++;
yann@1
   640
	}
yann@1
   641
	return 0;
yann@1
   642
}
yann@1
   643
yann@1
   644
const char *item_str(void)
yann@1
   645
{
yann@1
   646
	return item_cur->node.str;
yann@1
   647
}
yann@1
   648
yann@1
   649
int item_is_selected(void)
yann@1
   650
{
yann@1
   651
	return (item_cur->node.selected != 0);
yann@1
   652
}
yann@1
   653
yann@1
   654
int item_is_tag(char tag)
yann@1
   655
{
yann@1
   656
	return (item_cur->node.tag == tag);
yann@1
   657
}