|
This document details how to use the curses library included in VxWorks 6.x in a simple application. It is designed to be used as a primer to using curses, rather than trying to explain everything fully. More information regarding curses can be found on the Internet.
This document uses these abbreviations for paths and commands to describe the VxWorks installation: $WIND_BASE is the Directory of VxWorks install, for example C:/WindRiver/vxworks-6.6; $WIND_CURSES relates to $WIND_BASE/vxworks-6.2/target/usr/apps/samples/UNIX/vi; xxx is the architecture and; yyy the compiler used Libraries The version of curses shipped with VxWorks 6.2 is compiled into 2 libraries: They are found by default at $WIND_CURSES/lib/xxxyyy Rebuilding the Libraries It is possible to rebuild the libraries following a change (such as adding a path to a termcap file in termcap.c) by calling make CPU=xxx TOOL=yyy as applicable to your project in both the following locations from the command line: - $WIND_CURSES/vw_curses/curses
- $WIND_CURSES/vw_curses/termlib
Creating a Workbench Project To use the curses libraries within a workbench RTP project the following properties should be changed (note the forward slashes): - Build Properties > Build Tools > Command > add L$WIND_CURSES /lib/xxxyyy into the box before any "-l" statements.
- Build Properties > Build Macros > Build spec specific settings > LIBS should add -lcurses -ltermlib
- Build Properties > Build Paths > Build spec specific settings > Add both: -I$WIND_CURSES/vw_curses/curses and -I$WIND_CURSES/vw_curses/h
Every source file that wishes to use curses must include curses.h and curses.ext. Usable API Unfortunately, the VxWorks curses doesn’t have the complete API that might be expected. However, it’s perfectly usable, and possibly more suitable for a lighter embedded system that way. This table details of the available commands: | Command | Details | | initscr () | Initializes the terminal in curses mode. To do any screen manipulation using curses package this has to be called first. | | endwin () | Frees the memory taken by curses sub-system and its data structures and puts the terminal back to normal mode. This function must be called after you are done with the curses mode. Otherwise your terminal might behave strangely after the program quits. | | printw () | This function is analogous to normal printf in all respects except that it prints the data on the standard window (called stdscr) at the current (y,x) co-ordinates. | refresh ()
| Dump the contents of stdscr to the screen. | | mvprintw (y, x, string) | Move to (y, x) then print the string. | | move (y, x) | Move the cursor to (y, x). | addch (ch)
| Add a single character ch. | | mvaddch (row,col,ch) | Move to (y, x) then add a single character ch. | | getch () | Get a single character from standard input. | | getyx (stdscr, y, x) | Get the current curser position within stdscr. | | newwin (nlines, ncols, begin_y, begin_x) | Create new window of specified size and initial cursor placement. Return value of type WINDOW * to identify it. | | delwin (WINDOW *win) | Delete the specified window. | | clearok (stdscr, TRUE) | When called with TRUE as argument, the next call to refresh will clear the screen completely and redraw the entire screen from scratch. | | cbreak () | Get input as soon as it is typed, don't wait for an EOL. | | nocbreak () | Wait for an EOL to get input. | | noecho () | Don't echo characters. | | echo () | Do echo characters. | | leaveok (stdscr, TRUE | FALSE) | Leave (TRUE) or don’t leave (FALSE) the cursor wherever the update happens. | | Scrollok (stdscr, TRUE | FALSE) | Controls what happens when the cursor of a window is moved off the edge of the window or scrolling region.
| clear ()
| Clear the screen and send cursor to position (0,0). | | Refresh () | Implement all changes since last refresh. |
Thankfully there is an example of using the curses libraries in an application called twinkle located at $WIND_CURSES\vw_curses\test. This should be able to be compiled easily for anyone new to curses and shows some of the things that are possible. Also included is a vi clone called stevie. This builds into an RTP named vi.vxe in $WIND_BASE\vxworks-6.2\target\usr\root\PENTIUM4diab\bin. Example Code This example uses curses to view an incrementing number and allows the user to quit by pressing 'q' at any time. It is also available as a workbench archive (for registered users) Curses Example Code. 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
/* cursesRtpExample.c - example code to show the curses API */
/* Copyright (c) 2007 Harmonic Software Systems Ltd. */
/* modification history -------------------- 01a,26nov07,hss Created */
/* DESCRIPTION
This example uses curses to view an incrementing number and allows the user to quit by presing 'q' at any time. This code will form an RTP, and therefore the entry point is the main function. */
#ifndef VxWorks #define VxWorks #endif
#include <stdio.h> #include <stdlib.h> #include <curses.h> #include <taskLib.h> #include <string.h> #include "sysLib.h" #include "curses.ext"
/* defines */
#define NCOLS 80 #define TASK_PRIORITY 100 #define TASK_OPTIONS 0 #define TASK_STACK 0x10000 #define WELCOME_START_ROW 0 #define WELCOME_START_COL 2 #define WELCOME_END_ROW 4 #define NUMBER_ROW 10 #define NUMBER_COL 5
#define TERMINAL "nansi"
/* global variables */
int run = 1; /* controls the exit */ int number = 0;
/* functions */
void printWelcome (void); void printNumber (void); void controlTask (void);
/***************************************************************************** * * main - run the RTP * * This function will run the RTP * * RETURNS: N/A * */
int main ( int argc, /* number of arguments */ char * argv[], /* array of arguments */ char * envp[], /* array of environment strings */ void * auxp /* implementation specific auxiliary vector */ ) { /* Initialise the curses */
strcpy(Def_term,TERMINAL); initscr (); clearok (stdscr, TRUE); /* get input as soon as it's typed */ cbreak (); /* Don't wait for EOL to get input */ noecho (); /* Don't echo characters */ leaveok (stdscr, TRUE); /* Leave the cursor where it is */ clear(); /* clear screen */ refresh(); /* refresh screen */
/* Spawn the input task */
if ((taskSpawn ("tControl", TASK_PRIORITY, TASK_OPTIONS, TASK_STACK, (FUNCPTR)controlTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR) { mvprintw (21, 2, "Unable to spawn control task\n"); return; }
/* Print a welcome message */
printWelcome (); refresh();
while (run) { printNumber (); taskDelay (sysClkRateGet ()); }
endwin(); /* End curses mode */ return 0; }
/***************************************************************************** * * printWelcome - display a welcome message * * This function will display some info on the screen. * * RETURNS: N/A * */
void printWelcome (void) { int i;
/* Display some welcome info */
mvprintw (WELCOME_START_ROW, WELCOME_START_COL, "Harmonic Software Systems"); mvprintw ((WELCOME_START_ROW + 2), WELCOME_START_COL, "Press 'q' to exit");
move (WELCOME_END_ROW, 0);
for (i = 0; i < NCOLS; i++) { addch ('-'); } }
/***************************************************************************** * * printNumber - display a message * * This function will display some info on the screen. * * RETURNS: N/A * */
void printNumber (void) { mvprintw (NUMBER_ROW, NUMBER_COL, "Number is now %d", number); refresh (); number++; }
/***************************************************************************** * * controlTask - input to control curses * * This function will take input to allow the user to exit. * * RETURNS: N/A * */
void controlTask (void) { int ch;
while (1) { ch = getch();
if (ch == 'q') { run = 0; clear (); refresh(); break; } } }
|
Running a curses RTP There are multiple ways to run an RTP that uses curses, including using workbench. Using the target shell is possible, and easier using the VxWorks Command shell (entered by typing cmd). From there, rtp exec /path-to/rtpName.vxe will run the RTP. This is a handy way to start any RTP that’s not used within a production environment. Since the RTP must be started form a filesystem, a standalone application may want to include it in ROMFS.
|