回精華區
作者itoc, 信區: itoc
標題[功能] 使用者自定主選單(2)
時間03/07/16
作者: itoc (風調雨順,國泰民安) 看板: plan
標題: [功能] 使用者自定主選單(2)
時間: Wed Jul 16 22:13:30 2003                          Updated: 2003/07/17

  使用者自定主選單(2) 編輯自定主選單

: menu.c 一開始

extern UCACHE *ushm;

+ static int launch_set();

: menu.c 在適當的選單加入

+ launch_set, PERM_VALID, M_XMODE,
+ "Menu       《 自定選單 》",

: menu.c 最後加入以下這整段

/* ----------------------------------------------------- */
/* 使用者自定 Quick Launch                               */
/* ----------------------------------------------------- */


#define MAX_LAUNCH      (22 - MENU_XPOS)

static char *fn_quick = "quick";


typedef struct
{
  int key;
  void *func;
  int umode;
  char *desc;
}       LaunchFunc;


/* 要加 list 的在這邊加 */


#define LAUNCHLIST_LEN  17


static LaunchFunc quick_cb[LAUNCHLIST_LEN + 1] =
{
  /* 編號不用照順序,也可以隨便給,只要是不重覆的整數即可,
     但是編號不能變動 (因為會存在 user 目錄的 quick 檔中) */

  /* 編號, 函式,  動態,     選單敘述 */

   1, Boards,     M_BOARD,  "Boards     ← 佈告討論 →",
   2, Class,      M_BOARD,  "Class      ← 分組討論 →",
   3, MyFavorite, M_MF,     "Favorite   ← 我的最愛 →",
   4, Gem,        M_GEM,    "Announce   ← 精華公佈 →",

 101, XoMbox,     M_RMAIL,  "Read       ← 閱\讀信件 →",
 102, m_send,     M_SMAIL,  "Mail       ← 站內寄信 →",
 103, m_internet, M_SMAIL,  "Internet   ← 寄依妹兒 →",

 201, t_pal,      M_PAL,    "GoodFriend ← 好友設定 →",
 202, XoUlist,    M_LUSERS, "Users      ← 遊客名單 →",
 203, t_query,    M_QUERY,  "Query      ← 查詢網友 →",
 204, t_display,  M_BMW,    "Display    ← 瀏覽水球 →",
 205, t_bmw,      M_BMW,    "Write      ← 回顧水球 →",
 206, bin/chat.so:t_chat", - M_CHAT, "Chat       ← 眾口鑠金 →",

 301, u_info,     M_XMODE,  "Info       ← 個人資料 →",
 302, u_setup,    M_UFILES, "Habit      ← 喜好模式 →",
 303, pad_view,   M_READA,  "Note       ← 觀看留言 →",

 401, "bin/enews.so:main_enews", - M_XMODE, "Kimo       ← 奇摩新聞 →",

  /* 最後一個固定是 0, goodbye */
  0, goodbye,     M_XMODE,  "Goodbye    ← 下次再會 →"
};


static int
launch_set()
{
  int i, num, keylist[MAX_LAUNCH];
  char buf[80];
  LaunchFunc *cb;

  /* 界面做得頗遜,只能支援到 LAUNCHLIST_LEN = 20,想改的人再自己改 :p */

  memset(keylist, 0, sizeof(keylist));

  clear();

  for (i = 0; i < LAUNCHLIST_LEN; i++)
  {
    cb = quick_cb + i;
    move(i + 2, 0);
    prints("%2d %s", i + 1, cb->desc);
  }

  i = 0;
  while (vget(b_lines, 0, "請選擇快捷列選項:", buf, 4, DOECHO))
  {
    num = atoi(buf) - 1;
    if (num >= 0 && num < LAUNCHLIST_LEN)
    {
      cb = quick_cb + num;
      keylist[i] = cb->key;
      move(i + 2, 40);
      prints("捷徑 %d:%s", i + 1, cb->desc);
      if (++i >= MAX_LAUNCH - 1)
      {
        sprintf(buf, "最多只能加 %d 個捷徑而已", MAX_LAUNCH - 1);
        vmsg(buf);
        break;
      }
    }
  }

  if (i)
  {
    /* 最後再補上一個捷徑:goodbye */
    keylist[i] = (quick_cb + LAUNCHLIST_LEN)->key;
    usr_fpath(buf, cuser.userid, fn_quick);
    unlink(buf);
    rec_add(buf, keylist, sizeof(keylist));
  }

  return 0;
}


/* ----------------------------------------------------- */
/* 使用 Quick Launch Skin                                */
/* ----------------------------------------------------- */


static MENU menu_launch[MAX_LAUNCH];


static int                      /* 回傳設了幾個 quick launch */
launch_load()
{
  int i, key, keylist[MAX_LAUNCH];
  char fpath[64];
  LaunchFunc *cb;
  MENU *menu;

  usr_fpath(fpath, cuser.userid, fn_quick);
  if (rec_get(fpath, keylist, sizeof(keylist), 0))
    return 0;

  menu = menu_launch;
  for (i = 0; i < MAX_LAUNCH; i++)
  {
    cb = quick_cb;
    do
    {
      key = cb->key;
      if (key == keylist[i])
        break;
      cb++;
    } while (key);

    menu->func = cb->func;
    menu->umode = cb->umode;
    menu->desc = cb->desc;
    menu++;

    if (!key)
      break;
  }

  return i;
}


