kconfig/lxdialog/util.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Jan 17 23:06:02 2010 +0100 (2010-01-17)
changeset 1740 c57458bb354d
parent 1 eeea35fbf182
child 2448 a103abae1560
permissions -rw-r--r--
configure: do not require hg when configuring in an hg clone

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