回精華區
作者itoc, 信區: itoc
標題[功能] pnote.c 答錄機
時間03/07/05
作者: itoc (風調雨順,國泰民安) 看板: plan
標題: [功能] 答錄機
時間: Sat Jul  5 16:11:44 2003                          Updated: 2003/07/05

: menu.c:vs_head()

void
vs_head(title, mid)
  char *title, *mid;
{
  char buf[40], ttl[60];
+ char fpath[64];
  int spc, len;

  ...
  ...

+ usr_fpath(fpath, cuser.userid, "pnote.dat.new");

  if (cutmp->ufo & UFO_BIFF)
  {
    mid = "\033[5;41m 郵差來按鈴了 \033[m";
    spc = 14;
  }
+ else if (rec_num(fpath, 1))
+ {
+   mid = "\033[5;41m 您有新留言喔 \033[m";
+   spc = 14;
+ }
  else

: menu.c 適當的選單加入

+ "bin/pnote.so:main_pnote", PERM_BASIC, - M_XMODE,
+ "Pnote      ├ 答錄留言 ┤",

: so/Makefile

SO =    ..... pnote.so

: so/pnote.c 加新程式

/*-------------------------------------------------------*/
/* pnote.c      ( NTHU CS MapleBBS Ver 3.10 )            */
/*-------------------------------------------------------*/
/* target : 答錄機                                       */
/* create : 98/04/14                                     */
/* update : 03/07/05                                     */
/* author : herb                                         */
/* recast : itoc.bbs@bbs.tnfsh.tn.edu.tw                 */
/*-------------------------------------------------------*/


#include "bbs.h"


#define MAX_PNOTE       10      /* 答錄機保留通數 */
#define MAXHINTLINES    10      /* 答錄機主人留言長度 */

/* binary 檔 */
static char *fn_pnote_dat_new = "pnote.dat.new";/* 答錄機資料庫新的留言 */
static char *fn_pnote_dat_old = "pnote.dat.old";/* 答錄機資料庫舊的留言 */

/* 純文字檔 */
static char *fn_pnote_hint = "pnote.hint";      /* 答錄機主人問候語 */
static char *fn_pnote_tmp = "pnote.tmp";        /* 秀出全部留言時的暫存檔 */


typedef struct
{
  time_t chrono;
  char userid[IDLEN + 1];
  char msg[3][71];
} PNOTE;


static int
pnote_init(pnotes, fpath)       /* 取出所有的留言 */
  PNOTE *pnotes;
  char *fpath;
{
  FILE *fp;
  int total;

  total = 0;
  if (fp = fopen(fpath, "r"))
  {
    while (fread(&pnotes[total], sizeof(PNOTE), 1, fp) == 1)
      total++;
    fclose(fp);
  }
  return total;
}


static void
pnote_show(pnote)
  PNOTE *pnote;
{
  int i;

  for (i = 8; i >= 4; i--)
  {
    move(i, 0);
    clrtoeol();
  }

  prints("\033[1;36m┌─── \033[37m%s\033[m 在 \033[33m%s\033[m 留言給您",
    pnote->userid, Btime(&pnote->chrono));
  outs("\n  ");
  outs(pnote->msg[0]);
  outs("\n  ");
  outs(pnote->msg[1]);
  outs("\n  ");
  outs(pnote->msg[2]);
  outs("\n\033[1;36m  ─────────────────────────────────────┘\033[m\n");
}


static void
pnote_hint(userid)              /* 秀出 userid 的主人問候語 */
  char *userid;
{
  int i;
  char buf[80];
  FILE *fp;

  clear();
  move(1, 0);

  usr_fpath(buf, userid, fn_pnote_hint);
  if (fp = fopen(buf, "r"))
  {
    outs("\033[1;34m● ────────────── \033[32m問候語\033[34m ────────────── ●\033[m\n");

    i = 0;
    while (i++ < MAXHINTLINES && fgets(buf, sizeof(buf), fp))
      outs(buf);

    outs("\033[1;34m● ──────────────────────────────── ●\033[m\n");
    fclose(fp);
  }
  else
  {
    prints("您好,這是 %s 的電話答錄機,", userid);
  }
  outs("\n請在聽到「嗶」聲後,開始留言,謝謝。");
}


static void
pnote_draw(userid)              /* 留言給 userid */
  char *userid;
{
  int i, cc;
  char fpath[64];
  PNOTE pnote;

  /* 開始留言 */
  do
  {
    pnote.msg[0][0] = pnote.msg[1][0] = pnote.msg[2][0] = '\0';
    move(14, 0);
    clrtobot();
    outs("\n請留言 (至多三行),按[Enter]結束");
    for (i = 0; (i < 3) &&
      vget(16 + i, 0, ":", pnote.msg[i], 71, DOECHO); i++);
    cc = vans("(S)存檔觀賞 (E)重新來過 (Q)算了?[S] ");
    if (cc == 'q' || i == 0)
      return;
  } while (cc == 'e');

  time(&pnote.chrono);
  strcpy(pnote.userid, cuser.userid);

  /* 寫入對方的留言檔 */
  usr_fpath(fpath, userid, fn_pnote_dat_new);
  if (rec_num(fpath, sizeof(PNOTE)) >= MAX_PNOTE)
  {
    vmsg("對方的答錄機已有過多新留言,無法再留言");
    return;
  }
  rec_add(fpath, &pnote, sizeof(PNOTE));
}


static void
pnote_view(pnotes, num)         /* 把 binary 檔改成文字檔,並印出來 */
  PNOTE *pnotes;
  int num;
{
  int i;
  char fpath[64];
  FILE *fp;
  PNOTE *pnote;

  usr_fpath(fpath, cuser.userid, fn_pnote_tmp);

  if (fp = fopen(fpath, "w"))
  {
    fputs("                  \033[1;32m★\033[37m 答 錄 機 中 的 留 言 \033[32m★\033[m\n\n", fp);
    for (i = 0; i < num; i++)
    {
      pnote = &pnotes[i];

      fprintf(fp, "\033[1;36m┌─── \033[37m%s\033[m 在 \033[33m%s\033[m 留言給您",
        pnote->userid, Btime(&pnote->chrono));
      fprintf(fp, "\n  %s\n  %s\n  ", pnote->msg[0], pnote->msg[1], pnote->msg[2]);
      fprintf(fp, "\n\033[1;36m──────────────────────────────────────┘\033[m\n");
    }
    fclose(fp);

    more(fpath, NULL);
    unlink(fpath);
  }
}


static void
Pnote(newflag)
  int newflag;                  /* 1:新留言 0:舊留言 */
{
  int pos, num;
  char fpath[64], prompt[80];
  PNOTE pnotes[MAX_PNOTE];

  usr_fpath(fpath, cuser.userid, newflag ? fn_pnote_dat_new :  fn_pnote_dat_old);
  if ((num = pnote_init(pnotes, fpath)) <= 0)
  {
    vmsg("您沒有留言");
    return;
  }

  vs_bar("答錄機");

  pos = 0;
  sprintf(prompt, "◎ 瀏覽留言 P)前翻 N)後翻 A)全部 %s K)刪除全部 Q)離開 [Q] ", newflag ? "S)保留" : "D)刪除");

  while (1)
  {
    if (pos < 0)                /* 全部留言都被刪除或被保留了 */
      return;

    move(2, 0);
    clrtoeol();
    prints("\033[1;36m答錄機裡的 \033[37m%d/%d\033[36m 通%s留言\033[m\n", pos + 1, num, newflag ? "新的" : "");
    pnote_show(&pnotes[pos]);

    switch (vans(prompt))
    {
    case 'p':
      pos = (pos == 0) ? num - 1 : pos - 1;
      break;

    case 'n':
      pos = (pos == num - 1) ? 0 : pos + 1;
      break;

    case 'a':
      pnote_view(&pnotes, num);
      break;

    case 's':
      if (newflag)
      {
        if (num >= MAX_PNOTE)
        {
          vmsg("您的的答錄機已保留過多留言");
        }
        else
        {
          char buf[64];

          usr_fpath(buf, cuser.userid, fn_pnote_dat_old);
          rec_add(buf, &pnotes[pos], sizeof(PNOTE));
          memcpy(&pnotes[pos], &pnotes[pos + 1], sizeof(PNOTE) * (num - pos - 1));
          rec_del(fpath, sizeof(PNOTE), pos, NULL);
          pos--;
          num--;
          vmsg("保留成功\");
        }
      }
      break;

    case 'd':
      if (!newflag)
      {
        memcpy(&pnotes[pos], &pnotes[pos + 1], sizeof(PNOTE) * (num - pos - 1));
        rec_del(fpath, sizeof(PNOTE), pos, NULL);
        pos--;
        num--;
      }
      break;

    case 'k':
      unlink(fpath);
      return;
      break;

    default:
      return;
    }
  }
}


static void
p_read()
{
  switch (vans("◎ 閱\讀留言 N)新的留言 S)被保存的留言 Q)取消?[Q] "))
  {
  case 'n':
    Pnote(1);
    break;

  case 's':
    Pnote(0);
    break;
  }
}


static void
p_call()
{
  ACCT acct;

  if (acct_get("您想留言給誰:", &acct) > 0)
  {
    pnote_hint(acct.userid);
    pnote_draw(acct.userid);
  }
}


static void
p_edithint()
{
  char fpath[64];

  switch (vans("◎ 主人留言 D)刪除 E)錄製 Q)取消?[Q] "))
  {
  case 'e':
    usr_fpath(fpath, cuser.userid, fn_pnote_hint);
    vedit(fpath, 0);
    vmsg("留言錄製完畢");
    break;

  case 'd':
    usr_fpath(fpath, cuser.userid, fn_pnote_hint);
    unlink(fpath);
    vmsg("留言刪除完畢");
    break;
  }
}


int
main_pnote()
{
  while (1)
  {
    switch (vans("★ 個人答錄機:R)閱\讀留言 C)錄製留言 E)更改問候語 Q)離開?[Q] "))
    {
    case 'r':
      p_read();
      break;

    case 'c':
      p_call();
      break;

    case 'e':
      p_edithint();
      break;

    default:
      return 0;
    }
  }
}

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