C语言开发tui,TUI库newt和snack简要介绍

大多数商业化软件产品一般会通过实现GUI(Graphical User Interface)或者TUI(Text-based User Interface/Textual User Interface/Terminal User Interface)来降低软件的使用难度。本文简要介绍一个TUI库: newt。

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窗口程序完全不涉及程序流程的改变,实现非常简单。

newt中的主要结构为组件(components), 它和其他窗口库中所称的widget为相同概念。newt组件有许多, 常用的包括:

Button

CompactButton

EntryBox

CheckBox

RadioButton

Textbox

Scrollbars

Listbox

具体可以参考这篇tutorail文章

。这篇文章写于2003年, 当时newt版本为v0.31,略有些老,但内容上在现在的版本(v0.52)上依然适用。

Form是一种特殊的组件,它将其他组件组合在一起。newt应用程序使用form做为与用户交互的媒介。newt应用程序与用户交互的的简要逻辑为: 当newt应用需要从用户获取输入时,它运行一个form。此时,newt应用开始等待用户输入。用户输入信息到form中所包含的组件后,将控制权交还newt应用(如通过触发按钮等行为),newt应用再从组件中获取到用户输入的内容继续执行。form可以包含任意组件,也包括其他form。form嵌套可以用于改变TAB键触发的移动顺序、控制窗口不同区域的背景色,滚动特定窗口区域等。

newt代码中将所有的组件都用一种变量类型:newtComponent来表示。我们可以给组件注册回调函数,回调函数何时被触发取决于组件类型。回调函数原型和注册函数原型如下:

1

2typedef void (*newtCallback)(newtComponent, void *);

void newtComponentAddCallback(newtComponent co, newtCallback f, void * data);

newt所有组件都绘制在窗口(window)上,newt默认创建了一个特殊的背景窗口,叫做root窗口。我们能够在该窗口上放置组件,也可以使用API创建新的窗口。newt库的坐标系统原点坐于屏幕左上角,函数原型中,left参数表示x坐标,从原点出发从左至右增大,top参数表示y坐标,从上到下增大。left可以对应为列数,top可以对应为行数,两个坐标都可以为负数,表示从反方向开始计算。如:

1newtDrawRootText(10, -5, "Hello NEWT");

表示在距屏幕左上角的第10列,倒数第5行的位置输出字符串Hello NEWT。

下边我们以一个实例来说明newt的使用。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105#include

#include

#include

#include

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;

}

CentOS发行版默认已带有newt库,我们需要安装newt-devel库:

1yum install newt-devel

编译该程序:

1gcc -o newtdemo newtdemo.c -lnewt

执行newtdemo, 界面如下图:

a3840c3d6f76a298ad16be893a5eab6b.png

在密码框中输入123456后,移动焦点选择OK按钮,回车后显示另一个窗口:

2f0733b6e95b23d3d3b1bdcac775959b.png

我们简单说明下源代码。main函数中首先调用了:

1newtInit();

newtInit()用于初始化newt库的内部数据结构,并将终端设置为raw模式。接着调用newtCls()来清空屏幕。newt窗口的最后一行用于显示帮助信息,如每个快捷键所对应的功能。代码中调用newtPushHelpLine(NULL)显示默认的帮助信息。接下来通过调用newtOpenWindow()创建了一个新窗口,后续的组件将绘制在该窗口中。接下来,在窗口上创建了Username和Password两个输入框用于接收用户输入,以及两个按钮。

从组件定义的代码行中可以看到所有的组件都是newtComponent类型:

1

2newtComponent form, btn_ok, btn_cancel, label_username, label_password,

entry_username, entry_password, result;

我们使用一个Form表单将这些组件组合起来:

1

2

3

4newtFormAddComponents(form, label_username, entry_username,

label_password, entry_password,

btn_ok, btn_cancel, result,

NULL);

当执行newtFormRun()时,newt应用将等待用户操作。我们通过exit_status结构体接收用户的操作信息来判断哪个按钮被触发。如果用户触发了Cancel按钮则程序结束。如果触发的为OK按钮,则检测输入的密码是否为123456。如果输入错误,则显示一个错误信息窗口。密码验证通过则显示一个长消息Textbox窗口。

这里我们也可以通过注册回调函数给两个按钮组件,根据哪个回调函数被执行来判断哪个按钮被触发。

newt整体使用非常简单,然而比较遗憾的是,它基本没有文档,最好的参考资料为官方源码中的几个示例:

官方newt库中还提供了Python封装库,名称为snack。具体用法和C库类似,官方也提供了两个示例:

除此之外,newt库中还提供了一个whiptail的命令行程序,用在SHELL脚本中显示对话框。比如,我们在BASH中执行:

1whiptail --yesno "Continue?" 10 50

这将显示如下窗口:

7a45fa7cafc50c23e8eeecd9d3c52691.png

当选择YES按钮时,程序退出码为0,选择NO按钮,程序退出码为1。我们选择YES之后,查看退出码:

1

2[root@centos2 newt]# echo $?

0

具体信息可以参考:

类似的TUI工具还有CDK和dialog。[CDK](Curses Development Kit)是一个程序库,能够链接进我们自己开发的应用程序,dialog为一个命令行程序,与whiptail类似,可以在SHELL脚本中实现TUI界面。它们都是基于ncurses开发的,ncurses是目前最为广泛使用的TUI库。不过它的API过于底层,我们直接使用相对繁琐,对于简单的界面实现,还是推荐使用更为上层的封装库。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
# 课程背景2021年ARM又推出了ARMv9架构,系统软件架构也在悄无声息地发生变化。在这种架构中,强调的是隔离技术,包括资源的隔离、运行时隔离,特权操作系统的权限也变得越来越小…不管您是什么领域,ARM服务器、汽车电子、手机或者是其它设备终端,安全都是其中的一个重要环节。我们常说的安全一般是只网络安全/业务安全/App安全,这些安全依赖的正是操作系统安全,操作系统安全所依赖的就是安全架构技术,在该安全架构中,首当要学习的就是Trustzone/TEE技术。只有设备安全/操作系统安全/APP安全/网络安全/服务器安全整个一条链都安全了,那么你的业务才算得上的安全.不管您是做什么的,您做不做安全或虚拟化,掌握整个系统软件架构也是一件必要的事情。您只有掌握了安全架构,你才具有全局的视野,才能进行全局的软件设计,才称得上架构师。安全不仅仅是架构安全,安全还是一种生态,安全还产生一类标准。安全出现在产品声明周期的任何一个角落,它可能零碎地出现在硬件中、零碎地出现在软件代码中。如果你不了解安全,你可能无法进行优秀的产品设计,你甚至无法去正确的阅读代码。# 课程介绍(1) 讲解ARM最新硬件架构(ARM Core、ARM Architecture)、SOC架构(2) 讲解最新的Trustzone安全架构、TEE架构、Secureboot等(3) 讲解软件组件:TF-A(ATF)、optee_os、Linux Kernel、CA/TA应用程序等,及其交互模型、设计模型(4) 多系统交互代码导读、安全论证实践、CA/TA示例实践、安全业务设计实践(5) 我们学习的是全部硬件、全部系统,软硬结合,或者是大系统的软硬件融合# 课程收益1、安全不再神秘,能cover住全局2、熟悉ARM Architecture架构知识3、熟悉SOC架构知识4、熟悉主流的系统软件框架5、知道多系统之间是如何交互的,也能够进行系统级的设计6、深入了解当前的系统安全架构以及未来安全架构趋势7、熟悉基础的安全业务设计方法8、熟悉系统的启动流程、Secureboot等9、知道Linux Kernel在大系统中的位置,以及与其它系统交互的方法10、熟悉各类标准和规范11、学习资料的获取方法 # 课程大纲《Trustzone/TEE/系统安全开发速成班》 --当前48节课/19小时说明: 本视频会持续更新,购买时请以课程目录为主。本EXCEL一个月更新一次。章节编号课程时常第一章基础和简介1课程介绍 8:332ARM和SOC的架构简介60:13第二章软硬件基础3armv8/armv9基础概念26:204ARMv8/ARMv9的Trustzone技术77:565ARMv7的Trustzone技术8:376安全架构及其未来趋势(FF-A/SPM/CCA)6:417ARMv9 CCA机密计算框架底层核心原理简介20:448ARMv9 RME安全扩展详解61:299ATF Quick Start0161:2710Optee Quick Start49:3411系统软件Quick Start21:0412Secureboot原理深度讲解60:2813Android AVB的介绍26:0914TZC400详解17:5615TZC400代码导读之ATF13:4416RPMB详解30:0617RPMB代码导读之optee14:0318efuse详解12:1919Anti-Rollback的介绍11:33第三章软件架构20TEE的组件介绍67:5921TEE的RPC反向调用31:1422TEE的调度模型21:3223各类标准和规范22:17第四章软件架构(高级)24多系统之间的管理模型(ABI/标准)10:3025多系统之间的调度12:2126多系统之间的中断(不含虚拟化)61:4727多系统之间的中断(虚拟化)6:5728再谈多系统之间的调度(多核多线程)10:3129其它(内存管理/PSCI...)10:12第五章安全应用开发基础30安全应用开发基础5:3731TEE环境:qemu_V8环境的使用4:2032TEE环境:编写一个CA和TA程序11:0433TEE环境:编写漂亮的文档4:1434TEE环境:搭建阅读代码神器opengrok3:2635TEE环境(必看):使用集成好的qemu_v8镜像程序20:2936[CA/TA开发]CA到TA的通信9:1837[CA/TA开发]CA到TA的传参27:1638[CA/TA开发]TEE中的存储系统20:5739[CA/TA开发]TEE中的密码学系统简介12:3740[CA/TA开发]TEE中的密码学系统简介-数字摘要Hash等33:2141[CA/TA开发]TEE中的密码学系统简介-对称密码学算法AES等12:2042[CA/TA开发]TEE中的密码学系统简介-消息摘要算法HMAC等15:4843[CA/TA开发]TEE中的密码学系统简介-非对称密码学算法RSA等7:33第六章安全业务设计高级44Gatekeeper的介绍29:3245keymaster/keymint/keystore/keystore213:2746生物认证(指纹/人脸)13:5747DRM的介绍21:3748TUI介绍17:03总计时统计(分钟)1128:12 说明:本课程会持续更新…
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值