/*
 *  inputbox.c -- 实现输入框
 *
 *  原作者：Savio Lam (lam836@cs.cuhk.hk)
 *  修改为 Linux 内核配置：William Roadcap (roadcap@cfw.com)
 *
 *  本程序是自由软件；你可以根据自由软件基金会发布的 GNU 通用公共许可证的条款重新分发和/或修改它；要么是许可证的第 2 版，要么（如果你选择的话）是任何后续版本。
 *
 *  本程序的分发是希望它能有用，但没有任何保证；甚至没有适销性或适用于特定目的的隐含保证。详见 GNU 通用公共许可证以获取更多详细信息。
 *
 *  你应该已经收到了一份 GNU 通用公共许可证的副本；如果没有，请写信给自由软件基金会，Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "dialog.h" 
// 包含对话框相关的头文件

char dialog_input_result[MAX_LEN + 1]; 
// 定义一个字符数组用于存储输入框的结果

/*
 *  打印终止按钮
 */
static void print_buttons(WINDOW * dialog, int height, int width, int selected)
{
	int x = width / 2 - 11; 
	// 计算按钮的起始 x 坐标
	int y = height - 2; 
	// 计算按钮的起始 y 坐标

	print_button(dialog, gettext("  Ok  "), y, x, selected == 0); 
	// 打印 "Ok" 按钮
	print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); 
	// 打印 "Help" 按钮

	wmove(dialog, y, x + 1 + 14 * selected); 
	// 移动光标到选中的按钮位置
	wrefresh(dialog); 
	// 刷新对话框窗口
}

/*
 * 显示一个用于输入字符串的对话框
 */
