2007年3月29日星期四

WGet使用指南

wget是一个从网络上自动下载文件的自由工具。它支持HTTP,HTTPS和FTP协议,可以使用HTTP代理.

所谓的自动下载是指,wget可以在用户退出系统的之后在后台执行。这意味这你可以登录系统,启动一个wget下载任务,然后退出系统,wget将在后台执行直到任务完成,相对于其它大部分浏览器在下载大量数据时需要用户一直的参与,这省去了极大的麻烦。

wget可以跟踪HTML页面上的链接依次下载来创建远程服务器的本地版本,完全重建原始站点的目录结构。这又常被称作”递归下载”。在递归下载的 时候,wget遵循Robot Exclusion标准(/robots.txt). wget可以在下载的同时,将链接转换成指向本地文件,以方便离线浏览。

wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性.如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完 毕。如果是服务器打断下载过程,它会再次联到服务器上从停止的地方继续下载。这对从那些限定了链接时间的服务器上下载大文件非常有用。

wget的常见用法

wget的使用格式

Usage: wget [OPTION]... [URL]...
  • 用wget做站点镜像:
wget -r -p -np -k http://dsec.pku.edu.cn/~usr_name/
# 或者
wget -m http://www.tldp.org/LDP/abs/html/
  • 在不稳定的网络上下载一个部分下载的文件,以及在空闲时段下载
wget -t 0 -w 31 -c http://dsec.pku.edu.cn/BBC.avi -o down.log &
# 或者从filelist读入要下载的文件列表
wget -t 0 -w 31 -c -B ftp://dsec.pku.edu.cn/linuxsoft -i filelist.txt -o down.log &

上面的代码还可以用来在网络比较空闲的时段进行下载。我的用法是:在mozilla中将不方便当时下载的URL链接拷贝到内存中然后粘贴到文件filelist.txt中,在晚上要出去系统前执行上面代码的第二条。

  • 使用代理下载
wget -Y on -p -k https://sourceforge.net/projects/wvware/

代理可以在环境变量或wgetrc文件中设定

# 在环境变量中设定代理
export PROXY=http://211.90.168.94:8080/
# 在~/.wgetrc中设定代理
http_proxy = http://proxy.yoyodyne.com:18023/
ftp_proxy = http://proxy.yoyodyne.com:18023/

wget各种选项分类列表

  • 启动
-V,  --version           显示wget的版本后退出
-h, --help 打印语法帮助
-b, --background 启动后转入后台执行
-e, --execute=COMMAND 执行`.wgetrc'格式的命令,wgetrc格式参见/etc/wgetrc或~/.wgetrc
  • 记录和输入文件
-o,  --output-file=FILE     把记录写到FILE文件中
-a, --append-output=FILE 把记录追加到FILE文件中
-d, --debug 打印调试输出
-q, --quiet 安静模式(没有输出)
-v, --verbose 冗长模式(这是缺省设置)
-nv, --non-verbose 关掉冗长模式,但不是安静模式
-i, --input-file=FILE 下载在FILE文件中出现的URLs
-F, --force-html 把输入文件当作HTML格式文件对待
-B, --base=URL 将URL作为在-F -i参数指定的文件中出现的相对链接的前缀
--sslcertfile=FILE 可选客户端证书
--sslcertkey=KEYFILE 可选客户端证书的KEYFILE
--egd-file=FILE 指定EGD socket的文件名
  • 下载
--bind-address=ADDRESS   指定本地使用地址(主机名或IP,当本地有多个IP或名字时使用)
-t, --tries=NUMBER 设定最大尝试链接次数(0 表示无限制).
-O --output-document=FILE 把文档写到FILE文件中
-nc, --no-clobber 不要覆盖存在的文件或使用.#前缀
-c, --continue 接着下载没下载完的文件
--progress=TYPE 设定进程条标记
-N, --timestamping 不要重新下载文件除非比本地文件新
-S, --server-response 打印服务器的回应
--spider 不下载任何东西
-T, --timeout=SECONDS 设定响应超时的秒数
-w, --wait=SECONDS 两次尝试之间间隔SECONDS秒
--waitretry=SECONDS 在重新链接之间等待1...SECONDS秒
--random-wait 在下载之间等待0...2*WAIT秒
-Y, --proxy=on/off 打开或关闭代理
-Q, --quota=NUMBER 设置下载的容量限制
--limit-rate=RATE 限定下载输率
  • 目录
-nd  --no-directories            不创建目录
-x, --force-directories 强制创建目录
-nH, --no-host-directories 不创建主机目录
-P, --directory-prefix=PREFIX 将文件保存到目录 PREFIX/...
--cut-dirs=NUMBER 忽略 NUMBER层远程目录
  • HTTP 选项
--http-user=USER      设定HTTP用户名为 USER.
--http-passwd=PASS 设定http密码为 PASS.
-C, --cache=on/off 允许/不允许服务器端的数据缓存 (一般情况下允许).
-E, --html-extension 将所有text/html文档以.html扩展名保存
--ignore-length 忽略 `Content-Length'头域
--header=STRING 在headers中插入字符串 STRING
--proxy-user=USER 设定代理的用户名为 USER
--proxy-passwd=PASS 设定代理的密码为 PASS
--referer=URL 在HTTP请求中包含 `Referer: URL'头
-s, --save-headers 保存HTTP头到文件
-U, --user-agent=AGENT 设定代理的名称为 AGENT而不是 Wget/VERSION.
--no-http-keep-alive 关闭 HTTP活动链接 (永远链接).
--cookies=off 不使用 cookies.
--load-cookies=FILE 在开始会话前从文件 FILE中加载cookie
--save-cookies=FILE 在会话结束后将 cookies保存到 FILE文件中
  • FTP 选项
-nr, --dont-remove-listing   不移走 `.listing'文件
-g, --glob=on/off 打开或关闭文件名的 globbing机制
--passive-ftp 使用被动传输模式 (缺省值).
--active-ftp 使用主动传输模式
--retr-symlinks 在递归的时候,将链接指向文件(而不是目录)
  • 递归下载
