|
Volume 3 Issue 6, June 2004 Curses,
Part 2 |
Copyright (C) 2004 by Steve Litt. All rights reserved. Materials from guest authors copyrighted by them and licensed for perpetual use to Linux Productivity Magazine. All rights reserved to the copyright holder, except for items specifically marked otherwise (certain free software source code, GNU/GPL, etc.). All material herein provided "As-Is". User assumes all risk and responsibility for any outcome.
|
|
|
and Rapid Learning: Secret Weapon of the Successful Technologist by Steve Litt |
[ Troubleshooters.Com
| Back Issues |Troubleshooting Professional Magazine
]
|
|
CONTENTS
| News Mag |
Submission URL or
Email
address |
Comments |
| Slashdot |
http://slashdot.org/submit.pl |
Just fill in the short form. |
| LinuxToday |
http://linuxtoday.com/contribute.php3 |
Just fill in the short form. |
| Linux Weekly News |
lwn@lwn.net |
Just tell them the URL, why you like it. |
| NewsForge |
webmaster@linux.com |
Just tell them the URL, why you like it. |
| VarLinux |
http://www.varlinux.org/vlox/html/modules/news/submit.php |
Just fill in the short form. |
| LinuxInsider.Com, Newsfactor Network |
http://www.newsfactor.com/perl/contact_form.pl?to=contact |
Just tell them the URL, why you like it. |
| The Linux Knowledge Portal |
webmaster@linux-knowledge-portal.org |
Just tell them the URL, why you like it. |
| OS News |
http://www.osnews.com/submit.php |
Just tell them the URL, why you like it. |
| DesktopLinux |
http://www.desktoplinux.com/cgi-bin/news_post.cgi |
Only for LPM issues involving the Linux desktop,
not
for programming or server issues. |
"GNU/Linux" is probably the most accurate moniker one can give to this operating system. Please be aware that in all of Troubleshooters.Com, when I say "Linux" I really mean "GNU/Linux". I completely believe that without the GNU project, without the GNU Manifesto and the GNU/GPL license it spawned, the operating system the press calls "Linux" never would have happened.
I'm part of the press and there are times when it's easier to say "Linux" than explain to certain audiences that "GNU/Linux" is the same as what the press calls "Linux". So I abbreviate. Additionally, I abbreviate in the same way one might abbreviate the name of a multi-partner law firm. But make no mistake about it. In any article in Troubleshooting Professional Magazine, in the whole of Troubleshooters.Com, and even in the technical books I write, when I say "Linux", I mean "GNU/Linux".
There are those who think FSF is making too big a deal of this.
Nothing
could be farther from the truth. The GNU General Public License,
combined
with Richard Stallman's GNU Manifesto and the resulting GNU-GPL
License,
are the only reason we can enjoy this wonderful alternative to
proprietary
operating systems, and the only reason proprietary operating systems
aren't
even more flaky than they are now.
For practical purposes, the license requirements of "free software" and
"open
source" are almost identical. Generally speaking, a license that
complies
with one complies with the other. The difference between these two is a
difference
in philosophy. The "free software" crowd believes the most important
aspect
is freedom. The "open source" crowd believes the most important aspect
is
the practical marketplace advantage that freedom produces.
I think they're both right. I wouldn't use the software without the
freedom
guaranteeing me the right to improve the software, and the guarantee
that
my improvements will not later be withheld from me. Freedom is
essential.
And so are the practical benefits. Because tens of thousands of
programmers
feel the way I do, huge amounts of free software/open source is
available,
and its quality exceeds that of most proprietary software.
In summary, I use the terms "Linux" and "GNU/Linux" interchangably,
with
the former being an abbreviation for the latter. I usually use the
terms
"free software" and "open source" interchangably, as from a licensing
perspective
they're very similar. Occasionally I'll prefer one or the other
depending
if I'm writing about freedom, or business advantage.
| Functionality |
Typical keysrokes |
What it does |
| Pick |
Enter, Ctrl+P |
Terminates the picklist and
returns to the calling subroutine with the unique identifier of the
item that was highlighted when the user chose |
| Add |
Insert, Ctrl+A |
The picklist calls a blank form
to create a new item in the list or table under consideration. When the
user terminates that form, if the user did not bail, then the newly
created record is visible on the picklist |
| Change |
Enter, Ctrl+C, Ctrl+M, Ctrl+E |
Change, modify, edit are
synonyms. The picklist calls a form, with the current contents of the
highlighted record already in place. The user can then modify the
record's data, and submit it to the database or file, returning
afterward back to the calling picklist. |
| Delete |
Del, Backspace, Ctrl+D |
The picklist calls a read only
form containing data from the highlighted record. The user can then
choose to continue with the deletion or bail from the deletion. Either
way control returns to the picklist, but if the user bails, the record
is not deleted from the database. |
| Bail |
Esc |
Terminate the picklist, and
return to the calling subroutine with an identifier indicating that the
user declined to choose. The calling subroutine typically then acts as
if the user had never gone into the picklist. |
| Refresh |
Ctrl+L |
Refresh the list of records on
the picklist. Some picklist tools are incapable of putting a newly
added record into the list, so the user must refresh the list. This is
typically a slow operation, so it's better if the picklist and its
associated routines refreshes the list. However, in a multiuser
environment, refreshing might still be necessary because other users
might have inserted or deleted records. |
| Data |
Program |
|
Anderson |
|
#include <curses.h> /* Necessary for all Curses programs */ |
rm -f ./a.out |