void
skin()
{
  MENU *mptr;
  usint mode;
  int cc, cx;           /* current / previous cursor position */
  int max;              /* menu max */
  int cmd;
  char *str;
  int (*func) ();

  if (!(max = launch_load()))
  {
    menu();
    return;
  }

  mode = MENU_DRAW | MENU_FILM;
  cmd = KEY_HOME;           /* default command */

  for (;;)
  {
    if (mode & MENU_DRAW)
    {
      if (mode & MENU_FILM)
      {
        clear();
        movie();
        cx = -1;
      }

      vs_head("快捷列", NULL);

      for (mode = 0; mode <= max; mode++)
      {
        move(MENU_XPOS + mode, MENU_YPOS + 2);
        mptr = menu_launch + mode;
        str = mptr->desc;
        prints("(\033[1;36m%c\033[m)", *str++);
        outs(str);
        clrtoeol();
      }
    }

    mode = 0;

    switch (cmd)
    {
    case KEY_DOWN:
      cc = (cc == max) ? 0 : cc + 1;
      break;

    case KEY_UP:
      cc = (cc == 0) ? max : cc - 1;
      break;

    case Ctrl('A'): /* itoc.020829: 預設選項第一個 */
    case KEY_HOME:
      cc = 0;
      break;

    case KEY_END:
      cc = max;
      break;

    case KEY_PGUP:
      cc = (cc == 0) ? max : 0;
      break;

    case KEY_PGDN:
      cc = (cc == max) ? 0 : max;
      break;

    case '\n':
    case KEY_RIGHT:
      mptr = menu_launch + cc;
      cmd = mptr->umode;
      if (cmd >= 0)
      {
        utmp_mode(cmd);
        func = mptr->func;
        mode = (*func) ();
      }
      else                      /* dynamic load */
      {
        if (func = DL_get(mptr->func))
        {
          utmp_mode(-cmd);
          mode = (*func)();
        }
        else
          mode = XEASY;
      }

      utmp_mode(M_0MENU);

      if (mode == XEASY)
      {
        outz(feeter);
        mode = 0;
      }
      else
      {
        mode = MENU_DRAW | MENU_FILM;
      }

      cmd = mptr->desc[0];
      continue;

#ifdef EVERY_Z
    case Ctrl('Z'):
      every_Z(0);
      goto every_key;

    case Ctrl('U'):
      every_U(0);
      goto every_key;
#endif

    /* itoc.010911: Select everywhere,不再限制是在 M_0MENU */
    case 's':
    case Ctrl('S'):
      utmp_mode(M_BOARD);
      Select();
      goto every_key;

#ifdef MY_FAVORITE
    /* itoc.010911: Favorite everywhere,不再限制是在 M_0MENU */
    case 'f':
    case Ctrl('F'):
      if (HAS_PERM(PERM_BASIC)) /* itoc.010407: 要檢查權限 */
      {
        utmp_mode(M_MF);
        MyFavorite();
      }
      goto every_key;
#endif

    case Ctrl('X'):
      cuser.ufo &= ~UFO_USERSKIN;
      vmsg("重新上站後就會恢復原來的公版選單");
      goto default_key;

every_key:  /* 特殊鍵處理結束 */
      utmp_mode(M_0MENU);
      mode = MENU_DRAW | MENU_FILM;
      cmd = (menu_launch + cc)->desc[0];
      continue;

    case KEY_LEFT:
    case 'e':
      cmd = 'G';

default_key:
    default:

      if (cmd >= 'a' && cmd <= 'z')
        cmd -= 0x20;

      cc = 0;
      for (;;)
      {
        if ((menu_launch + cc)->desc[0] == cmd)
          break;
        if (++cc > max)
        {
          cc = cx;
          goto menu_key;
        }
      }
    }

    if (cc != cx)   /* 若游標移動位置 */
    {
#ifdef CURSOR_BAR
      if (cx >= 0)
      {
        move(MENU_XPOS + cx, MENU_YPOS);
        if (cx <= max)
        {
          mptr = menu_launch + cx;
          str = mptr->desc;
          prints("  (\033[1;36m%c\033[m)", *str++);
          prints("%s ", str);
        }
        else
        {
          outs("  ");
        }
      }
      move(MENU_XPOS + cc, MENU_YPOS);
      mptr = menu_launch + cc;
      str = mptr->desc;
      prints(COLOR4 "> (%c)", *str++);
      prints("%s \033[m", str);
      cx = cc;
#else       /* 沒有 CURSOR_BAR */
      if (cx >= 0)
      {
        move(MENU_XPOS + cx, MENU_YPOS);
        outc(' ');
      }
      move(MENU_XPOS + cc, MENU_YPOS);
      outc('>');
      cx = cc;
#endif
    }
    else        /* 若游標的位置沒有變 */
    {
#ifdef CURSOR_BAR
      move(MENU_XPOS + cc, MENU_YPOS);
      mptr = menu_launch + cc;
      str = mptr->desc;
      prints(COLOR4 "> (%c)", *str++);
      prints("%s \033[m", str);
#else
      move(MENU_XPOS + cc, MENU_YPOS + 1);
#endif
    }

menu_key:

    cmd = vkey();
  }
}

--
□ 本文章由 itocitoc.Dorm11.NCTU.edu.tw 發表
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