-r,  --recursive          递归下载--慎用!
-l, --level=NUMBER 最大递归深度 (inf 或 0 代表无穷).
--delete-after 在现在完毕后局部删除文件
-k, --convert-links 转换非相对链接为相对链接
-K, --backup-converted 在转换文件X之前,将之备份为 X.orig
-m, --mirror 等价于 -r -N -l inf -nr.
-p, --page-requisites 下载显示HTML文件的所有图片
  • 递归下载中的包含和不包含(accept/reject)
-A,  --accept=LIST                分号分隔的被接受扩展名的列表
-R, --reject=LIST 分号分隔的不被接受的扩展名的列表
-D, --domains=LIST 分号分隔的被接受域的列表
--exclude-domains=LIST 分号分隔的不被接受的域的列表
--follow-ftp 跟踪HTML文档中的FTP链接
--follow-tags=LIST 分号分隔的被跟踪的HTML标签的列表
-G, --ignore-tags=LIST 分号分隔的被忽略的HTML标签的列表
-H, --span-hosts 当递归时转到外部主机
-L, --relative 仅仅跟踪相对链接
-I, --include-directories=LIST 允许目录的列表
-X, --exclude-directories=LIST 不被包含目录的列表
-np, --no-parent 不要追溯到父目录

2007年3月28日星期三

Efficient Editing With vim

This article has been translated into French by Geoffrey Bachelet. You can read the French version here: L'?dition efficace avec vim.


"To me, vi is Zen.
To use vi is to practice zen.
Every command is a koan.
Profound to the user,
unintelligible to the uninitiated.
You discover truth every time you use it."
--reddy@lion.austin.com

This tutorial assumes a basic knowledge of vim -- insert mode, command mode, loading and saving files, etc. It is intended to help vi novices develop their skills so that they can use vi efficiently.

In this tutorial, means Ctrl-X -- that is, hold down the Ctrl key and press X. You can get help on most of the commands used here by typing :help command in vim, where command is what you need help on.
Moving efficiently
Stay out of insert mode

In general, you want to spend as little of your time in vim's insert mode as possible, because in that mode it acts like a dumb editor. This is why most vim novices spend so much time in insert mode -- it makes vim easy to use. But vim's real power lies in command mode! You'll find that the better you know vim, the less time you will spend in insert mode.
Use h, j, k, and l

The first step to efficient editing in vim is to wean yourself from the arrow keys. One of the the advantages of vim's modal design is that you do not need to constantly move your hands back and forth between the arrow keys and the letter keys; when you are in command mode, the letters h, j, k and l correspond to the directions left, down, up, and right, respectively. It takes some practice to get used to, but you will notice the speed difference once you're used to it.

When you are editing e-mail or other paragraph-formatted text, you might notice that the direction keys skip more lines than you expect. This is because your paragraphs appear as one long line to vim. Type g before h, j, k or l to move by screen lines instead of virtual lines.
Use motions to move the cursor in the current line

