回精華區
作者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 發表
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