rm -f ./a.out |

/* #DEFINES AND ENUMS {{{ */
|
:h foldOne thing should be said right now -- this program has some design and philosophical errors. Turning it into a true data driven tool, in which all picklist configuration could be accomplished in configuration files rather than code changes, would require some more work. For instance, color pair constants shouldn't have been defined by color name, but instead by function name -- BORDERPAIR, UIPAIR, UIHIGHLIGHTPAIR and the like. And they should be variables so that they don't conflict with the application's color pair constants. The picklist tool would then contain a color string to color constant translation table so that string representations of a color, read in from a config file, could be converted to the number Curses uses for that color.
struct PICKINFO /*{{{*/ |
| PICKINFO
element |
What's
stored in the element |
| ROWSINFO |
Pointer to a struct ROWSINFO, which contains
everything about the rows of data presented for possible selection. |
| KEYSTROKES |
Pointer to a struct KEYSTROKES, which
contains everything about possible keystrokes, including keystroke
ascii codes, string representation of keystroke names, and for each
possible action of the picklist, the keystrokes that trigger such
action. |
| SUBROUTINES |
A pointer to the subroutines to
be run upon the ADD, CHANGE or DELETE actions
-- typically a form. Note that a picklist could also simply return the
action chosen by the user, in which case the next loop iteration would
run the form on the record selected by the user. |
| WINDOWS |
The
layout of the picklist -- its height, width, as well as the dimensions
of the surrounding border window. Color scheme, and prompts location. |
| actionNames |
Strings representing PICK, ADD,
CHANGE, DELETE, BAIL or REFRESH. |
struct WINDOWS /*{{{*/
|
struct KEYSTROKES /*{{{*/ |
struct ROWSINFO /*{{{*/
|
struct ROWINFO /*{{{*/
|
| struct |
Manipulating
function |
Description |
| struct ROWINFO |
struct ROWINFO * newRowInfo( |
This allocates all storage for a
new row. First it allocates storage for the struct ROWINFO itself, and then
it allocates strings equal to displayString,
sortString and uid, leaving the original arguments untouched and
unassigned. If sortPointsToDisplay=True,
it does not make an allocated copy of sortString. |
void freeRowInfo(struct ROWINFO * rowInfo); |
This frees the displayString and uid,
pointers, and also the ,
sortString pointer if sortPointsToDisplay=false.
It then deallocates the struct
ROWINFO itself. |
|
void testRowInfo(); |
This is a loop to repeatedly
runs newRowInfo() and freeRowInfo() in order to
detect memory leak and other problems. Ideally, you should look at the
memory display of the Linux top
command. If memory usage continuously rises, you have a memory leak. |
|
| struct ROWSINFO |
struct ROWSINFO * newRowsInfo(long increase_maxrows_by); |
This allocates the ROWSINFO structure and
initializes rowsInfo, maxrows and increase_maxrows_by. It does
not allocate storage for rows
and headNode, but instead
sets them to NULL. |
void freeRowsInfo(struct ROWSINFO *rowsInfo); |
This deallocates EVERYTHING in
the structure ROWSINFO,
including any allocated rows. At this time it doesn't deallocate any ROWNODE structures because
those structures aren't yet incorporated into the program, but exist as
stub. |
|
void testRowInfo(); |
This operates a loop that
repeatedly:
|
|
void addRow( |
This calls newRow to allocate and
configure a new ROWINFO
pointer, and also updates the numrows, maxrows |
int runMenu( /*{{{*/ |
#include <form.h> |
rm -f ./a.outWhen you run the program, the result looks like this:
gcc -Wall -lncurses -lform form.c
./a.out

#include <form.h> |
rm -f ./a.outThe result is as follows:
gcc -Wall -lncurses -lform form.c
./a.out

#include <form.h> |
rm -f ./a.outThe result is as follows:
gcc -Wall -lncurses -lform form.c
./a.out

#include <ncurses.h> |