📄 unix 屏幕导向程序的发展利器1.htm
字号:
<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title>UNIX 屏幕导向程序的发展利器</title></head><body bgcolor="black" text="white" link="#0066ff" vlink="#9999ff" alink="red"><div align=center> </div><div align=right>Copyleft by <a href="mailto:rezaie@softhome.net">Wilbur Lang</a>. If you have any <br>question, please read <a href="javascript:if(confirm('http://personal.xfol.com/~rezaie/api/licensing.html \n\nThis file was not retrieved by Teleport Pro, because the server reports that this file cannot be found. \n\nDo you want to open it from the server?'))window.location='http://personal.xfol.com/%7Erezaie/api/licensing.html'" tppabs="http://personal.xfol.com/%7Erezaie/api/licensing.html">licenses</a>.</div><!-- ================================================================== --><!-- --><!-- Main Body --><!-- --> <p align="center"><font color="#9879c6"><big><big>UNIX 屏幕导向程序的发展利器 - curses (之一)</big></big></font></p> <p align="right">作者:林建宏</p><pre> ■ 前言 相信您在网络上一定用过如 tin,elm 等工具, 这些软体有项共同的特色, 即他们能利用上下左右等方向键来控制光标的位置. 除此之外, 这些程序 的画面也较为美观. 对 Programming 有兴趣的朋友一定对此感到好奇, 也 许他能在 PC 上用 Turbo C 轻易地写出类似的程序, 然而, 但当他将相同 的程序一字不变地移到工作站上来编译时, 却出现一堆抓也抓不完的错误. 其实, 原因很简单, 他使用的函数库可能在 UNIX 上是没有定义的. 有些 在 Turbo-C 上被广泛使用的一些函数, 可能在 UNIX 上是不被定义的. 为了因应网络上各式各样的终端类型 (terminal), UNIX 上特别发展出 一套函数库, 专门用来处理 UNIX 上光标移动及屏幕的显示. 这就是本篇 文章要为您介绍的 - curses.h 函数库. 利用这个函数库, 您也可以写出 像 elm 般利用方向键来移动光棒位置的程序. (CCCA 近来所提供的线上选 课程序, 及程序服务界面, 即是笔者利用 curses 发展而成的 ) ■ curses 的历史与版本 cureses 最早是由柏克莱大学的 Bill Joy 及 Ken Arnold 所发展出来的. 当时发展此一函数库主要原因是为了提高程序对不同终端的相容性而设 计的. 因此, 利用 curses 发展出来的程序将和您所使用的终端无关. 也就是说, 您不必担心您的程序因为换了一部终端而无法使用. 这对程 序设计者而言, 尤其是网络上程序的撰写, 是件相当重要的一件事. curses之所以能对上百种以上的终端工作, 是因为它将所有终端的资 料, 存放在一个叫 termcap 的资料库, ( 而在第二版的 System V 系统中 , 新版的 curses 以 terminfo 取代原来的 termcap). 有了这些记录, 程 式就能够知道遇到哪一种终端时, 须送什麽字元才能移动光标的位置, 送什麽字元才能清除整个屏幕清除. (* 注一) 另外, 本文的介绍 以 System V 的 curses 版本为主. ■ 如何在您的程序使用 curses ? 在您的 C 程序的档头将 <curses.h> include 进来.当您引进 curses.h 这个函数库後, 系统会自动将 <stdio.h> 和 <unctl.h>一并 include 进 来.另外, 在 System V 版本中, <terminfo.h> 这个函数库也将一并 include进来. #include <curses.h> main() { : : : : } 当然, 您的系统内必须放有 curses.h 这个函数库. ■ 如何编译(compile) 当您编辑好您的程序, 在 UNIX 提示符号下键入: % /usr/5bin/cc [file.c] -lcurses ^^^^^^^ 引进 curses.h 这个 library 或 % /usr/5bin/cc [file.c] -lcurses -ltermlib (*注二) ■ 如何开始我的第一个 curses 程序? 在开始使用 curses 的一切命令之前, 您必须先利用 initscr()这个函数 来开启 curses 模式. 相对的, 在结束 curses 模式前 ( 通常在您结束程序前 ) 也必须以 endwin()来关闭 curses 模式. #include <curses.h> main() { initscr(); : : : : : : endwin(); } 这是一般 curses 程序标准的模式. 此外, 您可以就您程序所须, 而做不同的设定. 当然, 您可以不做设定,而 只是呼叫 initscr(). 您可以自己写一个函数来存放所有您所须要的设定. 平常使用时, 只要呼 叫这个函数即可启动 curses 并完成一切设定. 下面的例子, 即是笔者将平常较常用的一些设定放在一个叫 initial()的函 式内. void initial() { initscr(); cbreak(); nonl(); noecho(); intrflush(stdscr,FALSE); keypad(stdscr,TRUE); refresh(); } 各函数分别介绍如下: □ initscr() initscr() 是一般 curses 程序必须先呼叫的函数, 一但这个函数 被呼叫之後, 系统将根据终端的形态并启动 curses 模式. □ endwin() curses 通常以呼叫 endwin() 来结束程序. endwin() 可用来关闭 curses 模式, 或是暂时的跳离 curses 模式.如果您在程序中须要 call shell ( 如呼叫 system() 函数 ) 或是需要做 system call, 就必须先以 endwin() 暂时跳离 curses 模式. 最後再以 wrefresh() doupdate() 来重返 curses 模式. □ cbreak() nocbreak() 当 cbreak 模式被开启後, 除了 DELETE 或 CTRL 等仍被视为特殊 控制字元外一切输入的字元将立刻被一一读取.当处於 nocbreak 模 式时, 从键盘输入的字元将被储存在 buffer 里直到输入 RETURN 或 NEWLINE.在较旧版的 curses 须呼叫 crmode(),nocrmode() 来 取代 cbreak(),nocbreak() □ nl() nonl() 用来决定当输入资料时, 按下 RETURN 键是否被对应为 NEWLINE 字 元 ( 如 \n ). 而输出资料时, NEWLINE 字元是否被对应为 RETURN 和 LINDFEED 系统预设是开启的. □ echo() noecho() 此函数用来控制从键盘输入字元时是否将字元显示在终端上.系统 预设是开启的. □ intrflush(win,bf) 呼叫 intrflush 时须传入两个值: win 为一 WINDOW 型态指标, 通常传入标准输出入屏幕 stdscr bf 为 TRUE 或 FALSE 当 bf 为 true 时, 当输入中断字元 ( 如 break) 时, 中断的反应 将较为快速.但可能会造成屏幕的错乱. □ keypad(win,bf) 呼叫 keypad 时须传入两个值: win 为一 WINDOW 型态指标, 通常传入标准输出入屏幕 stdscr bf 为 TRUE 或 FALSE 当开启 keypad 後, 可以使用键盘上的一些特殊字元, 如上下左右 等方向键, curses 会将这些特殊字元转换成 curses.h 内定义的一 些特殊键. 这些定义的特殊键通常以 KEY_ 开头. □ refresh() refresh() 为 curses 最常呼叫的一个函数. curses 为了使屏幕输出入达最佳化, 当您呼叫屏幕输出函数企图改 变屏幕上的画面时, curses 并不会立刻对屏幕做改变, 而是等到 refresh() 呼叫後, 才将刚才所做的变动一次完成. 其馀的资料将 维持不变. 以尽可能送最少的字元至屏幕上. 减少屏幕重绘的时间. 如果是 initscr() 後第一次呼叫 refresh(), curses 将做清除萤 幕的工作. ■ 光标的控制 move(y,x) 将光标移动至 x,y 的位置 getyx(win,y,x) 得到目前光标的位置 (请注意! 是 y,x 而不是 &y,&x ) ■ 有关清除屏幕的函数 clear() erase() 将整个屏幕清除 (请注意配合refresh() 使用) ■ 如何在屏幕上显示字元 echochar(ch) 显示某个字元 addch(ch) 显示某个字元 mvaddch(y,x,ch) 在(x,y) 上显示某个字元 相当於呼叫 move(y,x);addch(ch); addstr(str) 显示一串字串 mvaddstr(y,x,str) 在(x,y) 上显示一串字串 相当於呼叫 move(y,x);addstr(str); printw(format,str) 类似 printf() , 以一定的格式输出至屏幕 mvprintw(y,x,format,str) 在(x,y) 位置上做 printw 的工作. 相当於呼叫 move(y,x);printw(format,str); ■ 如何从键盘上读取字元 getch() 从键盘读取一个字元 (注意! 传回的是整数值) getstr() 从键盘读取一串字元 scanw(format,&arg1,&arg2...) 如同 scanf, 从键盘读取一串字元 □例: int ch; char string1[80]; /* 请注意! 不可宣告为 char *string1; */ char string2[80]; echo(); /* 开启 echo 模式, 使输入立刻显示在屏幕上 */ ch=getch(); string1=getstr(); scanw("%s",string2); mvprintw(10,10,"String1=%s",string1); mvprintw(11,10,"String2=%s",string2); ■ 如何利用方向键 curses 将一些如方向键等特殊控制字元, 以 KEY_ 为开头定义在 curses.h 这个档案里头, 如 KEY_UP 即代表方向键的 " ↑ ". 但, 如果您想使用 curses.h 所为您定义的这些特殊键的话, 您就必须将 keypad 设定为 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 以上仅列出笔者较常使用的一些控制键, 至於其他控制键的定义, 请自行参 阅 man curses (* 注三) 一并为您列出其他常用的一些特殊字元 [TAB] /t [ENTER] /r [ESC] 27 [BACKSPACE] 127 ■ 如何改变屏幕显示字元的属性 为了使输出的屏幕画面更为生动美丽, 我们常须要在屏幕上做一些如反白, 闪烁等变化. curses 定义了一些特殊的属性, 透过这些定义, 我们也可以 在 curses 程序□控制屏幕的输出变化. attron(mod) 开启属性 attroff(mod) 关闭属性 curses.h 里头定义了一些属性, 如: A_UNDERLINE 加底线 A_REVERSE 反白 A_BLINK 闪烁 A_BOLD 高亮度 A_NORMAL 标准模式 (只能配合 attrset() 使用)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -