作者tsaikd.bbs@bbs.cs.nchu.edu.tw (千人斬) 看板: plan
標題[修正] window.c pans() pmsg() 自動調整寬度並可支援多行訊息
時間中興資科 (2004/10/05 Tue 11:20:03) Updated: 2004/12/30
整合itoc大大 [修正] window.c pans() 自動調整寬度
及小弟之前的 [功能] window.c pmsg 及 pans 可支援多行訊息
使 pans() 的 title
及 pmsg() 的 msg
可以用 '\n' 的方式來斷行,而不會造成畫面錯亂
: maple/window.c
+ #define COLOR_POPMENU_HEADER "\033[1;37;44m" /* 選單標題顏色 */
+ #define COLOR_POPMENU_BODY "\033[32;40m" /* 選單內文顏色 */
static screenline slt[t_lines];
static int x_roll;
+ static int desc_maxlen; /* 最長選項的長度 */
: maple/window.c : pans()
int /* 傳回小寫字母或數字 */
pans(x, y, title, desc)
int x, y; /* -1: 自動找出畫面中心來放 menu */
char *title;
char *desc[];
{
int cur, old_cur, max, ch;
char hotkey;
+ /* 找出 title 及 desc 中最長的長度 */
+ char buf[512]; /* tsaikd.041005: title 可能有好幾行 */
+ char *tmp;
+
+ strcpy(buf, title);
+ desc_maxlen = strlen(strtok(buf, "\n"));
+ while (tmp = strtok(NULL, "\n"))
+ desc_maxlen = (desc_maxlen > strlen(tmp)) ? desc_maxlen : strlen(tmp);
+ for (ch = 1; desc[ch]; ch++)
+ {
+ if (desc_maxlen < strlen(desc[ch]))
+ desc_maxlen = strlen(desc[ch]);
+ }
+ desc_maxlen += (desc_maxlen % 2) + 2; /* 變成偶數 */
x_roll = vs_save(slt);
hotkey = desc[0][0];
+ /* tsaikd.041007: 自動找位置 */
+ if (x < 0)
+ x = (b_lines - 4 - ch) / 2;
+ if (y < 0)
+ y = (b_cols - 12 - desc_maxlen) / 2;
/* 畫出整個選單 */
max = draw_menu(x, y, title, desc, hotkey, &cur);
...
...
if (old_cur != cur) /* 游標變動位置才需要重繪 */
{
+ int i, shift;
+ shift = 0;
+ for (i = 0; i < strlen(title); i++)
+ {
+ if (title[i] == '\n')
+ shift++;
+ }
+ draw_item(x + old_cur + shift, y, desc[old_cur], hotkey, 0);
+ draw_item(x + cur + shift, y, desc[cur], hotkey, 1);
- draw_item(x + old_cur, y, desc[old_cur], hotkey, 0);
- draw_item(x + cur, y, desc[cur], hotkey, 1);
old_cur = cur;
/* 避免在偵測左右鍵全形下,按左鍵會跳離二層選單的問題 */
move(b_lines, 0);
}
: maple/window.c : 重寫 draw_menu()
static int /* 回傳總共有幾個選項 */
draw_menu(x, y, title, desc, hotkey, cur)
int x, y;
char *title;
char *desc[];
char hotkey;
int *cur; /* 回傳預設值所在位置 */
{
int i, meet;
char buf[128];
/* tsaikd.041005: title 最大可以放五行,最後一個必需是 NULL */
char *ptitle[5 + 1], buf_title[512];
/* tsaikd.041005: 把 title 分行 */
strcpy(buf_title, title);
ptitle[0] = strtok(buf_title, "\n");
for (i = 0; i < 5; i++)
{
if (!(ptitle[i] = strtok(NULL, "\n")))
break;
}
ptitle[i] = NULL; /* tsaikd.041005: 最後一個必需是 NULL */
/* tsaikd.041005: 畫出上邊線 */
strcpy(buf, " ╭");
for (i = -6; i < desc_maxlen; i += 2)
strcat(buf, "─");
strcat(buf, "╮ ");
draw_line(x++, y, buf);
/* tsaikd.041005: 印出 title */
for (i = 0; ptitle[i]; i++)
{
/* tsaikd.041005: 借用 meet */
meet = ptitle[1] ? desc_maxlen :
strlen(ptitle[i]) + (strlen(ptitle[i]) % 2);
sprintf(buf, " │" COLOR_POPMENU_HEADER " %*s%-*s \033[m│ ",
(desc_maxlen-meet) >> 1 + 1, " ",
(desc_maxlen+meet) >> 1, ptitle[i]);
draw_line(x++, y, buf);
}
/* tsaikd.041005: 畫出 title 與選項的分隔線 */
strcpy(buf, " ├");
for (i = -6; i < desc_maxlen; i += 2)
strcat(buf, "─");
strcat(buf, "┤ ");
draw_line(x++, y, buf);
/* tsaikd.041005: 印出選項 */
for (i = 1; desc[i]; i++)
{
meet = (desc[i][0] == hotkey);
draw_item(x++, y, desc[i], hotkey, meet);
if (meet)
*cur = i;
}
meet = i;
/* tsaikd.041005: 畫出下邊線 */
strcpy(buf, " ╰");
for (i = -6; i < desc_maxlen; i += 2)
strcat(buf, "─");
strcat(buf, "╯ ");
draw_line(x, y, buf);
/* 避免在偵測左右鍵全形下,按左鍵會跳離二層選單的問題 */
move(b_lines, 0);
return meet - 1;
}
: maple/window.c : draw_item()
- sprintf(buf, " │%s%c %c%c%c%-25s \033[m│ ",
- mode ? COLOR4 : "\033[30;47m", mode ? '>' : ' ',
- (hotkey == *desc) ? '[' : '(', *desc,
- (hotkey == *desc) ? ']' : ')', desc + 1);
+ sprintf(buf, " │%s%s %c%c%c%-*s \033[m│ ",
+ mode ? COLOR4 : COLOR_POPMENU_BODY, mode ? "→" : " ",
+ (hotkey == *desc) ? '[' : '(', *desc,
+ (hotkey == *desc) ? ']' : ')', desc_maxlen - 1, desc + 1);
: maple/windows.c : pmsg()
int
pmsg(msg)
char *msg; /* 不可為 NULL */
{
int len, x, y, i;
- char buf[80];
+ char buf[512];
+ char *pbuf; /* tsaikd.041005: 有分行時找出最長的一行 */
x_roll = vs_save(slt);
- len = strlen(msg);
+ strcpy(buf, msg);
+ len = strlen(strtok(buf, "\n"));
+ for (i = 1; (pbuf = strtok(NULL, "\n")); i++)
+ len = len < strlen(pbuf) ? strlen(pbuf) : len;
if (len < 16) /* 取 msg title 其中較長者為 len */
len = 16;
if (len % 2) /* 變成偶數 */
len++;
- x = (b_lines - 4) >> 1; /* 置中 */
+ x = (b_lines - i - 4) >> 1; /* 置中 */
y = (b_cols - 8 - len) >> 1;
...
...
strcpy(buf, "├");
for (i = -4; i < len; i += 2)
strcat(buf, "─");
strcat(buf, "┤");
draw_line(x++, y, buf);
- sprintf(buf, "│\033[30;47m %-*s \033[m│", len, msg);
- draw_line(x++, y, buf);
+ while (1) /* tsaikd.041005: 把 msg 依照 \n 分行印出 */
+ {
+ sprintf(buf, "│\033[30;47m %-*s", len, msg);
+ strtok(buf, "\n");
+ sprintf(buf, "%-*s \033[m│", len + 12, buf);
+ draw_line(x++, y, buf);
+ if (!(msg = strstr(msg, "\n")))
+ break;
+ msg++;
+ }
strcpy(buf, "╰");
: 如果有做
: [功能] visio.c 視窗型的 Y/N
: 那麼還要將 visio.c : vans() 改成這樣
int
vans(prompt)
char *prompt;
{
char ans[3];
+#ifdef POPUP_ANSWER
+ int len;
+ char buf[80], *str, *menu[4];
+
+ if (str = (char *) strrchr(prompt, '['))
+ {
+ if (str[-6] == 'Y' && str[-4] == 'N' && (str[1] == 'Y' || str[1] == 'N'))
+ {
+ strcpy(buf, prompt);
+ len = str - prompt;
+ str = buf + len;
+ *str = '\0';
+ str[2] = str[1];
+ menu[0] = str + 1;
+ menu[1] = "Yes 是";
+ menu[2] = "No 否";
+ menu[3] = NULL;
+
+ /* tsaikd.041005 找出 prompt 中最長的長度 */
+ len = strlen(strtok(buf, "\n"));
+ while (str = strtok(NULL, "\n"))
+ len = (len > strlen(str)) ? len : strlen(str);
+ len = len < 16 ? 16 : len;
+ strcpy(buf, prompt);
+ *(strrchr(buf, '[')) = '\0';
+ return pans((b_lines - 4) >> 1, (b_cols - 8 - len) >> 1, buf, menu);
+ }
+ }
+#endif
/* itoc.010812.註解: 會自動換成小寫的 */
return vget(b_lines, 0, prompt, ans, sizeof(ans), LCECHO);
}
--
┌┼ Author: 中興資科˙中興資科 e資獨秀 csNCHU.twbbs.org
└┘ Origin: tsaikd 從 140.116.104.202 發表