int dialog_inputbox(const char *title, const char *prompt, int height, int width,
                    const char *init)
{
	int i, x, y, box_y, box_x, box_width; 
	// 定义一些变量用于计算和存储位置和大小
	int input_x = 0, key = 0, button = -1; 
	// 定义输入框的 x 坐标、按键和按钮状态变量
	int show_x, len, pos; 
	// 定义显示 x 坐标、字符串长度和光标位置变量
	char *instr = dialog_input_result; 
	// 指向输入结果的指针
	WINDOW *dialog; 
	// 定义对话框窗口指针

	if (!init)
		instr[0] = '\0'; 
		// 如果没有初始值，将输入结果置为空字符串
	else
		strcpy(instr, init); 
		// 否则，将初始值复制到输入结果中

do_resize: 
// 标签，用于处理窗口大小变化
	if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN)) 
	// 如果屏幕高度不足以显示对话框
		return -ERRDISPLAYTOOSMALL; 
		// 返回错误代码
	if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) 
	// 如果屏幕宽度不足以显示对话框
		return -ERRDISPLAYTOOSMALL; 
		// 返回错误代码

	/* 在屏幕上居中对话框 */
	x = (getmaxx(stdscr) - width) / 2; 
	// 计算对话框的 x 坐标
	y = (getmaxy(stdscr) - height) / 2; 
	// 计算对话框的 y 坐标

	draw_shadow(stdscr, y, x, height, width); 
	// 绘制对话框阴影

	dialog = newwin(height, width, y, x); 
	// 创建对话框窗口
	keypad(dialog, TRUE); 
	// 启用对话框窗口的键盘功能

	draw_box(dialog, 0, 0, height, width, 
	// 绘制对话框边框
		 dlg.dialog.atr, dlg.border.atr);
	wattrset(dialog, dlg.border.atr); 
	// 设置对话框边框属性
	mvwaddch(dialog, height - 3, 0, ACS_LTEE); 
	// 绘制左下角边框字符
	for (i = 0; i < width - 2; i++)
		waddch(dialog, ACS_HLINE); 
		// 绘制水平边框线
	wattrset(dialog, dlg.dialog.atr); 
	// 设置对话框属性
	waddch(dialog, ACS_RTEE); 
	// 绘制右下角边框字符

	print_title(dialog, title, width);
	 // 打印对话框标题

	wattrset(dialog, dlg.dialog.atr); 
	// 设置对话框属性
	print_autowrap(dialog, prompt, width - 2, 1, 3); 
	// 打印提示信息

	/* 绘制输入框 */
	box_width = width - 6; 
	// 计算输入框宽度
	getyx(dialog, y, x); 
	// 获取当前光标位置
	box_y = y + 2; 
	// 计算输入框的 y 坐标
	box_x = (width - box_width) / 2; 
	// 计算输入框的 x 坐标
	draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, 
	// 绘制输入框边框
		 dlg.dialog.atr, dlg.border.atr);

	print_buttons(dialog, height, width, 0); 
	// 打印按钮

	/* 设置初始值 */
	wmove(dialog, box_y, box_x); 
	// 移动光标到输入框起始位置
	wattrset(dialog, dlg.inputbox.atr); 
	// 设置输入框属性

	len = strlen(instr); 
	// 获取输入字符串的长度
	pos = len; 
	// 设置光标位置为字符串长度

	if (len >= box_width) { 
		// 如果字符串长度超过输入框宽度
		show_x = len - box_width + 1; 
		// 计算显示起始 x 坐标
		input_x = box_width - 1; 
		// 设置输入框的 x 坐标
		for (i = 0; i < box_width - 1; i++) 
		// 在输入框中显示字符串
			waddch(dialog, instr[show_x + i]);
	} else {
		show_x = 0; 
		// 设置显示起始 x 坐标为 0
		input_x = len; 
		// 设置输入框的 x 坐标为字符串长度
		waddstr(dialog, instr); 
		// 在输入框中显示字符串
	}

	wmove(dialog, box_y, box_x + input_x); 
	// 移动光标到字符串末尾

	wrefresh(dialog); 
	// 刷新对话框窗口

	while (key != KEY_ESC) {
		 // 循环直到按下 ESC 键
		key = wgetch(dialog); 
		// 获取按键

		if (button == -1) {	/* 输入框被选中 */
			switch (key) {
			case TAB: 
			// 制表符键
			case KEY_UP: 
			// 向上箭头键
			case KEY_DOWN: 
			// 向下箭头键
				break; 
				// 忽略这些按键
			case KEY_BACKSPACE: 
			// 退格键
			case 127: 
			// ASCII 退格键
				if (pos) { 
					// 如果光标位置不为 0
					wattrset(dialog, dlg.inputbox.atr); 
					// 设置输入框属性
					if (input_x == 0) { 
						// 如果输入框的 x 坐标为 0
						show_x--; 
						// 显示起始 x 坐标减 1
					} else
						input_x--; 
						// 输入框的 x 坐标减 1

					if (pos < len) { 
						// 如果光标位置小于字符串长度
						for (i = pos - 1; i < len; i++) 
						// 删除字符
							instr[i] = instr[i+1];
					}

					pos--; 
					// 光标位置减 1
					len--; 
					// 字符串长度减 1
					instr[len] = '\0';
					 // 字符串末尾添加空字符
					wmove(dialog, box_y, box_x); 
					// 移动光标到输入框起始位置
					for (i = 0; i < box_width; i++) { 
						// 在输入框中显示字符串
						if (!instr[show_x + i]) {
							waddch(dialog, ' '); 
							// 如果字符串结束，添加空格
							break;
						}
						waddch(dialog, instr[show_x + i]);
					}
					wmove(dialog, box_y, input_x + box_x); 
					// 移动光标到字符串末尾
					wrefresh(dialog); 
					// 刷新对话框窗口
				}
				continue; 
				// 继续循环
			case KEY_LEFT: 
			// 向左箭头键
				if (pos > 0) { 
					// 如果光标位置大于 0
					if (input_x > 0) { 
						// 如果输入
										print_buttons(dialog, height, width, 1); // 打印按钮，选中 "Help" 按钮
				break;
			case 0: // 如果 "Ok" 按钮被选中
				button = -1; // 表示输入框被选中
				print_buttons(dialog, height, width, 0);
				wmove(dialog, box_y, box_x + input_x); // 移动光标到输入框
				wrefresh(dialog); // 刷新对话框窗口
				break;
			case 1: // 如果 "Help" 按钮被选中
				button = 0; // 表示 "Ok" 按钮被选中
				print_buttons(dialog, height, width, 0);
				break;
			}
			break;
		case TAB: // 制表符键
		case KEY_DOWN: // 向下箭头键
		case KEY_RIGHT: // 向右箭头键
			switch (button) {
			case -1: // 如果输入框被选中
				button = 0; // 表示 "Ok" 按钮被选中
				print_buttons(dialog, height, width, 0);
				break;
			case 0: // 如果 "Ok" 按钮被选中
				button = 1; // 表示 "Help" 按钮被选中
				print_buttons(dialog, height, width, 1);
				break;
			case 1: // 如果 "Help" 按钮被选中
				button = -1; // 表示输入框被选中
				print_buttons(dialog, height, width, 0);
				wmove(dialog, box_y, box_x + input_x); // 移动光标到输入框
				wrefresh(dialog); // 刷新对话框窗口
				break;
			}
			break;
		case ' ': // 空格键
		case '\n': // 回车键
			delwin(dialog); // 删除对话框窗口
			return (button == -1 ? 0 : button); // 返回按钮状态
		case 'X': // 'X' 键
		case 'x': // 'x' 键
			key = KEY_ESC; // 设置按键为 ESC 键
			break;
		case KEY_ESC: // ESC 键
			key = on_key_esc(dialog); // 处理 ESC 键
			break;
		case KEY_RESIZE: // 窗口大小变化键
			delwin(dialog); // 删除对话框窗口
			on_key_resize(); // 处理窗口大小变化
			goto do_resize; // 跳转到 do_resize 标签重新绘制对话框
		}
	}

	delwin(dialog); // 删除对话框窗口
	return KEY_ESC; // 返回 ESC 键表示用户取消操作
}