<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    jinfeng_wang

    G-G-S,D-D-U!

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks
    UNIX 螢?zāi)粚?dǎo)向程式的發(fā)展利器 - curses
                                                             校園網(wǎng)路策進(jìn)會(huì)
    會(huì)長    林建宏
    
     ■ 前言
        相信您在網(wǎng)路上一定用過如  tin,elm 等工具, 這些軟體有項(xiàng)共同的特色,
    即他們能利用上下左右等方向鍵來控制游標(biāo)的位置.  除此之外, 這些程式
    的畫面也較為美觀. 對(duì) Programming 有興趣的朋友一定對(duì)此感到好奇, 也
    許他能在 PC 上用 Turbo C 輕易地寫出類似的程式, 然而, 但當(dāng)他將相同
    的程式一字不變地移到工作站上來編譯時(shí), 卻出現(xiàn)一堆抓也抓不完的錯(cuò)誤.
    其實(shí), 原因很簡單, 他使用的函式庫可能在 UNIX 上是沒有定義的.  有些
    在 Turbo-C 上被廣泛使用的一些函式, 可能在 UNIX 上是不被定義的.
        為了因應(yīng)網(wǎng)路上各式各樣的終端機(jī)形態(tài)  (terminal), UNIX 上特別發(fā)展出
    一套函式庫, 專門用來處理 UNIX 上游標(biāo)移動(dòng)及螢?zāi)坏娘@示.  這就是本篇
    文章要為您介紹的 - curses.h 函式庫.  利用這個(gè)函式庫, 您也可以寫出
    像 elm 般利用方向鍵來移動(dòng)光棒位置的程式. (CCCA 近來所提供的線上選
    課程式, 及程式服務(wù)界面, 即是筆者利用 curses 發(fā)展而成的 )
    
     ■ curses 的歷史與版本
        cureses 最早是由柏克萊大學(xué)的 Bill Joy 及 Ken Arnold 所發(fā)展出來的.
    當(dāng)時(shí)發(fā)展此一函式庫主要原因是為了提高程式對(duì)不同終端機(jī)的相容性而設(shè)
    計(jì)的.  因此, 利用 curses  發(fā)展出來的程式將和您所使用的終端機(jī)無關(guān).
    也就是說, 您不必?fù)?dān)心您的程式因?yàn)閾Q了一部終端機(jī)而無法使用.  這對(duì)程
    式設(shè)計(jì)師而言,    尤其是網(wǎng)路上程式的撰寫,    是件相當(dāng)重要的一件事.
    curses之所以能對(duì)上百種以上的終端機(jī)工作,  是因?yàn)樗鼘⑺薪K端機(jī)的資
    料, 存放在一個(gè)叫 termcap 的資料庫, ( 而在第二版的 System V 系統(tǒng)中
    , 新版的 curses 以 terminfo 取代原來的 termcap). 有了這些記錄, 程
    式就能夠知道遇到哪一種終端機(jī)時(shí),   須送什麼字元才能移動(dòng)游標(biāo)的位置,
    送什麼字元才能清除整個(gè)螢?zāi)磺宄? (* 注一)
        另外, 本文的介紹 以 System V 的 curses 版本為主.
    
     ■ 如何在您的程式使用 curses ?
        在您的 C 程式的檔頭將  <curses.h> include 進(jìn)來.當(dāng)您引進(jìn)  curses.h
    這個(gè)函式庫後, 系統(tǒng)會(huì)自動(dòng)將 <stdio.h> 和 <unctl.h>一并  include 進(jìn)
    來.另外,  在  System  V  版本中, <terminfo.h>  這個(gè)函式庫也將一并
    include進(jìn)來.
         #include <curses.h>
         main()
    {
    :  :
    :  :
    }
        當(dāng)然, 您的系統(tǒng)內(nèi)必須放有 curses.h 這個(gè)函式庫.
    
     ■ 如何編譯(compile)
        當(dāng)您編輯好您的程式, 在 UNIX 提示符號(hào)下鍵入:
          % /usr/5bin/cc [file.c] -lcurses
    ^^^^^^^
    引進(jìn) curses.h 這個(gè) library
        或 % /usr/5bin/cc [file.c] -lcurses -ltermlib
          (*注二)
    
     ■ 如何開始我的第一個(gè) curses 程式?
        在開始使用 curses 的一切命令之前, 您必須先利用  initscr()這個(gè)函式
    來開啟 curses 模式.
        相對(duì)的, 在結(jié)束  curses  模式前  ( 通常在您結(jié)束程式前  )  也必須以
    endwin()來關(guān)閉 curses 模式.
         #include <curses.h>
         main()
    {
    initscr();
    :  :
    :  :
    :  :
    endwin();
    }
        這是一般 curses 程式標(biāo)準(zhǔn)的模式.
        此外, 您可以就您程式所須, 而做不同的設(shè)定. 當(dāng)然, 您可以不做設(shè)定,而
    只是呼叫 initscr().
        您可以自己寫一個(gè)函式來存放所有您所須要的設(shè)定.  平常使用時(shí), 只要呼
    叫這個(gè)函式即可啟動(dòng) curses 并完成一切設(shè)定.
        下面的例子, 即是筆者將平常較常用的一些設(shè)定放在一個(gè)叫 initial()的函
    式內(nèi).
          void initial()
    {
    initscr();
    cbreak();
    nonl();
    noecho();
    intrflush(stdscr,FALSE);
    keypad(stdscr,TRUE);
    refresh();
    }
    
       各函式分別介紹如下:
         □ initscr()
              initscr()  是一般 curses 程式必須先呼叫的函數(shù), 一但這個(gè)函數(shù)
    被呼叫之後, 系統(tǒng)將根據(jù)終端機(jī)的形態(tài)并啟動(dòng) curses 模式.
    
         □ endwin()
              curses 通常以呼叫 endwin() 來結(jié)束程式.  endwin() 可用來關(guān)閉
    curses 模式, 或是暫時(shí)的跳離  curses 模式.如果您在程式中須要
    call shell ( 如呼叫 system() 函式 ) 或是需要做 system call,
    就必須先以   endwin()   暫時(shí)跳離   curses  模式.   最後再以
    wrefresh() doupdate() 來重返 curses 模式.
    
         □ cbreak()
    nocbreak()
              當(dāng) cbreak  模式被開啟後, 除了 DELETE 或 CTRL 等仍被視為特殊
    控制字元外一切輸入的字元將立刻被一一讀取.當(dāng)處於 nocbreak 模
    式時(shí), 從鍵盤輸入的字元將被儲(chǔ)存在  buffer 里直到輸入  RETURN
    或 NEWLINE.在較舊版的 curses 須呼叫 crmode(),nocrmode() 來
    取代 cbreak(),nocbreak()
    
         □ nl()
    nonl()
              用來決定當(dāng)輸入資料時(shí), 按下 RETURN 鍵是否被對(duì)應(yīng)為 NEWLINE 字
    元 ( 如 \n ).
    而輸出資料時(shí), NEWLINE  字元是否被對(duì)應(yīng)為  RETURN 和 LINDFEED
    系統(tǒng)預(yù)設(shè)是開啟的.
    
         □ echo()
    noecho()
              此函式用來控制從鍵盤輸入字元時(shí)是否將字元顯示在終端機(jī)上.系統(tǒng)
    預(yù)設(shè)是開啟的.
    
         □ intrflush(win,bf)
              呼叫 intrflush 時(shí)須傳入兩個(gè)值:
    win 為一 WINDOW 型態(tài)指標(biāo), 通常傳入標(biāo)準(zhǔn)輸出入螢?zāi)?stdscr
    bf 為 TRUE 或 FALSE
              當(dāng) bf 為 true 時(shí), 當(dāng)輸入中斷字元 ( 如 break) 時(shí), 中斷的反應(yīng)
    將較為快速.但可能會(huì)造成螢?zāi)坏腻e(cuò)亂.
    
          □ keypad(win,bf)
              呼叫 keypad 時(shí)須傳入兩個(gè)值:
    win 為一 WINDOW 型態(tài)指標(biāo), 通常傳入標(biāo)準(zhǔn)輸出入螢?zāi)?stdscr
    bf 為 TRUE 或 FALSE
              當(dāng)開啟  keypad 後, 可以使用鍵盤上的一些特殊字元, 如上下左右
    等方向鍵, curses 會(huì)將這些特殊字元轉(zhuǎn)換成 curses.h 內(nèi)定義的一
    些特殊鍵. 這些定義的特殊鍵通常以 KEY_ 開頭.
    
          □ refresh()
              refresh() 為 curses 最常呼叫的一個(gè)函式.
              curses 為了使螢?zāi)惠敵鋈脒_(dá)最佳化, 當(dāng)您呼叫螢?zāi)惠敵龊狡髨D改
    變螢?zāi)簧系漠嬅鏁r(shí), curses  并不會(huì)立刻對(duì)螢?zāi)蛔龈淖?  而是等到
    refresh() 呼叫後, 才將剛才所做的變動(dòng)一次完成.  其馀的資料將
    維持不變. 以盡可能送最少的字元至螢?zāi)簧? 減少螢?zāi)恢乩L的時(shí)間.
    如果是 initscr() 後第一次呼叫  refresh(), curses 將做清除螢
    幕的工作.
    
     ■ 游標(biāo)的控制
           move(y,x)       將游標(biāo)移動(dòng)至 x,y 的位置
    getyx(win,y,x)  得到目前游標(biāo)的位置
    (請(qǐng)注意! 是 y,x 而不是 &y,&x )
    
     ■ 有關(guān)清除螢?zāi)坏暮?/pre>
    
               clear()
    erase()   將整個(gè)螢?zāi)磺宄?
    (請(qǐng)注意配合refresh() 使用)
    
     ■ 如何在螢?zāi)簧巷@示字元
         echochar(ch)              顯示某個(gè)字元
         addch(ch)                 顯示某個(gè)字元
    mvaddch(y,x,ch)           在(x,y) 上顯示某個(gè)字元
    相當(dāng)於呼叫 move(y,x);addch(ch);
         addstr(str)               顯示一串字串
    mvaddstr(y,x,str)         在(x,y) 上顯示一串字串
    相當(dāng)於呼叫 move(y,x);addstr(str);
         printw(format,str)        類似 printf() , 以一定的格式輸出至螢?zāi)?
    mvprintw(y,x,format,str)  在(x,y) 位置上做 printw 的工作.
    相當(dāng)於呼叫 move(y,x);printw(format,str);
    
     ■ 如何從鍵盤上讀取字元
          getch()                        從鍵盤讀取一個(gè)字元 (注意! 傳回的是整數(shù)值)
    getstr()                       從鍵盤讀取一串字元
    scanw(format,&arg1,&arg2...)   如同 scanf, 從鍵盤讀取一串字元
          □例:
          int ch;
    char string1[80];   /* 請(qǐng)注意! 不可宣告為 char *string1; */
    char string2[80];
          echo();            /* 開啟 echo 模式, 使輸入立刻顯示在螢?zāi)簧?*/
    ch=getch();
    string1=getstr();
    scanw("%s",string2);
    mvprintw(10,10,"String1=%s",string1);
    mvprintw(11,10,"String2=%s",string2);
     ■ 如何利用方向鍵
        curses 將一些如方向鍵等特殊控制字元, 以 KEY_ 為開頭定義在 curses.h
    這個(gè)檔案里頭, 如 KEY_UP  即代表方向鍵的  " ↑ ".  但, 如果您想使用
    curses.h  所為您定義的這些特殊鍵的話,  您就必須將   keypad  設(shè)定為
    TRUE. 否則, 您就必須自己為所有的特殊鍵定義了.
       curses.h 為一些特殊鍵的定義如下:
         KEY_UP          0403           ↑
    KEY_DOWN        0402           ↓
    KEY_LEFT        0404           ←
    KEY_RIGHT       0405           →
    KEY_HOME        0406           Home key (upward+left arrow)
    KEY_BACKSPACE   0407           backspace (unreliable)
    KEY_F0          0410           Function keys.
    KEY_F(n)        (KEY_F0+(n))   Formula for f .
    KEY_NPAGE       0522           Next page
    KEY_PPAGE       0523           Previous page
        以上僅列出筆者較常使用的一些控制鍵, 至於其他控制鍵的定義, 請(qǐng)自行參
    閱 man curses (* 注三)
        一并為您列出其他常用的一些特殊字元
         [TAB]                 /t
    [ENTER]               /r
    [ESC]                 27
    [BACKSPACE]           127
    
      ■ 如何改變螢?zāi)伙@示字元的屬性
        為了使輸出的螢?zāi)划嬅娓鼮樯鷦?dòng)美麗,  我們常須要在螢?zāi)簧献鲆恍┤绶窗?
    閃爍等變化.  curses 定義了一些特殊的屬性, 透過這些定義, 我們也可以
    在 curses 程式□控制螢?zāi)坏妮敵鲎兓?
         attron(mod)    開啟屬性
    attroff(mod)   關(guān)閉屬性
        curses.h 里頭定義了一些屬性, 如:
         A_UNDERLINE    加底線
    A_REVERSE      反白
    A_BLINK        閃爍
    A_BOLD         高亮度
    A_NORMAL       標(biāo)準(zhǔn)模式 (只能配合 attrset() 使用)
    
        當(dāng)使用 attron() 開啟某一種特殊屬性模式後, 接下來在螢?zāi)坏妮敵龆紩?huì)以
    該種屬性出現(xiàn). 直到您呼叫 attroff() 將此模式關(guān)閉.
        請(qǐng)注意, 當(dāng)您欲 attron() 開啟另一種屬性時(shí), 請(qǐng)記得利用 attroff()先關(guān)
    閉原來的屬性, 或直接以 attrset(A_NORMAL)  將所有特殊屬性關(guān)閉.否則,
    curses 會(huì)將兩種屬性做重疊處理.
         □例:
            attrset(A_NORMAL);            /* 先將屬性設(shè)定為正常模式       */
    attron(A_UNDERLINE);          /* 加底線                       */
    mvaddstr(9,10,"加底線");      /* 加底線輸出一串字元           */
    attroff(A_UNDERLINE);         /* 關(guān)閉加底線模式, 恢復(fù)正常模式 */
    attron(A_REVERSE);            /* 開啟反白模式                 */
    mvaddstr(10,10,"反白");       /* 輸出一串反白字元             */
    attroff(A_REVERSE);           /* 關(guān)閉反白模式, 恢復(fù)正常模式   */
    attron(A_BLINK);              /* 開啟閃爍模式                 */
    mvaddstr(11,10,"閃爍");       /* 輸出一串閃爍字元             */
    attroff(A_BLINK);             /* 關(guān)閉閃爍模式, 恢復(fù)正常模式   */
    attron(A_BOLD);               /* 開啟高亮度模式               */
    mvaddstr(12,10,"高亮度");     /* 輸出一串高亮度字元           */
    attroff(A_BOLD);              /* 關(guān)閉高亮度模式, 恢復(fù)正常模式 */
    
      ■ 其他常用的一些函式
           beep()              發(fā)出一聲嗶聲
    box(win,ch1,ch2)    自動(dòng)畫方框  ch1: 畫方框時(shí)垂直方向所用字元
    ch2: 畫方框時(shí)水平方向所用字元
                                           example: box(stdscr,'|','-');
    將以 | 及 - 圍成一個(gè)方框
      ■ 應(yīng)用完整□例
        下面所舉的例子,  即完全利用剛剛所介紹的含式來完成.這個(gè)程式可將從鍵
    盤上讀取的字元顯示在螢?zāi)簧? 并且可以上下左右方向鍵來控制游標(biāo)的位置
    , 當(dāng)按下 [ESC] 後, 程式即結(jié)束.
        您有沒有發(fā)現(xiàn), 這不就是一個(gè)簡單全螢?zāi)痪庉嬈鞯碾r形嗎?
    
       #include <curses.h>                  /* 引進(jìn) curses.h , 并自動(dòng)引進(jìn) stdio.h */
    
       #define StartX  1                    /* 決定游標(biāo)初始位置 */
    #define StartY  1
       void initial();
       main()
    {
    int x=StartX;                     /* 宣告 x,y 并設(shè)定其初值              */
          int y=StartY;
    int ch;                           /* 宣告 ch 為整數(shù),配合 getch() 使用   */
    
          initial();                        /* 呼叫 initial(), 啟動(dòng) curses 模式,  */
                                            /* 并完成其它設(shè)定                     */
    
          box(stdscr,'|','-');              /* 畫方框                             */
    
          attron(A_REVERSE);                /* 開啟反白模式                       */
          mvaddstr(0,20,"Curses Program");  /* 在 (20,0) 處輸出反白字元           */
          attroff(A_REVERSE);               /* 關(guān)閉反白模式                       */
    
          move(x,y);                        /* 將游標(biāo)移至初始位置                 */
    
          do {                              /* 以無限回圈不斷等待輸入             */
           ch=getch();                      /* 等待自鍵盤輸入字元
    switch(ch) {                     /* 判斷輸入字元為何                   */
    
              case KEY_UP: --y;             /* 判斷是否"↑"鍵被按下               */
                           break;
    case KEY_DOWN: ++y;           /* 判斷是否"↓"鍵被按下               */
                           break;
    case KEY_RIGHT: ++x;          /* 判斷是否"→"鍵被按下               */
                           break;
    case KEY_LEFT: --x;           /* 判斷是否"←"鍵被按下               */
                           break;
    case '\r':                    /* 判斷是否 ENTER 鍵被按下            */
                        ++y;
    x=0;
    break;
    case '\t':                    /* 判斷是否 TAB 鍵被按下              */
                        x+=7;
    break;
    case 127:                     /* 判斷是否 BACKSPACE 鍵被按下        */
                         mvaddch(y,--x,' ');/* delete 一個(gè)字元                    */
                         break;
              case 27: endwin();            /* 判斷是否[ESC]鍵被按下              */
                       exit(1);             /* 結(jié)束 curses 模式                   */
                                            /* 結(jié)束此程式                         */
    
              default:
    addch(ch);           /* 如果不是特殊字元, 將此字元印出     */
                       x++;
    break;
    }
    move(y,x);                      /* 移動(dòng)游標(biāo)至現(xiàn)在位置                 */
          } while (1);
    }
       void initial()                       /* 自定開啟 curses 函式               */
       {
    initscr();
    cbreak();
    nonl();
    noecho();
    intrflush(stdscr,FALSE);
    keypad(stdscr,TRUE);
    refresh();
    }
    
      ■ 後記
        學(xué)完了上述的一些命令,  相不相信您已經(jīng)可以寫出一個(gè)漂亮的全螢?zāi)痪庉?
    器了? 事實(shí)上, curses 提供的函式不下  200 個(gè), 可是筆者認(rèn)為, 一切再
    復(fù)雜的函式都可以用本文提到的一些組合變化而成,  學(xué)了太多的函式, 只
    是徒增自己困擾罷了.  當(dāng)然,  如果您對(duì)其它函式有興趣,  可以自行參閱
    curses 說明檔.  ( 方法: % man curses ) 本文不過行拋磚引玉之效, 也
    希望未來能陸續(xù)出現(xiàn)更多同學(xué)自行創(chuàng)作的程式.
         * 任何疑問及建議, 歡迎 e-mail 至 ljh@CCCA.NCTU.edu.tw. 謝謝 ! *
    
     注一:
    請(qǐng)參考 /usr/share/lib/termcup
    /usr/share/lib/terminfo/s/sun
     注二:
    1.如果是 BSD 的版本, 需使用
    cc [file.c] -lcurses -ltermcap 來完成 compile.
    2.計(jì)中工作站不知何故將原來的 /usr/5bin/cc 更改為 /usr/5bin/cc.org
    因此, 您若想在計(jì)中工作站 compile curses 程式.需以 /usr/5bin/cc.org
    取代 /usr/5bin/cc , 否則 compile 可能發(fā)生錯(cuò)誤.
    3.較舊版的 curses 需同時(shí)引進(jìn) curses 和 termlib 這兩個(gè) library,
    因此, 您必須使用 /usr/5bin/cc [file.c] -lcurses -ltermlib 來 compile.
     注三:
    根據(jù)筆者的經(jīng)驗(yàn), 上下左右方向鍵應(yīng)可正常使用而不會(huì)發(fā)生問題, 但其它
    如 PgUp,PgDn,功能鍵,Home,End 等特殊鍵, 很容易因機(jī)器, 鍵盤不同而無
    法使用, 因此, 若您的程式須要在不同的機(jī)器上使用, 建議您只用方向鍵來
    控制, 其它的特殊鍵少用為妙.
    至於 PgUp,PgDn 一些特殊鍵的控制方法, 由於較為復(fù)雜, 有興趣的同學(xué)可參
    考 tin 原始程式 curses.c 內(nèi)所使用的一些方法.
    
                     UNIX 螢?zāi)粚?dǎo)向程式的發(fā)展利器 - curses (二)
    
                                                              校園網(wǎng)路策進(jìn)會(huì)
    會(huì)長    林建宏
    
          在上期為您介紹完了 curses.h 函式庫的一些基本函式呼叫後在, 在本期里
    , 我們將繼續(xù)為您介紹 curses 有關(guān)多視窗處理的函式. 有了這些函式, 我們
    可以在程式里同時(shí)處理多個(gè)不同的視窗.  如 joe 編輯器內(nèi)我們可將螢?zāi)磺懈?
    成好幾個(gè)小螢?zāi)? 并且可以在這些不同的螢?zāi)婚g做切換并編輯不同的檔案, 這
    就是多視處理的應(yīng)用. 另外, 有關(guān) POP-UP 視窗的制作, 以及視窗的卷動(dòng), 在
    本文里, 我們將以簡單的例子, 告訴您這些功能是如何做到的. 關(guān)於一些較基
    本函式的用法, 我們將不再特別介紹. 如果您尚未熟悉 curses 基本函式使用
    方法, 請(qǐng)參閱上一期 (80 期 ) 通訊.
    
      ■ 視窗的建立
        視窗的建立, 以 newwin() 這個(gè)函式來完成.  同時(shí), 需宣告此視窗為 WINDOW
    結(jié)構(gòu)變數(shù).
        WINDOW *newwin(lines,colums,start_y,start_x);
    
         WINDOW *win;
    win=newwin(10,20,0,0);
        如此, 將以 (0,0) 為原點(diǎn), 取一個(gè) 10 列 20 行的矩形為一新的視窗.  今後
    我們只要呼叫 win 這個(gè)變數(shù), 就可以對(duì)這新視窗做處理.
         如: wmove(win,3,2);
    
      ■ 多視窗處理函式的格式
        這一類函式和一般的基本函式極為類似, 幾乎每一個(gè)基本函式都有一個(gè)對(duì)應(yīng)的
    視窗處理函式.  一般將 'w' 加在函式的里頭作為區(qū)別, 'w' 乃 'window' 之
    意. 另外, 因?yàn)榭赏瑫r(shí)處理多個(gè)視窗, 在呼叫使用時(shí), 需特別指定欲處理的視
    窗. 當(dāng)然, 如果您指定對(duì) stdscr 做處理, 由於是對(duì)標(biāo)準(zhǔn)輸出入螢?zāi)惶幚? 其
    作用將相當(dāng)於一般基本的函式.
         如:
          wmove(win,y,x)     即對(duì) win 這個(gè)視窗做 move() 動(dòng)作.
    wmove(stdscr,y,x)  相當(dāng)於 move(y,x)
        介紹一些較重要的函式
        wmove(win,y,x)
    touchwin(win)
    wrefresh(win)
    mvwaddstr(win,y,x,str)
    wattron(attr)
    delwin(win)
    subwin(win,ny,nx,y,x)
        其他函式多和基本函式互為對(duì)應(yīng), 故不全部列出, 詳細(xì)名稱可參考 curses
    的 online manual.
      ■ 視窗內(nèi)的座標(biāo)系
        視窗內(nèi)的座標(biāo)系, 將以此視窗的起始點(diǎn)為新原點(diǎn), 并以其相對(duì)位置作為新的
    座標(biāo). 舉例來說
        win=newwin(10,20,5,5);
    wmove(win,2,3);
        將以 (5,5) 為新原點(diǎn),  y 方向移動(dòng) 2 單位, x 方向移動(dòng) 3 單位. 因此實(shí)際
    上, 游標(biāo)將移動(dòng)至 y=7 x=8 的位置上.
    
      ■ POP-UP 視窗的建立
        利用 curses 所提供的視窗處理函式, 我們可以做出像  ONLINE HELP 的 POP
    -UP 畫面. 當(dāng)按下某鍵後, 一個(gè)新的視窗將像 " 跳 " 出來一般覆蓋原來的畫
    面. 當(dāng)關(guān)掉此視窗後, 又不會(huì)影響到原來被覆蓋的畫面.
    
        下面的例子, 我們及模擬 ONLINE HELP 的形式, 當(dāng)按下 'h' 鍵時(shí), 視窗即出現(xiàn)
    
       #include <curses.h>
       main()
    {
    int ch,x,y;
    WINDOW *win;
         initscr();   ←┐
    cbreak;        │ 啟動(dòng) curses 模式
    noecho();      │
    nonl();      ←┘
         win=newwin(4,30,LINES/2-3, COLS/2-15);/* 建立一個(gè)新視窗, 其中LINES,COLS
    */
    box(win,'|','-');                     /* 為 curses 內(nèi)定值,
    即螢?zāi)恍?列數(shù)*/
    mvwaddstr(win,1,4,"This is another screen");
    mvwaddstr(win,2,2,"Press anykey to continue..");
         for (y=0;y<LINES;++y)     /* 以'@'填滿螢?zāi)?*/
    for (x=0;x<COLS;++x)
    mvprintw(y,x,"@");
          for(;;) {
    refresh();
    ch=getch();
    switch(ch) {
    case 'q':                /* 按 'q' 鍵離開 */
    endwin();
    exit(0);
             case '\t':              /* 按 [TAB] 鍵 呼叫另一視窗   */
    touchwin(win);        /* wrefresh() 前需 touchwin() */
    wrefresh(win);
    getch();              /* 按任意鍵關(guān)閉視窗 */
    touchwin(stdscr);
    break;
             default:break;
    }
    }
    }
    
       執(zhí)行結(jié)果:
          ┌————————————————————————————┐
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    └————————————————————————————┘
    ↑ 原來畫面被 '@' 填滿, 按下[TAB]鍵後
    ↓ 出現(xiàn) POP-UP 畫面.
    ┌————————————————————————————┐
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@□---------------------------+@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@|   This is another screen   |@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@| Press anykey to continue.. |@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@□---------------------------+@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    │ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ │
    └————————————————————————————┘
    
      ■ 視窗的卷動(dòng)
        視窗的卷動(dòng), 掖Q用來配合視窗的處理, 當(dāng)我們持續(xù)對(duì)視窗輸出直到視窗的游
    標(biāo)移動(dòng)至最後一列時(shí), 如果我們?cè)佥敵鲆涣谢蚴禽敵鲆粋€(gè)換行字元時(shí), 視窗可
    整個(gè)往上卷動(dòng)一行. 這對(duì)我們撰寫一個(gè)編輯程式時(shí), 是尤其重要的, 一個(gè)畫面
    無法卷動(dòng)的編輯器, 勢必?zé)o法處理超過一個(gè)螢?zāi)淮笮〉臋n案.
        視窗的卷動(dòng)是預(yù)設(shè)為關(guān)閉的, 并以 scrollok() 來控制開閉.
        scrollok(win,TRUE);    開啟
    scrollok(win,FALSE);   關(guān)閉
    
        下面的例子因?yàn)椴粩嗟剌敵?0,1,2.. 故將以一個(gè) 40 * 10 的視窗不停的卷動(dòng)
          #include <curses.h>
          main()
    {
    int i;
    WINDOW *scrwin,*boxwin;
             initscr();     ←┐
    cbreak;          │ 啟動(dòng) curses 模式
    noecho();        │
    nonl();        ←┘
             scrwin=newwin(10,40,LINES/2-6,COLS/2-25); /* 設(shè)定另一視窗大小 */
    boxwin=newwin(12,42,LINES/2-7,COLS/2-26); /* 設(shè)定外框視窗大小 */
             scrollok(scrwin,TRUE);  /* 開啟視窗卷動(dòng)功能 */
             box(boxwin,'|','-');
    refresh();
    wrefresh(boxwin);
             for (i=0;;++i)         /* 不斷地在視窗內(nèi)輸出 0-8 的數(shù)字,使視窗卷動(dòng)
    */
    {
    wprintw(scrwin,"%d",i%9);
    wrefresh(scrwin);
    }
    }
    
          執(zhí)行結(jié)果:
    ┌——————————————————————┐
    │         □---------------------□          │
    │         |3456780123456780123412| ↑ 視     │
    │         |3456780123456780123456| │ 窗     │
    │         |7801234567801234567801| │ 不     │
    │         |2345678012345678012345| │ 停     │
    │         |6780123456780123456780| │ 往     │
    │         |1234567801234567801234| │ 上     │
    │         |5678012345678012345678| │ 卷     │
    │         |0123456780123456780123| │ 動(dòng)     │
    │         □---------------------□          │
    │                                            │
    └——————————————————————┘
    
      ■ □例 - 模擬 joe 分割畫面同時(shí)編輯兩個(gè)檔案
         在下面的例子里, 我們應(yīng)用了多視窗處理的函式, 改良上回介紹的編輯器,
    在這個(gè)程式里, 我們可以同時(shí)編輯兩個(gè)畫面, 并以 [ESC] 做不同視窗間的
    切換. 同時(shí), 按下 [TAB] 鍵, 會(huì)出現(xiàn) POP-UP 的 ONLINE HELP.
    
       #include <curses.h>
       void initial();
       main()
    {
    WINDOW *win[2],*curwin,*helpwin;
    int nowwin;
    int x,y;
    int i;
    int ch;
         initial();
         win[0]=newwin(LINES/2-1,COLS-1,0,0);       /* 設(shè)定兩個(gè)視窗的大小*/
    win[1]=newwin(LINES/2-1,COLS-1,LINES/2,0);
         helpwin=newwin(3,30,2,COLS/2-15 );        /* ONLINE HELP 的大小 */
    box(helpwin,'|','-');
    mvwaddstr(helpwin,0,10,"ONLINE HELP");    /* ONLINE HELP 的內(nèi)容 */
    mvwaddstr(helpwin,1,4,"Hit any key to continue..");
         for (i=0;i<COLS-1;++i)              /* 畫兩個(gè)視窗間的界限 */
    mvaddch(LINES/2-1,i,'-');
         nowwin=0;                          /* 先指定游標(biāo)在第一視窗 */
    curwin=win[nowwin];
    getyx(curwin,y,x);
    move(0,0);
    refresh();
         refresh();
         do {
    ch=getch();
    switch(ch) {
                 case KEY_UP: --y;             /* 判斷是否"↑"鍵被按下       */
    break;
    case KEY_DOWN: ++y;           /* 判斷是否"↓"鍵被按下       */
    break;
    case KEY_RIGHT: ++x;          /* 判斷是否"→"鍵被按下       */
    break;
    case KEY_LEFT: --x;           /* 判斷是否"←"鍵被按下       */
    break;
    case '\r':                    /* 判斷是否 ENTER 鍵被按下    */
    ++y;
    x=0;
    break;
    case '\t':                    /* 判斷是否 TAB 鍵被按下      */
    touchwin(helpwin);
    wrefresh(helpwin); /* 呼叫 ONLINE HELP */
    getch();
    touchwin(win[1-nowwin]);  /* 重畫第一,二視窗 */
    wrefresh(win[1-nowwin]);
    touchwin(curwin);
    wrefresh(curwin);
    break;
    case 127:                     /* 判斷是否 BACKSPACE 鍵被按下 */
    wmove(curwin,y,--x);/* delete 一個(gè)字元            */
    waddch(curwin,' ');
    break;
                case 27 : nowwin=1-nowwin;      /* [ESC] 鍵切換視窗 */
    curwin=win[nowwin];
    getyx(curwin,y,x);
    break;
    default:
    waddch(curwin,ch);
    x++;
    break;
    }
    wmove(curwin,y,x);
    wrefresh(curwin);
    } while(1);
    }
    
       void initial()
    {
    initscr();                  ←┐
    cbreak();                     │ 啟動(dòng) curses 模式
    nonl();                       │
    noecho();                   ←┘
    intrflush(stdscr,FALSE);
    keypad(stdscr,TRUE);
    refresh();
    }
    
        執(zhí)行結(jié)果:
               ┌—————————————————————————————┐
    │    screen1                                               │
    ┌→  │         this is screen 1, you can press [ESC] to         │
    以 │    │     switch between screen 1 and screen 2.                │
    [ESC]│    │                                                          │
    切 │    │                                                          │
    換 │    │----------------------------------------------------------│
    游 │    │     screen 2                                             │
    標(biāo) │    │                                                          │
    位 └→  │        _ (游標(biāo))                                          │
    置       │                                                          │
    └—————————————————————————————┘
    ↑ 按下[TAB] 鍵,出現(xiàn) ONLINE HELP
    ↓
    ┌—————————————————————————————┐
    │    screen1                                               │
    │         this is screen 1, you can press [ESC] to         │
    │     switch□--------ONLINE HELP--------□                │
    │           |   Hit any key to continue..|                 │
    │           □---------------------------□                │
    │----------------------------------------------------------│
    │     screen 2                                             │
    │                                                          │
    │                                                          │
    │                                                          │
    └—————————————————————————————┘
    ↑ 按任意鍵, ONLINE HELP 關(guān)閉
    ↓
    ┌—————————————————————————————┐
    │    screen1                                               │
    │         this is screen 1, you can press [ESC] to         │
    │     switch between screen 1 and screen 2.                │
    │                                                          │
    │                                                          │
    │----------------------------------------------------------│
    │     screen 2                                             │
    │                                                          │
    │        _ (游標(biāo))                                          │
    │                                                          │
    └—————————————————————————————┘
    
     ■ 結(jié)語
        我們以連續(xù)兩期來介紹 curses.h 函式庫的使用方法, 相信同學(xué)對(duì)撰寫這類的
    程式應(yīng)該不再陌生. 所謂『戲法人人會(huì)變, 巧妙各有不同』. 知道了基本函式
    的呼叫方法, 能不能寫出實(shí)用的程式, 就靠各位的巧思和創(chuàng)造力了.
    
        有任何問題建議, 歡迎 E-mail 至  ljh@CCCA.NCTU.edu.tw , 謝謝 !
    
    發(fā)信人: Cardinal.bbs@mic.ee.ntu.edu.tw (Cardinal), 信區(qū): unix
    標(biāo)  題: Re: 請(qǐng)問誰會(huì)用 curses 顯示 ANSI color 字
    發(fā)信站: 臺(tái)大電機(jī) Maxwell 站
    首先聲明,這一封的內(nèi)容應(yīng)該屬於 programming board,但是現(xiàn)在有不止一個(gè)
    人問我這個(gè)問題,所以在這個(gè)版再把詳細(xì)的方法說明一遍。如果有人看不懂而
    仍然有興趣的,請(qǐng) mail 給我 (Cardinal.bbs@mic.ee.ntu.edu.tw) ,不要在
    這邊 reply,我會(huì)考慮在私下或在 programming board解決你的問題。
    ==> 在 Cardinal@Maxwell (Cardinal) 的文章中提到:
    :   1.開一個(gè) new window (newwin)
    :   2.設(shè)定 window 的彩色屬性 (wattrset)
    ==> 在設(shè)定彩色屬性之前應(yīng)該先設(shè)定顏色的 "pair" ,所謂的 "pair" 是指
    foreground及background的顏色。curses的顏色有下面幾種 (type為
    short) :
    COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
    COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
        用init_pair(short pair, short f_color, short b_color)來設(shè)定 pair,
    for example:
    init_pair(100, COLOR_RED, COLOR_BLUE)
    就設(shè)定了編號(hào)為 100, 藍(lán)底紅字的 color pair 了.
        另外你要是嫌這幾種顏色太單調(diào)了, 可以用 init_color 來設(shè)定色彩, 細(xì)節(jié)
    這邊就不談了.
        然後就用 wattrset(WINDOW* pwindow, short color_pair)設(shè)定你window的
    顏色, for example:
    wattrset(pwindow, 100) 就設(shè)定了一個(gè)藍(lán)底紅字的 window (不要忘記
    這兒的 100 是剛剛用 init_pair設(shè)定的值)
    :   3.印在 window 的字就自動(dòng)變成那個(gè)顏色了 (mvwprintw, mvwaddstr, ...)
    ==> 這句... 該不會(huì)有問題吧.
    :   4.想要印不同顏色的字,只要把那個(gè)字 "OR" (|) 不同的顏色即可 (記住,
    :     這種有屬性的字要用 int,不能用 char)
    ==> 其實(shí)型別不是用 int, 而是用 chtype (不過沒有差別, 去查查 curses.h就
    知道) , 譬如說, 你想要在剛剛設(shè)定為藍(lán)底紅字的 window印一個(gè)別的顏色的
    'A' 字, 可以這麼做 :
        init_pair(another_color_pair, COLOR_隨便, COLOR_隨便) -->先設(shè)定另一
    個(gè) color pair
    char   cascii = 'A';
    chtype cascii_color = cascii | another_color_pair;
        再把 cascii_color 印出來就是一個(gè)你想要顏色的 A 了.
    --
    ~  Cardinal  ~
    From:      Cardinal (Cardinal)
    Title:     關(guān)於精華區(qū)...
    Date:      Fri Mar 10 20:36:27 1995
    
    您好:
    在 programming 版精華區(qū) unix - curses libraries 中有一篇文章是我寫的,
    剛剛來這邊找資料時(shí)翻到的, 真是受寵若驚. 不過原來的文章 (如何用 curses
    顯示彩色) 有一點(diǎn)忘了提到, 希望您能把下面的說明加進(jìn)去:
      1.  init_color及init_pair 是 SystemVR3以後的標(biāo)準(zhǔn), 不適用於 BSD 或
    SunOS.
    2.  在 SunOS 上要達(dá)成這樣的目的, 我知道的有兩種解法
    a.有一款大同的中文工作站有支援 init_color & init_pair 的 library
    這一型的 library 與 SunOS 為 object-code compatible.
    b.ncurses 支援 init_pair & init_color
    
    posted on 2007-07-20 14:03 jinfeng_wang 閱讀(432) 評(píng)論(0)  編輯  收藏 所屬分類: ZZLinux
    主站蜘蛛池模板: 久久精品国产亚洲AV电影网| 亚洲无线码一区二区三区| 91频在线观看免费大全| 无码av免费一区二区三区试看| 国产免费无码一区二区| 久久精品视频免费播放| 亚洲日本在线免费观看| 4hu四虎最新免费地址| 真人做A免费观看| 国产精品成人免费视频网站京东 | 国产成人精品日本亚洲专| 亚洲一级黄色大片| 亚洲国产精品一区二区三区在线观看| 日本亚洲色大成网站www久久 | 亚洲国色天香视频| 国产成+人+综合+亚洲专| 亚洲一区二区三区丝袜| 亚洲av无码成人影院一区| 国产成人亚洲精品播放器下载| 阿v视频免费在线观看| 一本久久A久久免费精品不卡| 中国一级特黄的片子免费| 日韩成人免费视频| 无码精品A∨在线观看免费| 性感美女视频免费网站午夜 | 成人av免费电影| 一本色道久久88亚洲综合 | 国产一区二区视频免费| 久久久久亚洲精品中文字幕| 国产亚洲色婷婷久久99精品| 久久久久久亚洲Av无码精品专口| avtt天堂网手机版亚洲| 男男gay做爽爽的视频免费| 久久成人18免费网站| 18pao国产成视频永久免费| 女人被男人躁的女爽免费视频| 亚洲无码日韩精品第一页| 亚洲国产精品久久久久婷婷老年| 天天爽亚洲中文字幕| 免费在线观看一区| 性色午夜视频免费男人的天堂 |