NEWT是在Linux下一个基于文本方式的窗口开发工具,最初是为RedHad Linux的安装程序而设计的。NEWT提供C语言的应用程序接口(API),它不直接进行低级屏幕操作,是在S-Lang库上实现的。编程时包含头文件#include <newt.h>,在Linux上用gcc编译时带-lnewt 参数。
考虑到 Red Hat Linux 有软盘安装这一安装方式,安装代码运行于有限的资源环境中,特别是在有限的文件空间中。NEWT 的大小一开始就成为一个重要的问题。为了最小化它所占的空间,NEWT 的设计思想有下面几点:(1)NEWT由C语言写成,而不是C++;(2)NEWT所有窗口的生成都是基于堆栈的数据结构,窗口的外观都是统一的模板,不由程序员修改;(3)输入设备只支持终端键盘。
Linux系统安装过程NEWT的界面:
#include <stdio.h> #include <newt.h> int main() { newtInit(); newtCls(); int rc = newtWinChoice(("Disc Found"), ("OK"), ("Skip"), ("To begin testing the media before installation press %s.\n\n" "Choose %s to skip the media test and start the installation."), ("OK"), ("Skip")); if (rc == 1) { newtDrawRootText(0,0,"you choose:ok"); newtRefresh(); } sleep(3); newtFinished(); return 0; }编译:gcc -o newt newt.c -lnewt
int newtInit(void); void newtCls(void);newtInit()必须是每个NEWT程序第一个调用的函数,用于初始化数据结构和重置终端于raw模式。大多数应用在newtInit()后立即调用newtCls(),newtCls()用于清除屏幕(这个函数不是必须的,但有助于优化屏幕 )。
int newtFinished(void);newtFinished()恢复终端在调用newtInit()前的状态,重置原来的输入状态。若没调用这函数,终端需重启才能回到命令行状态。
void newtDrawRootText(int left, int top, const char *text);该函数用于在根窗口指定位置写出text字苻串,left和top为字苻串text的开始处,left是屏幕x坐标,top是屏幕y坐标。Left和top允许为负数。屏幕坐标原点在显示器的左上角,x坐标从原点出发至左向右增大,y坐标从原点出发至上向下增大。点(10,5)表示以左上角为原点x=10,y=5,而left,top为负,表与为正数方向相对。点(-10,5)表以右上角为原点x=10,因此点(10,5)与点(-10,5)在屏幕左右两边相对,同理点(10,5)与点(10,-5)在屏幕上下两边相对。
void newtPushHelpLine(const char * text); void newtPopHelpLine(void);newtPushHelpLine()用于显示帮助行,text为所要显示的字苻串指针,若为NULL则显示缺省的帮助行。NewtPopHelpLine()则删除帮助行。
typedef void (*newtSuspendCallback)(void); void newtSetSuspendCallback(newtSuspendCallback cb);但可通过调用newtSetSuspendCallback()实现Ctrl-z强迫退出的功能,cb是相应的回调函数,它不带参数,只做清理工作,如newtFinished()等。早期Red Hat Linux的安装程序当运行到硬盘分区时,若你使用Fdisk则屏幕回到命令行状态运行Fdisk进行分区,退出Fdisk时又回到当前窗口。要实现这种功能,在回调函数中加入下面两个函数:
void newtSuspend(void); void newtResume(void);newtSuspend()告诉NEWT程序回到终端初始化前的状态,做需要做的工作。如需要回到NEWT界面,调用newtResume()恢复。
int newtCenteredWindow(int width, int height, const char * title); int newtOpenWindow(int left, int top, int width, int height, const char * title);由名字可知,newtCenteredWindow()在屏幕中心生成窗口,width为窗口宽度,height为窗口高度,title为窗口标题字串指针,标题文字为红色。由newtOpenWindow()生成的窗口位置由left,top 确定,其余参数同上。
void newtPopWindow(void);这函数删除屏幕最顶层的窗口,并重画被该窗口遮盖的部分。
newtComponent newtForm(newtComponent vertBar, const char * help, int flags);vertBar是垂直滚动条,help是提示信息,通常这两个参数都不会用到,用NULL即可,flags就是前述的标志。该函数返回标志所生成的Form 的变量。
void newtFormAddComponent(newtComponent form, newtComponent co); void newtFormAddComponents(newtComponent form, ...);newtFormAddComponent()只放一个组件在Form上,而newtFormAddComponents()则可放多个组件,最后用NULL结束。然后就运行它:
newtComponent newtRunForm(newtComponent form);其中Form参数是newtForm()返回的变量。
void newtFormDestroy(newtComponent form);(8)按钮
newtComponent newtButton(int left, int top, const char * text); newtComponent newtCompactButton(int left, int top, const char * text);newtButton()生成完全按钮,letf,top指定该按钮位置,text是指向按钮文字的指针,该函数返回按钮的newtComponent变量。NewtCompactButton()生成紧缩按钮,参数及返回值同上。
newtComponent newtLabel(int left, int top, const char * text); void newtLabelSetText(newtComponent co, const char * text);newtLabel()生成标签组件,并返回它的newtComponent变量,参数left,top指定标签组件位置,text为给定的文本。NewtLabelSetText()用于动态改变标签组件的文字,co是要改变的标签组件,test是要改变的字串指针。
newtComponent newtEntry(int left, int top, const char * initialValue, int width,char ** resultPtr, int flags); void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd); char * newtEntryGetValue(newtComponent co);newtEntry()生成输入盒组件,其中initialValue为初始化字符串指针,若不需则用NULL,width为宽度,resultPtr为指向当前输入的字符,flags为标志。Flags设为NEWT_ENTRY_SCROLL,当输入的字串长度等于输入盒的宽度时输入盒将往后滚动,否则不能再输入;Flags设为 NEWT_FLAG_HIDDEN输入不回显,主要应用于输入密码方面。NewtEntrySet()用于动态地改变输入盒的内容,value为字符串指针,cursorAtEnd实质是一个逻辑变量,由于C语言没有逻辑类型变量,仅用int代替,若为0则表TRUE,指定光标跟随,非0光标不跟随输入。NewtEntryGetValue()返回输入的字串。
newtComponent newtCheckbox(int left, int top, const char * text, char defValue,const char * seq, char * result); char newtCheckboxGetValue(newtComponent co);newtCheckbox()生成一个检查盒,text标明它所代表的内容,defValue为缺省值也即初始值,seq为切换的顺序,result指向当前状态。如 defValue='@',seq="@*X",则初始时为[@],当按空格键==》[*]再按空格键==》 [X],如此循环。若result为NULL则需NewtCheckboxGetValue()获取当前状态。
newtComponent newtRadiobutton(int left, int top, const char * text, int isDefault, newtComponent prevButton); newtComponent newtRadioGetCurrent(newtComponent setMember);newtRadiobutton()建立单选按钮集合,text为代表单选按钮的字符串指针,isDefault是逻辑开关,为1表逻辑TRUE, 初始状态为选中;为0表FALSE,初始状态为不选中。若当前单选按钮是集合中的第一个,prevButton为NULL让newtRadiobutton()自动建立一个集合;若不是第一个,prevButton为前一个由newtRadiobutton()生成的单选按钮。
newtComponent newtScale(int left, int top, int width, long long fullValue); void newtScaleSet(newtComponent co, unsigned long long amount);newtScale()生成水平进度条,width为宽度,fullValue为进度条的最大值。NewtScaleSet()用于设置进度条的值。
newtComponent newtTextbox(int left, int top, int width, int height, int flags); void newtTextboxSetText(newtComponent co, const char * text);(15)滚动条(Scrollbar)
newtComponent newtVerticalScrollbar(int left, int top, int height, int normalColorset, int thumbColorset);newtVerticalScrollbar()生成滚动条,normalColorset为滚动条颜色,thumbColorset为滚动块颜色。
newtComponent newtListbox(int left, int top, int height, int flags); int newtListboxAppendEntry(newtComponent co, const char * text, const void * data); void * newtListboxGetCurrent(newtComponent co); void newtListboxSetWidth(newtComponent co, int width); void newtListboxSetCurrent(newtComponent co, int num); void newtListboxSetCurrentByKey(newtComponent co, void * key);newtListbox()生产列表盒,flags可设为NEWT_FLAG_SCROLL、NEWT_FLAG_RETURNEXIT、NEWT_FLAG_BORDER、 NEWT_FLAG_MULTIPLE和它们的与操作。NewtListboxAppendEntry() 用于在当前列表盒最后追加一个列表项,每一个个列表项由key唯一标志,key可为任意类型,只要能和其他列表项区别开来就可以了。data为key数据。操作列表盒的函数还有:
void newtListboxSetEntry(newtComponent co, void * key, const char * text); int newtListboxInsertEntry(newtComponent co, const char * text, const void * data, void * key); int newtListboxDeleteEntry(newtComponent co, void * key); void newtListboxClear(newtComponent co);
#include <newt.h> #include <stdio.h> #include <stdlib.h> void rootwin_show() { newtCls(); /* 请观察 left,top 为正数 , 为负数地情形 */ newtDrawRootText(0, 0, "左上角"); newtDrawRootText(-6, 0, "右上角"); newtDrawRootText(0, -3, "左下角"); newtDrawRootText(-6, -3, "右下角"); /* 注意 helpline 缺省时的内容 */ newtPushHelpLine(NULL); newtRefresh(); sleep(10); newtPushHelpLine("我的帮助行"); newtRefresh(); sleep(3); newtPopHelpLine(); newtRefresh(); sleep(1); } void label_button() { newtComponent form, label, entry, button,cb; char * entryValue; newtCls(); newtCenteredWindow(50,10,"输入与标签演示"); /*left,top 是相对于中心窗口而言 */ label = newtLabel(10, 1, "请输入 :"); entry = newtEntry(19, 1, NULL, 20, (const char **)&entryValue, NEWT_FLAG_SCROLL); newtEntrySet(entry,"\0",0); button = newtButton(10, 5, "完全按钮"); cb=newtCompactButton(25,5,"紧缩按钮"); form = newtForm(NULL,NULL, 0); newtFormAddComponents(form, label, entry, button,cb, NULL); newtRunForm(form); if(*entryValue!='\0') { newtDrawRootText(0,0,"你输入了 :"); newtDrawRootText(12,0,entryValue); } else newtDrawRootText(0,0,"无输入 !"); newtRefresh(); newtFormDestroy(form); sleep(5); } void check_radio() { newtComponent form, checkbox, rb[3], button,lable1,lable2; char cbValue,cv[2]; int i; newtCls(); newtOpenWindow(10, 8, 40, 11, "检查盒与单选盒演示"); lable1 = newtLabel(2, 1, "检查盒 :"); checkbox = newtCheckbox(10, 1, "A checkbox", ' ', " *X", &cbValue); lable2 = newtLabel(2, 4, "单选盒 :"); rb[0] = newtRadiobutton(10, 3, "Choice 1", 1, NULL); rb[1] = newtRadiobutton(10, 4, "Choice 2", 0, rb[0]); rb[2] = newtRadiobutton(10, 5, "Choice 3", 0, rb[1]); button = newtButton(15, 7, "退出"); form = newtForm(NULL, NULL, 0); newtFormAddComponent(form, checkbox); newtFormAddComponent(form, lable1); newtFormAddComponent(form, lable2); for (i = 0; i < 3; i++) newtFormAddComponent(form, rb[i]); newtFormAddComponent(form, button); newtPushHelpLine("< 空格健 > 选择"); newtRefresh(); newtRunForm(form); for (i = 0; i < 3; i++) if (newtRadioGetCurrent(rb[0]) == rb[i]) { newtDrawRootText(0, 0, "单选盒 :"); newtDrawRootText(9, 0, "第"); if(i==0)newtDrawRootText(11, 0,"1"); if(i==1)newtDrawRootText(11, 0,"2"); if(i==2)newtDrawRootText(11, 0,"3"); newtDrawRootText(12, 0, "个"); } newtDrawRootText(0, 3, "检查盒状态 :"); cv[0]=cbValue;cv[1]='\0'; newtDrawRootText(13, 3, cv); newtRefresh(); newtFormDestroy(form); sleep(5); } void test() { char message[] = "This is a pretty long message. It will be displayed " "in a newt textbox, and illustrates how to construct " "a textbox from arbitrary text which may not have " "very good line breaks.\n\n" "Notice how literal \\n characters are respected, and " "may be used to force line breaks and blank lines."; newtComponent form, text, button; newtCls(); text = newtTextboxReflowed(1, 1, message, 30, 5, 5, 0); button = newtButton(12, newtTextboxGetNumLines(text) + 2, "退出"); newtOpenWindow(10, 5, 37, newtTextboxGetNumLines(text) + 7, "文本盒"); form = newtForm(NULL, NULL, 0); newtFormAddComponents(form, text, button, NULL); newtRunForm(form); newtFormDestroy(form); } main() { newtComponent ls,fm; int p = 1, q = 2, r = 3, s = 4, t = 5, *u; newtInit(); do { newtCls(); newtRefresh(); newtDrawRootText(0,0,"这是我的一个 NEWT 演示程序"); newtCenteredWindow(50,10,"请选择"); ls = newtListbox(18,3,5,NEWT_FLAG_RETURNEXIT); newtListboxAppendEntry(ls,"根窗口演示",&p); newtListboxAppendEntry(ls,"输入盒与按钮",&q); newtListboxAppendEntry(ls,"检查盒与单选盒",&r); newtListboxAppendEntry(ls,"文本盒",&s); newtListboxAppendEntry(ls,"退出 ",&t); newtPushHelpLine(" Move using the arrow keys and press ENTER to select"); fm = newtForm(NULL,NULL,0); newtFormAddComponents(fm,ls,NULL); newtRunForm(fm); u = newtListboxGetCurrent(ls); newtPopWindow(); newtFormDestroy(fm); switch(*u) { case 1: rootwin_show(); break; case 2: label_button(); break; case 3: check_radio(); break; case 4: test(); break; case 5: newtFinished(); exit(0); } } while(1); }编译运行:gcc -o newt2 newt2.c -lnewt