-
Notifications
You must be signed in to change notification settings - Fork 12
Home
大多数商业化软件产品一般会通过实现 GUI(Graphical User Interface) 或者 TUI(Text-based User Interface/Textual User Interface/Terminal User Interface) 来降低软件的使用难度
newt 是由 RedHat 开发,主要用在 RatHat 的 Linux 发行版本 (RHEL, Fedora 和 CentOS) 的安装程序项目 Anaconda 中。 NEWT 的全称是:Not Erik’s Windowing Toolkit ,它基于 S-Lang 库实现。
因为 newt 是用于 Linux 发行版本的安装程序中,因而它的运行空间非常有限,需要保证程序尽可能小,所以在设计时选择使用 C 语言进行开发,也尽量不支持多余特性。
于是在设计之初就不支持事件驱动。在支持事件驱动的窗口库中,有一个事件循环监听事件发生,根据发生的事件展示不同的窗口。
在 newt 中,窗口创建和销毁基于栈模式,新创建的窗口位于之前的窗口之上,且只能展示最上层窗口,当最上层窗口销毁之后才能展示下边的窗口。
这也就是说所有窗口都为模态窗口 ( model windows )。这种特性限制了 newt 库本身只适合用于完成顺序的程序流程,一个典型的场景就是程序的安装向导。
SHELL 程序往往也是顺序的流程,从 SHELL 程序转换为 newt 窗口程序完全不涉及程序流程的改变,实现非常简单。
示例:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <newt.h>
void show_message_window(void) {
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 text, button, form;
newtCls();
text = newtTextboxReflowed(1, 1, message, 30, 5, 5, 0);
button = newtButton(12, newtTextboxGetNumLines(text) + 2, "Exit");
newtCenteredWindow(37, newtTextboxGetNumLines(text) + 7, "MESSAGE");
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, text, button, NULL);
newtRunForm(form);
newtFormDestroy(form);
newtPopWindow();
}
void show_login_failed_window(void) {
newtComponent label, button, form;
newtCls();
newtCenteredWindow(60, 6, "NOTE");
label = newtLabel(10, 2, "Login failed!");
button = newtCompactButton(30, 4, "Exit");
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, label, button, NULL);
newtRunForm(form);
newtFormDestroy(form);
newtPopWindow();
}
int main(void) {
int cols, rows;
newtInit();
do {
newtCls();
newtPushHelpLine(NULL);
newtGetScreenSize(&cols, &rows);
newtOpenWindow(1, 1, cols - 2, rows - 4, "LOGIN");
newtComponent form, btn_ok, btn_cancel, label_username, label_password,
entry_username, entry_password, result;
const char *username, *password;
label_username = newtLabel(10, 3, "Username:");
entry_username = newtEntry(20, 3, "root", 20, &username,
NEWT_FLAG_SCROLL);
label_password = newtLabel(10, 5, "Password:");
entry_password = newtEntry(20, 5, "", 20, &password,
NEWT_FLAG_PASSWORD | NEWT_FLAG_SCROLL);
result = newtLabel(10, 10, "");
btn_ok = newtButton(10, 7, "OK");
btn_cancel = newtButton(20, 7, "Cancel");
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, label_username, entry_username,
label_password, entry_password,
btn_ok, btn_cancel, result,
NULL);
struct newtExitStruct exit_status;
newtFormRun(form, &exit_status);
if (exit_status.reason == NEWT_EXIT_COMPONENT) {
if (exit_status.u.co == btn_ok) {
if ((strcmp(username, "root") == 0)
&& (strcmp(password, "123456") == 0))
{
show_message_window();
break;
} else {
show_login_failed_window();
}
} else if (exit_status.u.co == btn_cancel) {
break;
}
}
newtRefresh();
newtFormDestroy(form);
newtPopWindow();
newtPopHelpLine();
} while (1);
newtFinished();
return 0;
}
编译
gcc -o newtdemo newtdemo.c -lnewt
官方 newt 库中还提供了 Python 封装库,名称为 snack 。具体用法和 C 库类似,官方也提供了两个示例:
Centos 6.X 以上可以直接使用
如果是想在 Centos 低版本上使用,需要做以下步骤:(因为需要升级 glibc 所以不建议操作)
升级 glibc 到 2.4 以上(有风险)
screen 模式,无法对 snack 类重新实例化导致。
执行此脚本时会检测是否有libnewt.so.0.52
和 libslang.so.2
文件,如果没有则进行拷贝,拷贝的库为 centos 6.5 系统的库文件
备注: Centos6.x 及以上系统时无需操作
使用的 Centos7.6 下的 snack(2014 年)
$ cd /usr/lib64/python2.7/site-packages
$ ll | grep snack
-rwxr-xr-x 1 root root 40904 Jun 10 2014 _snackmodule.so
-rw-r--r-- 1 root root 30957 Jun 10 2014 snack.py
在 centos6.X 上也是可以运行的