Most editors have only simple commands for moving the cursor (left, up, right, down, to beginning/end of line, etc). vim has very advanced commands for moving the cursor; these commands are referred to as motions. When the cursor moves from one point in the text to another, the text between the points (and including the points themselves) is considered to be "moved over." (This will be important later.)

Here are a few of the more useful motions:
fx Move the cursor forward to the next occurance of the character x on the current line (obviously, x can be any character you like). This is an extremely useful command. You can type ; to repeat the last f command you gave.
tx Same as above, but moves the cursor to right before the character, not all the way to it. (It's very useful, really.)
Fx Move the cursor backward to the next occurance of the character x on the current line.
w Move the cursor forward by a word.
b Move the cursor backward by a word.
0 Move the cursor to the beginning of the current line.
^ Move the cursor to the first character on the current line.
$ Move the cursor to the end of the line
) Move the cursor forward to the next sentence. (Useful when editing e-mail or text documents.)
( Move the cursor backward by a sentence.
Move efficiently through the file

vim has many commands that can send you to where you want to go in your file -- there's rarely a need to scroll manually through it. The below keystrokes are not technically motions, since they move around in the file instead of in a particular line.
Move the cursor forward by a screenful of text
Move the cursor backward by a screenful of text
G Move the cursor to the end of the file
numG Move the cursor line num. (For instance, 10G moves to line 10.)
gg Move the cursor to the beginning of the file
H Move the cursor to the top of the screen.
M Move the cursor to the middle of the screen.
L Move the cursor to the bottom of the screen.
* Read the string under the cursor and go to the next place it appears. (For instance, if your cursor was somewhere on the word "bob," the cursor would move to the next occurance of "bob" in your file.)
# Same as above, except it moves the cursor to the previous occurance.
/text Starting from the cursor, find the next occurance of the string text and go to it. You will need to press Enter to execute the search. To re-execute your last search, type n (for next occurance).
?text Same as /, but searches in the opposite direction.
ma Make a bookmark named a at the current cursor position. A bookmark can be named any lowercase letter. You can't see the bookmark, but it's there!
`a Go to bookmark a. Important: that's a backtick, not a single quote. The backtick is located to the left of the 1 on most keyboards.
`. Go to the line that you last edited. This is very useful! If you need to scroll through the file to look something up, you can go back to where you were without bookmarking it by using the `. command.
Typing efficiently
Use keyword completion

vim has a very nice keyword completion system. This means that you can type part of a long word, press a key, and have vim finish the word for you. For instance, if you have a variable called iAmALongAndAwkwardVarName somewhere in your code, you probably don't want to type the whole thing in every time you use it.

To use keyword completion, just type the first few letters of the string (e.g. iAmAL) and press (that means hold down Ctrl and type N) or . If vim doesn't give you the word you want at first, keep trying -- vim will cycle through all completions it can find.
Enter insert mode intelligently

Most users new to vim get into insert mode by typing i. This works, but it's often pretty inefficient, since vi has a host of commands that leave the editor in insert mode. Here are some of the more popular ones:
i Insert text to the left of the current character.
I Insert text at the beginning of the current line.
a Insert text to the right of the current character.
A Insert text at the end of the current line.
o Create a new line under the current one and insert text there.
O Create a new line above the current one and insert text there.
c{motion} Delete (change) the text moved over by {motion} and insert text to replace it. For instance, c$ would delete the text from the cursor to the end of the line and enter insert mode. ct! would delete the text from the cursor up to (but not including) the next exclamation mark and enter insert mode. The deleted text is copied to the clipboard and can be pasted.
d{motion} Delete the text moved over by {motion} -- same as c{motion}, but doesn't enter insert mode.
Moving blocks of text efficiently
Use visual selections and the appropriate selection mode

Unlike the original vi, vim allows you to highlight text and perform operations on it. There are three main visual selection modes (that is, text highlighting modes). These modes are as follows:
v Characterwise selection mode. This is the selection mode that most people are used to, so practice with it before trying the others.
V Linewise selection mode. Whole lines are always selected. This is better than characterwise mode when you want to copy or move a group of lines.
Blockwise selection mode. Extremely powerful and available in very few other editors. You can select a rectangular block and any text inside that block will be highlighted.

All the usual cusor movement keys apply -- so, for instance, vwww would go into visual selection mode and highlight the next three words. Vjj would go into linewise visual selection mode and highlight the current line and the two lines below it.
Cutting and copying from visual selections

Once you have a highlighted selection, you probably want to do something with it. Some of the more useful commands you can give when an area of text is highlighted:
d Cut (delete) the highlighted text and put it into the clipboard.
y Copy (or yank, which is vim-ese for "copy") the highlighted text into the clipboard.
c Cut the highlighted text into the clipboard. This is just like d, except it leaves the editor in insert mode.
Cutting and copying from non-visual selections

If you know exactly what you want to copy or cut, you can do it without entering visual mode. This saves time.
d{motion} Cut the text moved over by {motion} to the clipboard. For instance, dw would cut a word and dfS would cut from the cursor up to and including the next capital S on the current line of text.
y{motion} Copy the text moved over by {motion}.
c{motion} Cut the text moved over by {motion} and leave the editor in insert mode.
dd Cut the current line.
yy Copy the current line.
cc Cut the current line and leave the editor in insert mode.
D Cut from the cursor to the end of the current line.
Y Yank the whole line, just like yy. (Yes, it's inconsistent! You can use y$ to do what you would expect Y to do.)
C Cut from the cursor to the end of the current line and leave the editor in insert mode.
x Cut the current character. (This is sort of like a command-mode backspace.)
s Cut the current character and leave the editor in insert mode.
Pasting

Pasting is easy. Put the cursor where you want the pasted text and type p.
Using multiple clipboards

Most editors have a single clipboard. vim has many more; clipboards in vim are called registers. You can list all the currently defined registers and their contents by typing :reg. Typically, you'll be using the lowercase letter registers; the others are used for various internal vim purposes and are only occasionally helpful.

To use a specific register for a copy or paste operation, simply type "a before the command for the operation, where a is the register you want to use.

For example, to copy the current line into register k, you could type "kyy. (You could also type V"ky. Why would that work?). That line would stay in register k until you specifically copied something else into register k. You would then use "kp to paste the text from register k.
Avoiding repetition
The amazing . command

In vi, typing . (a period) will repeat the last command you gave. For instance, if your last command was dw (delete word), vi will delete another word.
Using counts

Counts are one of the most powerful and time-saving features of vim. Any command can be preceded by a number. The number will tell vim how many times to execute the command. Here are a few examples:

3j will move the cursor down three lines.

10dd will delete ten lines.

y3"e; will yank (copy) text from the cursor to the third quotation mark after the cursor on the current line. Counts are useful to extend the range of a motion in this manner.
Recording macros

Occasionally, you'll find yourself doing the same thing over and over to blocks of text in your document. vim will let you record an ad-hoc macro to perform the operation.
qregister Start macro recording into the named register. For instance, qa starts recording and puts the macro into register a.
q End recording.
@register Replay the macro stored in the named register. For instance, @a replays the macro in register a.

Keep in mind that macros just record your keystrokes and play them back; they are not magic. Recording macros is almost an art form because there are so many commands that accomplish a given task in vim, and you must carefully select the commands you use while your macro is recording so that they will work in all the places you plan to execute the macro.
Writing code in vim

vim is an excellent editor for source code because it has many features that are specifically designed to help programmers. Here are a few of the more handy ones:
]p Just like p, but it automatically adjusts the indent level of the pasted code to match that of the code you paste into. Try it!
% Putting the cursor on a brace, bracket, or parenthese and pressing % will send the cursor to the matching brace, bracket, or parenthese. Great for fixing parse problems related to heavily nested blocks of code or logic.
>> Indent the highlighted code. (See the earlier section about efficient text selection. If no text is selected, the current line is indented.)
<< Like >>, but un-indents.
gd Go to the definition (or declaration) of the function or variable under the cursor.
K Go to the man page for the word currently under the cursor. (For instance, if your cursor is currently over the word sleep, you will see the man page for sleep displayed.)

2007年3月10日星期六

UNIX下c语言的图形编程--curses.h 函式库

相信您在网路上一定用过如 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 程式的档头将 include 进来.当您引进 curses.h
这个函式库後, 系统会自动将 一并 include 进
来.另外, 在 System V 版本中, 这个函式库也将一并
include进来.

#include

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

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() 使用)


当使用 attron() 开启某一种特殊属性模式後, 接下来在萤幕的输出都会以

该种属性出现. 直到您呼叫 attroff() 将此模式关闭.

请注意, 当您欲 attron() 开启另一种属性时, 请记得利用 attroff()先关

闭原来的属性, 或直接以 attrset(A_NORMAL) 将所有特殊属性关闭.否则,

curses 会将两种属性做重叠处理.

□例:

attrset(A_NORMAL); /* 先将属性设定为正常模式 */

attron(A_UNDERLINE); /* 加底线 */

mvaddstr(9,10,"加底线"); /* 加底线输出一串字元 */

attroff(A_UNDERLINE); /* 关闭加底线模式, 恢复正常模式 */

attron(A_REVERSE); /* 开启反白模式 */

mvaddstr(10,10,"反白"); /* 输出一串反白字元 */

attroff(A_REVERSE); /* 关闭反白模式, 恢复正常模式 */

attron(A_BLINK); /* 开启闪烁模式 */

mvaddstr(11,10,"闪烁"); /* 输出一串闪烁字元 */

attroff(A_BLINK); /* 关闭闪烁模式, 恢复正常模式 */

attron(A_BOLD); /* 开启高亮度模式 */

mvaddstr(12,10,"高亮度"); /* 输出一串高亮度字元 */

attroff(A_BOLD); /* 关闭高亮度模式, 恢复正常模式 */



■ 其他常用的一些函式

beep() 发出一声哔声
box(win,ch1,ch2) 自动画方框 ch1: 画方框时垂直方向所用字元
ch2: 画方框时水平方向所用字元

example: box(stdscr,'|','-');
将以 | 及 - 围成一个方框

■ 应用完整□例

下面所举的例子, 即完全利用刚刚所介绍的含式来完成.这个程式可将从键

盘上读取的字元显示在萤幕上, 并且可以上下左右方向键来控制游标的位置

, 当按下 [ESC] 後, 程式即结束.

您有没有发现, 这不就是一个简单全萤幕编辑器的雏形吗?


#include /* 引进 curses.h , 并自动引进
stdio.h */


#define StartX 1 /* 决定游标初始位置 */
#define StartY 1

void initial();

main()
{
int x=StartX; /* 宣告 x,y 并设定其初值
*/

int y=StartY;
int ch; /* 宣告 ch 为整数,配合 getch()
使用 */


initial(); /* 呼叫 initial(), 启动 curses
模式, */

/* 并完成其它设定
*/


box(stdscr,'|','-'); /* 画方框
*/


attron(A_REVERSE); /* 开启反白模式
*/

mvaddstr(0,20,"Curses Program"); /* 在 (20,0) 处输出反白字元
*/

attroff(A_REVERSE); /* 关闭反白模式
*/


move(x,y); /* 将游标移至初始位置
*/


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 一个字元
*/

break;

case 27: endwin(); /* 判断是否[ESC]键被按下
*/

exit(1); /* 结束 curses 模式
*/

/* 结束此程式
*/


default:
addch(ch); /* 如果不是特殊字元, 将此字元印
出 */

x++;
break;
}
move(y,x); /* 移动游标至现在位置
*/

} while (1);
}

void initial() /* 自定开启 curses 函式
*/

{
initscr();
cbreak();
nonl();
noecho();
intrflush(stdscr,FALSE);
keypad(stdscr,TRUE);
refresh();
}



■ 後记

学完了上述的一些命令, 相不相信您已经可以写出一个漂亮的全萤幕编辑
器了? 事实上, curses 提供的函式不下 200 个, 可是笔者认为, 一切再
复杂的函式都可以用本文提到的一些组合变化而成, 学了太多的函式, 只
是徒增自己困扰罢了. 当然, 如果您对其它函式有兴趣, 可以自行参阅
curses 说明档. ( 方法: % man curses ) 本文不过行抛砖引玉之效, 也
希望未来能陆续出现更多同学自行创作的程式.

* 任何疑问及建议, 欢迎 e-mail 至 ljh@CCCA.NCTU.edu.tw. 谢谢 ! *



注一:
请参考 /usr/share/lib/termcup
/usr/share/lib/terminfo/s/sun

注二:
1.如果是 BSD 的版本, 需使用
cc [file.c] -lcurses -ltermcap 来完成 compile.
2.计中工作站不知何故将原来的 /usr/5bin/cc 更改为 /usr/5bin/cc.org

因此, 您若想在计中工作站 compile curses 程式.需以 /usr/5bin/cc.
org
取代 /usr/5bin/cc , 否则 compile 可能发生错误.
3.较旧版的 curses 需同时引进 curses 和 termlib 这两个 library,
因此, 您必须使用 /usr/5bin/cc [file.c] -lcurses -ltermlib 来
compile.

注三:
根据笔者的经验, 上下左右方向键应可正常使用而不会发生问题, 但其它

如 PgUp,PgDn,功能键,Home,End 等特殊键, 很容易因机器, 键盘不同而无

法使用, 因此, 若您的程式须要在不同的机器上使用, 建议您只用方向键来

控制, 其它的特殊键少用为妙.
至於 PgUp,PgDn 一些特殊键的控制方法, 由於较为复杂, 有兴趣的同学可

考 tin 原始程式 curses.c 内所使用的一些方法.