henkp@ruuinf.cs.ruu.nl (Henk P. Penning) (05/07/90)
I've written some software which gives (almost) full curses functionality to perl. It consists of two parts. First, a perl library 'cterm.pl' which defines (in perl) all curses functions and constants on your system. Second, a C program 'cterm' which runs as a separate process and controls the terminal (window). Subroutines in cterm.pl (like &addstr($str)) send commands through a pipe to cterm. Cterm updates the terminal. In some cases (like getch()), cterm passes results back to to the perl application through an other pipe. It works for me, maybe it works for you too. The following perl program should put an informative message on the middle of your screen. do 'cterm.pl' || die "$0 can't include cterm.pl\n" ; &startCterm(@ARGV) ; &initscr ; &nonl ; &cbreak ; &noecho ; $japh = 'just another perl hacker' ; &mvaddstr(int($LINES/2),int(($COLS-length($japh))/2),$japh) ; &mvaddstr($LINES-1,0,'hit any key to continue ') ; &refresh ; &getchR ; &clear ; &move(0,0) ; &refresh() ; &endwin ; &finishCterm ; Since there exist many versions of curses, I've tried to make the software adaptable to local circumstances. SYSV systems seem to have a richer curses than Suns or BSD systems, but cterm should work on both. In this message I've included the cterm man-page which tells all about usage and installation. Read it and, if you are still interested, drop me (henkp@cs.ruu.nl) a message and I'll mail you the stuff (50K). === HenkP === Henk P. Penning, Dept of Computer Science, Utrecht University. Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. Telephone: +31-30-534106 e-mail : henkp@cs.ruu.nl (uucp to hp4nl!ruuinf!henkp) ---- snip ---- snip ---- snip ---- snip ---- snip ---- snip ---- .TH CTERM 1 "" "Department of Computer Science, RUU" .SH NAME cterm, cterm.pl \- curses terminal emulation (for perl) .SH SYNOPSIS .B cterm .I in out [ .I options ] [ .I logfile [ .I loglevel ] ] .B cterm.pl .SH DESCRIPTION .PP .B Cterm emulates a curses terminal. On filedescriptor .I in it expects curses functions+arguments in the format described below. On filedescriptor .IR out, some functions (like getch()) pass back results. Cterm should only be forked by other programs after the proper pipes have been set up. There are currently no documented .I options (see also the section on undocumented features). As optional arguments to cterm, the name of a .I logfile and a .I loglevel may be specified. Loglevel 0 only logs strings provided by the application through the curses extension .BR ctermlog(str) . Loglevel 1 logs all curses functions, arguments and results handled by cterm. Loglevel 2 shows even more intestines. Default is loglevel 0. Cterm exits in a controlled fashion when it receives signal SIGINT or SIGPIPE. .B Cterm.pl is a library of perl subroutines that provides easy interaction with cterm. Cterm.pl defines perl-counterparts for almost all curses functions, tables with curses defined constants, and subroutines for starting and finishing cterm. .SH Communication between cterm.pl and cterm The cterm.pl subroutine .B &startCterm() sets up two (pair of) pipes, forks and execs cterm. In the parent (perl application) STDIN and STDOUT are redirected to the pipes. In the child (cterm) the pipes are connected to filedescriptors .I out and .IR in . Subroutine .B &finishCterm() finishes cterm and restores STDIN and STDOUT again. For the pupose of communication between cterm.pl and cterm, each curses function supported in the interface is given a number. A curses routine in cterm.pl prints this number on STDOUT followed by its parameters, each on a new line. When results are required they are read in from STDIN and returned to the caller. Cterm reads the numbers from .I in and calls appropriate functions which in turn read arguments from .I in and perform the required curses functions. Results are written to .IR out . Cterm always flushes .I out after writing results to it. Cterm.pl can be used with $|=0 in applications. All curses subroutines in cterm.pl that need to return results, flush STDOUT before reading the results from STDIN. This implies for instance that the screen always gets up to date when user input is requested. A curses extension .B frefresh (flush/refresh) does a normal refresh but also flushes STDOUT when .B $flushOn is set. If you always use frefresh you can set $flushOn in parts of the application where you are willing to pay the price for a higher flush-rate in order to get a more accurate presentation. With subroutine .B &curFlush() the user can actively flush STDOUT. In order to access curses defined constants, cterm.pl defines two tables: .B %curcon and .BR %curkey . Associative array %curcon contains entries like ('KEY_UP',259) and ('A_BLINK',1024), so curses constants (as strings) map to their value. Associative array %curkey contains the inverse of %curcon restricted to KEY-codes. So, for example, $curkey{259} = 'KEY_UP' if $curcon{'KEY_UP'} = 259. The contents of %curcon and %curkey differ from system to system. They are created during installation. The KEY-associations (KEY_TAB,9) and (KEY_RET,13) are always defined. Variables .BR $LINES , .BR $COLS , .B $stdscr and .B $curscr are set by &initscr. .SH Arguments and results, representation Like in curses, in cterm.pl characters are really integers. So, for instance, .B &addch(c) should be provided with an integer and .B &getch supplies one. Windows are really pointers in curses. Since mixing pointers and integers is potentially dangerous (espcially printing and reading them in again) an indirection is introduced. Cterm stores the result of curses functions returning windows in a table and returns the index in the table to cterm.pl. When curses returns window NULL, cterm returns -1. Subroutine .B &delwin(win) deletes the window and the entry in the table. Subroutine .B &initscr clears the table and sets variables .B $stdscr and .BR $curscr. String arguments are printed on STDOUT as they are handed to cterm.pl. Things break if a string contains a newline character because cterm will get out of sync. No mechanism was implemented to check and/or repair synchronization. Curses subroutines in cterm.pl return values by result and not by modifying parameters. The 'return-parameters' may be omitted in the call. This implies that for instance .B getyx should be called like '($a,$b) = &getyx($win)', although in C one would write 'getyx(win,a,b)'. The same holds for the .B getstr function family. Curses subroutines in cterm.pl don't check their parameters, they just pass 'em on. .SH Using cterm Cterm is started up with .B &startCterm() and finished with .BR &finishCterm . In addition to proper values for .I in and .IR out , all arguments of startCterm are passed as arguments to the exec'ed cterm. So, if cterm logging is required, the name of the logfile should be passed as an argument to startCterm. If cterm should log internals too, an integer loglevel greater than 0 should be passed as well. Variable .B $ctermPid holds the pid of the forked cterm process. Since cterm only performs curses calls, one usually has to go through the customary proceedings: &initscr ; &nonl ; &cbreak ; &noecho. Subroutine endwin() should be called before finishing cterm. .br If the perl application does not call finishCterm before exit'ing, as in the case of a runtime error, cterm can't reset the terminal and hangs. This is a nuisance. When .B &safeCterm is called before &startCterm, cterm will be exec'ed in the parent process. This has the advantage that cterm wil always cleanup when the perl application suddenly dies. The disadvantage is that the application has no control over the terminal after &finishCterm because the shell takes over when cterm exits. It should be used while developing that part of the application that runs between &startCterm and &finishCterm. Subroutine .B ch2str(c) takes an integer argument .I c and, depending on its value, returns a string consisting of the correspondig ASCII character, or a string like 'KEY_LEFT' or 'KEY_HOME' if .I c is a KEY-code in curses, or the argument otherwise. The subroutine .B getchint() is defined as .BR ch2str(&getch()) . The KEY-associations (KEY_TAB,9) and (KEY_RET,13) are always defined. Subroutine .B clrreg(top,bot) clears the screen from lines .I top to .IR bot . Subroutine .B wclrreg(win,top,bot) clears window .I win from .I top to .IR bot . Subroutine .B ctermlog(str) adds string .I str to the cterm logfile if one was specified in &startCterm(). Associative array .B %curcon maps curses constants (as strings) to their (integer) values. The contents of %curcon is determined by the installer. Associative array .B %curkey maps curses KEY-codes (as strings) to their integer values. It is the inverse of %curcon restricted to keys matching /^KEY/. The contents of %curkey is determined by the installer. Associative array .B %curfun maps curses functions (as strings) in the cterm interface to a string listing their parameters and results (if any). Table %curfun can be used to determine if a curses function is available. The installer determines which functions are supported in the interface. Function .B edit(str,curpos,y,x,xlen,rep) returns .B (str,quitkey) and constitutes a local edit mode of cterm. The subroutine allows one to edit a string (initially .IR str ). It shows (part of) the string in an edit window in line .I y using .I xlen columns, starting from column .IR x . The initial cursor position in .I str is .IR curpos . Edit-mode is left and the resulting string returned to the caller when a 'special' is typed in. The set of 'special' characters can be specified as follows. Function .B editreset() clears the set. Function .B editq(chint) adds a character (supply an int) to the set. The 'special' character (really an int) which caused edit() to leave is returned to the caller too. .br Edit facilities are limited. Arrow-left and arrow-right work if keypad is enabled. Typing in 'Kill' (as defined by curses killchar()) will delete the character pointed to by the cursor. Typing in 'Erase' (as defined by curses erasechar()) will delete the character left of the cursor. When the cursor points to the first character in .I str and 'Erase' is typed in, .I str will be swapped with an initially empty save-buffer. It can be used to present a user with a default wich he/she can edit or discard by typing 'Erase'. Printable ASCII characters are inserted. All others are rejected. .br Argument .I rep must be a string of four characters. They are used by edit to indicate which part of .I str is shown on the screen. One of the first two characters in .I rep is shown in the first column of the edit window. One of the last two characters in .I rep is shown in the last column of the edit window. Edit can only use .I xlen-2 columns to present (part of) .IR str . For the sake of simplicity, let us assume that .IR rep ='[<>]'. If lenght(\fIstr\fP)<=\fIxlen-2\fP, then .I str is shown on the screen like '[\fIstr\fP]'. If lenght(\fIstr\fP)>\fIxlen-2\fP, then only a substring .I sub of .I str can be shown on the screen. If .I sub is a prefix of .I str then it is shown like '[\fIsub\fP>'. If it is a suffix it is shown like '<\fIsub\fP]'. It is shown like '<\fIsub\fP>' otherwise. .br The cursor position will be held at the middle of the edit window if .I sub is neither a prefix nor a suffix of .IR str . .br Subroutine .B wedit(win,str,curpos,y,x,xlen,rep) does edit() in a window. Subroutine .B editreset() clears the set of 'special' characters (see edit()). Subroutine .B editq(chint) adds a character (supply an int) .I chint to the set of 'special' characters (see edit()). Subroutine .B endwin() flushes STDOUT. Subroutine .B frefresh() does a refresh. STDOUT is flushed if .B $flushOn is set. Function .B getstr(str) should be called like '$str = &getstr', mvgetstr(str) should be called like '$str = &mvgetstr($y,$x)', and mvwgetstr, wgetstr likewise. Function .B getyx should be called like '($a,$b) = &getyx($win)'. Function .B getchR() and .B wgetchR(win) act like getch() but redraw the screen if ^L is entered. They do getch's until a non-^L is found. Subroutine .B initscr() sets $LINES and $COLS and forgets about all windows except stdscr and curscr. Subroutine .B refresh() does not flush STDOUT (see also &frefresh()). Subroutine .B show(str,curpos,y,x,xlen,rep) shows .I str on the screen like edit initially would. It is handy in applications that are to be independent of the value of COLS. .br Subroutine .B wshow(win,str,curpos,y,x,xlen,rep) does show() in a window. .SH Omissions and limitations Implementations of curses differ a lot. A few curses functions that are available on some systems are not supported in this distribution. Some were documented as obsolete, some are meaningless in this application. The ones which take a variable number of arguments don't fit the interface model and can be done in perl more easily anyway. Some are left out because the author was unable to understand what they were supposed to do. Use %curfun to find out which curses functions are supported in the interface. Which constants go in %curcon and %curkey is determined by the installer. As distributed, the size of the window table is 100. The size of the set of 'special' characters for edit() is 1000. Strings passed to cterm shouldn't be larger than 10K. .SH Installation Edit the 'Makefile' in the source directory. Define BINDIR to be a directory were exec usually looks for executables. Define PERLLIB to be a directory where perl's do-statement looks for libraries to include. The Makefile variables EDIT_LEFT, EDIT_RIGHT and BEEP are passed to edit.c. They are used in edit(). When user input equals EDIT_LEFT (EDIT_RIGHT), edit() moves the cursor left (right). If your curses recognizes arrow-keys, define EDIT_LEFT (EDIT_RIGHT) to whatever curses getch() returns if the user types in arrow-left (arrow-right). If not, define EDIT_LEFT as 2 (^B for Back) and EDIT_RIGHT as 6 (^F for Forward). You may also comment them out entirely. .br BEEP is the function that is used to signal edit errors to the user. Set it to 'beep' (sound bell) if your curses supports it. Set it to 'mybeep' if you have nothing better. It writes ^G to stderr. You may want to change the implementation of 'mybeep' in cursesX.c. Function 'nobeep' is defined and does nothing. It is used if you don't define BEEP. Run 'make' to generate the necessary stuff. Don't worry about warnings from 'curcon.mk'. They simply mean that not all the curses constants suggested in 'curcon.in' are available on your system. You might want to try the perl programs 'try1' and 'try2' before installing. Arguments to try1 and try2 are passed to startCterm and thus to cterm. Running 'make install' will copy the stuff to the designated directories. Running 'make clean' will remove temporaries. Running 'make realclean' will remove all generated stuff. The author has tried to make the system adaptable to local conditions. There are two files that the installer can modify. .br The file .B cdefs.in is the input for cdefs.mk which generates the interface between cterm and cterm.pl: cdefs.c and cdefs.pl. It contains one line for each curses function which is supported in the interface. It specifies the name of the function and the parameters that are to be passed from cterm.pl to cterm, and in some cases the results that are to be passed back. If your curses doesn't support some of them, simply comment them out ('#' in the first column). If there is a problem with something in the 'extensions' or 'extra's', please contact the author. Create your own minicurses if you think it is all too baroque. The file .B cdefs.in.SUN contains a stripped version of cdefs.in that runs on SunOs.4.0.3. .br The file .B curcon.in is the input for curcon.mk which generates curcon.c which defines th contents of %curcon and %curkey in file curcon.pl. Curcon.in is a wishlist. Comment out constants that are not defined and add others that are. As distributed, 10 function keys are defined in the way they should be on some systems. If you want to add functionality, define more functions in cdefs.in. Look at other functions and cdefs.types to see how parameters and results are to be specified. If you define a function, add an implementation for it in cursesX.c. For an example, look at .IR clrreg . Function initscr() calls initCursesX(). This is the place to put initialisation stuff for curses additions. .SH "Author's note" I developed cterm as part of a perl project called 'jinx'. Jinx is a simple, not-quite-relational database system. It seemed more practical to have a weak implementation of 'full curses' in stead of a strong, tested implementation of an ad hoc subset of curses. In jinx I have sofar used only some of the curses facilities. The newwin and subwin stuff has not been tried a lot. I've never tried to set up a multi-terminal application. I want to get it right though, so complaints will be honored. .br For the future I have a wishlist. I would like to also have sockets for communication available. I have never used sockets before so I don't see any problems. A simple synchronisation mechanism would be easy to implement, but I never have problems in that area. I guess I don't know how serious the newlines-in-strings problem is. It should be possible to tell cterm how to handle signals while it runs. Cterm should more often be able to reset the terminal. .br Thanks go to Piet van Oostrum (piet@cs.ruu.nl) for his harsh criticism and willingness to discuss technicalities. .SH Undocumented features If you supply option .BR -X , typing ^X to getchR (and wgetchR) will get you IO statistics in line 0. Use it to see how much setting $flushOn or $| are costing you in context switches. The curses extension quitcterm makes cterm quit. It is used by finishCterm. .SH AUTHOR Henk P. Penning (henkp@cs.ruu.nl), Department of Computer Science, Utrecht University, the Netherlands. -- Henk P. Penning, Dept of Computer Science, Utrecht University. Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. Telephone: +31-30-534106 e-mail : henkp@cs.ruu.nl (uucp to hp4nl!ruuinf!henkp)
henkp@ruuinf.cs.ruu.nl (Henk P. Penning) (06/15/90)
Recently I posted the man page of my cterm software. The package allows (almost) full curses functionality in Perl applications. No changes to Perl are needed (of course). The curses stuff is handled in a separate, forked process. Some 20 people asked for the software. I've received no complaints, so I think I can post the package now. Here it is. I've changed one thing since the posting of the man page, The 'no-newlines-in-strings' constraint is relaxed to 'no-$;-in-strings'. Also I have learned that ATT-curses (which is much better than BSD-curses) is available on SUNs if you use the SYSV C compiler (/usr/5bin/cc). The man page is changed accordingly. The software is ftp'able from sol.cs.ruu.nl (131.211.80.5) in file 'pub/UNIX/cterm.shar.Z'. You can also send a message to 'mail-server@cs.ruu.nl' (or hp4nl!ruuinf!mail-server) with the body 'send UNIX/cterm.shar.Z'. The UUEncoded file will be mailed to you. === HenkP === Henk P. Penning, Dept of Computer Science, Utrecht University. Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. Telephone: +31-30-534106 e-mail : henkp@cs.ruu.nl (uucp to hp4nl!ruuinf!henkp) #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: Makefile cdefs.in cdefs.in.SUN cdefs.mk cdefs.types # cterm.1 cterm.c cterm.pl curcon.in curcon.mk cursesX.c cursesX.h # defs.h edit.c try1 try2 # Wrapped by henkp@ruuinf on Thu May 17 00:53:20 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(1490 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# names of programs used and compiler flags X XCC=gcc XCFLAGS=-O XLFLAGS=-lcurses XNROFF=nroff XTROFF=lroff XPERL=perl X X# directories where the stuff gets installed X XBINDIR=/usr/staff/bin XBINMODE=755 XPERLLIB=/usr/staff/lib/nrex XLIBMODE=755 X X# constants used by edit.c X XEDIT_RIGHT=-DEDIT_RIGHT=KEY_RIGHT XEDIT_LEFT=-DEDIT_LEFT=KEY_LEFT XBEEP=-DBEEP=beep X X# no editing beyond this line X XPLS=cterm.pl cdefs.pl curcon.pl XOBJ=cterm.o cursesX.o cdefs.o edit.o X Xall: cterm curcon.pl Xcterm: cterm.o cursesX.o edit.o cdefs.o X ${CC} ${CFLAGS} -o cterm cterm.o cursesX.o edit.o cdefs.o ${LFLAGS} Xcterm.o: cterm.c defs.h X ${CC} ${CFLAGS} -c cterm.c XcursesX.o: cursesX.c cursesX.h defs.h X ${CC} ${CFLAGS} -c cursesX.c Xcdefs.o: cdefs.c cursesX.h defs.h X ${CC} ${CFLAGS} -c cdefs.c Xedit.o: edit.c defs.h X ${CC} ${CFLAGS} ${EDIT_RIGHT} ${EDIT_LEFT} ${BEEP} -c edit.c Xcdefs.c: cdefs.in X ${PERL} cdefs.mk Xcurcon.pl: curcon X ./curcon > curcon.pl Xcurcon: curcon.c X ${CC} ${CFLAGS} -o curcon curcon.c Xcurcon.c: curcon.in X ${PERL} curcon.mk Xcterm.1.nr: cterm.1 X ${NROFF} -man cterm.1 > cterm.1.nr Xcterm.1.tr: cterm.1 X ${TROFF} -man cterm.1 > cterm.1.tr Xinstall: all X cp cterm ${BINDIR} X chmod ${BINMODE} ${BINDIR}/cterm X cp ${PLS} ${PERLLIB} X cd ${PERLLIB} ; chmod ${LIBMODE} ${PLS} X @echo 'install man page by hand' Xman: cterm.1.tr cterm.1.nr Xclean: X rm -f ${OBJ} core cdefs.c curcon.c curcon Xrealclean: clean X rm -f cterm cdefs.pl curcon.pl cterm.1.nr cterm.1.tr Xshar: realclean X rm -f cterm.shar X shar -o cterm.shar * END_OF_FILE if test 1490 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'cdefs.in' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cdefs.in'\" else echo shar: Extracting \"'cdefs.in'\" \(2563 characters\) sed "s/^X//" >'cdefs.in' <<'END_OF_FILE' X# BEGIN unsupported X# delay_output ms X# del_term X# gettmode X# mvprintw X# mvscanw X# mvwprintw X# mvwscanw X# newterm X# printw X# putp X# scanw X# setterm X# setupterm X# set_term X# set_curterm X# tgetent X# tgetflag X# tgetnum X# tgetstr X# tgoto X# tparm X# tputs X# traceoff X# traceon X# vidattr X# vidputs X# END unsupported X X# BEGIN extensions XgetLINES RETURN resint XgetCOLS RETURN resint Xedit str curpos y x xlen rep RETURN str resint Xwedit win str curpos y x xlen rep RETURN str resint Xshow str curpos y x xlen rep Xwshow win str curpos y x xlen rep Xeditq chint Xeditreset Xctermlog str Xquitcterm FLUSH X# END extensions X X# BEGIN extra's XgetchR RETURN resint XwgetchR win RETURN resint Xclrreg top bot Xwclrreg win top bot X# END extra's X X# BEGIN curses Xaddch ch Xaddstr str Xattroff attrs Xattron attrs Xattrset attrs Xbaudrate RETURN resint Xbeep Xbox win vert hor Xcbreak Xclear Xclearok win flag Xclrtobot Xclrtoeol Xdelch Xdeleteln Xdelwin delw Xdoupdate Xdraino ms Xecho Xendwin FLUSH Xerase Xerasechar RETURN resint Xfixterm Xflash Xflushinp Xgetch RETURN resint Xgetstr &str RETURN str Xgetyx win &y &x RETURN y x Xhas_ic RETURN resint Xhas_il RETURN resint Xidlok win flag Xinch RETURN resint Xinitscr Xinsch ch Xinsertln Xintrflush win flag Xkeypad win flag Xkillchar RETURN resint Xleaveok win flag Xlongname RETURN resstr Xmeta win flag RETURN resint Xmove y x Xmvaddch y x ch Xmvaddstr y x str Xmvcur oldrow oldcol newrow newcol Xmvdelch y x Xmvgetch y x RETURN resint Xmvgetstr y x &str RETURN str Xmvinch y x RETURN resint Xmvinsch y x ch Xmvwaddch win y x ch Xmvwaddstr win y x str Xmvwdelch win y x Xmvwgetch win y x RETURN resint Xmvwgetstr win y x &str RETURN str Xmvwin win y x Xmvwinch win y x RETURN resint Xmvwinsch win y x ch Xnapms ms Xnewpad num_lines num_cols RETURN reswin Xnewwin num_lines num_cols y x RETURN reswin Xnl Xnocbreak Xnodelay win flag Xnoecho Xnonl Xnoraw Xoverlay win1 win2 Xoverwrite win1 win2 Xpnoutrefresh pad pminrow pmincol sminrow smincol smaxrow smaxcol Xprefresh pad pminrow pmincol sminrow smincol smaxrow smaxcol Xraw Xrefresh Xresetterm Xresetty Xsaveterm Xsavetty Xscroll win Xscrollok win flag Xsetscrreg top bot Xstandend Xstandout Xsubwin win num_lines num_cols y x RETURN reswin Xtouchwin win Xtypeahead fd Xunctrl chint RETURN resstr Xwaddch win ch Xwaddstr win str Xwattroff win attrs Xwattron win attrs Xwattrset win attrs Xwclear win Xwclrtobot win Xwclrtoeol win Xwdelch win Xwdeleteln win Xwerase win Xwgetch win RETURN resint Xwgetstr win &str RETURN str Xwinch win RETURN resint Xwinsch win ch Xwinsertln win Xwmove win y x Xwnoutrefresh win Xwrefresh win Xwsetscrreg win top bot Xwstandend win Xwstandout win X# END curses END_OF_FILE if test 2563 -ne `wc -c <'cdefs.in'`; then echo shar: \"'cdefs.in'\" unpacked with wrong size! fi # end of 'cdefs.in' fi if test -f 'cdefs.in.SUN' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cdefs.in.SUN'\" else echo shar: Extracting \"'cdefs.in.SUN'\" \(2608 characters\) sed "s/^X//" >'cdefs.in.SUN' <<'END_OF_FILE' X# BEGIN unsupported X# delay_output ms X# del_term X# gettmode X# mvprintw X# mvscanw X# mvwprintw X# mvwscanw X# newterm X# printw X# putp X# scanw X# setterm X# setupterm X# set_term X# set_curterm X# tgetent X# tgetflag X# tgetnum X# tgetstr X# tgoto X# tparm X# tputs X# traceoff X# traceon X# vidattr X# vidputs X# END unsupported X X# BEGIN extensions XgetLINES RETURN resint XgetCOLS RETURN resint Xedit str curpos y x xlen rep RETURN str resint Xwedit win str curpos y x xlen rep RETURN str resint Xshow str curpos y x xlen rep Xwshow win str curpos y x xlen rep Xeditq chint Xeditreset Xctermlog str Xquitcterm FLUSH X# END extensions X X# BEGIN extra's XgetchR RETURN resint XwgetchR win RETURN resint Xclrreg top bot Xwclrreg win top bot X# END extra's X X# BEGIN curses Xaddch ch Xaddstr str X# attroff attrs X# attron attrs X# attrset attrs Xbaudrate RETURN resint X# beeb Xbox win vert hor Xcbreak Xclear Xclearok win flag Xclrtobot Xclrtoeol Xdelch Xdeleteln Xdelwin delw X# doupdate X# draino ms Xecho Xendwin FLUSH Xerase Xerasechar RETURN resint X# fixterm X# flash Xgetch RETURN resint Xgetstr &str RETURN str Xgetyx win &y &x RETURN y x X# has_ic RETURN resint X# has_il RETURN resint Xidlok win flag Xinch RETURN resint Xinitscr Xinsch ch Xinsertln X# intrflush win flag X# keypad win flag Xkillchar RETURN resint Xleaveok win flag Xlongname RETURN resstr X# meta win flag RETURN resint Xmove y x Xmvaddch y x ch Xmvaddstr y x str Xmvcur oldrow oldcol newrow newcol Xmvdelch y x Xmvgetch y x RETURN resint Xmvgetstr y x &str RETURN str Xmvinch y x RETURN resint Xmvinsch y x ch Xmvwaddch win y x ch Xmvwaddstr win y x str Xmvwdelch win y x Xmvwgetch win y x RETURN resint Xmvwgetstr win y x &str RETURN str Xmvwin win y x Xmvwinch win y x RETURN resint Xmvwinsch win y x ch X# napms ms X# newpad num_lines num_cols RETURN reswin Xnewwin num_lines num_cols y x RETURN reswin Xnl Xnocbreak X# nodelay win flag Xnoecho Xnonl Xnoraw Xoverlay win1 win2 Xoverwrite win1 win2 X# pnoutrefresh pad pminrow pmincol sminrow smincol smaxrow smaxcol X# prefresh pad pminrow pmincol sminrow smincol smaxrow smaxcol Xraw Xrefresh X# resetterm Xresetty X# saveterm Xsavetty Xscroll win Xscrollok win flag X# setscrreg top bot Xstandend Xstandout Xsubwin win num_lines num_cols y x RETURN reswin Xtouchwin win X# typeahead fd Xunctrl chint RETURN resstr Xwaddch win ch Xwaddstr win str X# wattroff win attrs X# wattron win attrs X# wattrset win attrs Xwclear win Xwclrtobot win Xwclrtoeol win Xwdelch win Xwdeleteln win Xwerase win Xwgetch win RETURN resint Xwgetstr win &str RETURN str Xwinch win RETURN resint Xwinsch win ch Xwinsertln win Xwmove win y x X# wnoutrefresh win Xwrefresh win X# wsetscrreg win top bot Xwstandend win Xwstandout win X# END curses END_OF_FILE if test 2608 -ne `wc -c <'cdefs.in.SUN'`; then echo shar: \"'cdefs.in.SUN'\" unpacked with wrong size! fi # end of 'cdefs.in.SUN' fi if test -f 'cdefs.mk' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cdefs.mk'\" else echo shar: Extracting \"'cdefs.mk'\" \(4900 characters\) sed "s/^X//" >'cdefs.mk' <<'END_OF_FILE' X#! /local/bin/perl X Xdo 'cdefs.types' ; X Xunlink('cdefs.c') ; Xunlink('cdefs.pl') ; Xopen(STDIN,'cdefs.in') || die 'can\'t open cdefs.in' ; Xopen(C,'>cdefs.c') || die 'can\'t write cdefs.c' ; Xopen(P,'>cdefs.pl') || die 'can\'t write cdefs.pl' ; X X$curdef = '0' ; X$sep = "\\034" ; X Xprint C "#include <stdio.h>\n" ; Xprint C "#include <curses.h>\n" ; Xprint C "#include \"cursesX.h\"\n" ; Xprint C "#include \"defs.h\"\n" ; Xprint C "\n" ; Xfor ( sort keys %type ) X { if ( $type{$_} eq 'int' ) X { print C "static int $_ ;\n" ; } X elsif ( $type{$_} eq 'char' ) X { print C "static char $_ ;\n" ; } X elsif ( $type{$_} eq 'str' ) X { print C "static char $_\[BUFSIZE] ;\n" ; } X elsif ( $type{$_} eq 'win' ) X { print C "static WINDOW *$_ ;\n" ; } X } Xprint C "static int res ;\n" ; Xprint C "\n" ; X Xwhile ( $_ = <STDIN> ) X { chop ; X next if $_ =~ /^[ \t]*$/ || /^#/ ; X @ret = () ; X @arg = () ; X $varargs = 0 ; X $arg = '' ; X $body = '' ; X $form = '' ; X @_ = split ; X $func = shift @_ ; X push(@func,$func) ; X print C "void do_$func() {\n" ; X print C " addlogs(LOGCURS1,\"$func\") ;\n" ; X print P "# $_\n" ; X print P "\$curfun{'$func'} = '$_' ;\n" ; X print P "sub $func {\n" ; X $form = "$curdef$sep" ; X for ( $i = 0 ; $i <= $#_ ; $i++ ) X { $arg = $_[$i] ; X if ( $type{$arg} eq 'char' ) X { $form .= "%c$sep" ; X print C " $arg = nextChr() ;\n" ; X } X elsif ( $type{$arg} eq 'str' ) X { $form .= "%s$sep" ; X print C " strcpy($arg,nextStr()) ;\n" ; X } X elsif ( $type{$arg} eq 'int' ) X { $form .= "%d$sep" ; X print C " $arg = nextInt() ;\n" ; X } X elsif ( $type{$arg} eq 'win' ) X { $form .= "%d$sep" ; X print C " $arg = windows[nextInt()] ;\n" ; X } X elsif ( $type{$arg} eq 'var' ) X { $arg =~ s/^&(.*)/$1/ ; X $varargs++ ; X } X elsif ( $arg eq 'RETURN' ) X { @ret = @_[$i+1..$#_] ; X last ; X } X elsif ( $arg eq 'FLUSH' ) X { last ; } X else X { print "unknown argument $arg in $_\n" ; } X push(@arg,$arg) ; X } X X if ( $#arg - $varargs < 0 ) X { print P " print(\"$form\") ;\n" ; } X elsif ( $#arg - $varargs == 0 ) X { print P " printf(\"$form\",\$_[0]) ;\n" ; } X else X { print P " printf(\"$form\",\@_) ;\n" ; } X X if ( $#ret >= 0 ) X { print P ' local($', join(',$',@ret), ") ;\n" ; } X X if ( $func eq 'initscr' ) X { print C " initscr() ;\n" ; X print C " hasWin = 1 ;\n" ; X print C " initWindows() ;\n" ; X print C " saveWindow(stdscr) ;\n" ; X print C " saveWindow(curscr) ;\n" ; X print C " initCursesX() ;\n" ; X $body .= " \$stdscr = 0 ;\n" ; X $body .= " \$curscr = 1 ;\n" ; X $body .= " \$LINES = &getLINES ;\n" ; X $body .= " \$COLS = &getCOLS ;\n" ; X } X elsif ( $func eq 'endwin' ) X { print C " endwin() ;\n" ; X print C " hasWin = 0 ;\n" ; X $body .= " &curFlush ;\n" ; X } X elsif ( $func eq 'delwin' ) X { print C " win = windows[$arg] ;\n" ; X print C " unsaveWindow($arg) ;\n" ; X print C " delwin(win) ;\n" ; X } X elsif ( $arg eq 'RETURN' ) X { $body .= " &curFlush ;\n" ; X @res = grep(/^res(int|str|win)$/,@ret) ; X if ( $#res > 0 ) X { print "$_ : you may specify res... only once\n" ; } X elsif ( $#res == 0 ) X { if ( $type{$res[0]} eq 'str' ) X { print C " strcpy($res[0],$func(". join(',',@arg) . ")) ;\n" ; } X else X { print C " $res[0] = $func(". join(',',@arg) . ") ;\n" ; } X } X else X { print C " $func(". join(',',@arg) . ") ;\n" ; } X for $ret ( @ret ) X { $body .= " \$$ret = <STDIN> ; chop(\$$ret) ;\n" ; X if ( $type{$ret} eq 'str' ) X { print C " fprintf(OUT,\"%s\\n\",$ret) ;\n" ; X print C " addlogss(LOGCURS1," ; X print C "\"do_$func prints OUT\",$ret) ;\n" ; X } X elsif ( $type{$ret} eq 'win' ) X { print C " res = saveWindow($ret) ;\n" ; X print C " fprintf(OUT,\"%d\\n\",res) ;\n" ; X print C " addlogsn(LOGCURS1," ; X print C "\"do_$func prints OUT\",res) ;\n" ; X } X elsif ( $type{$ret} eq 'int' ) X { print C " fprintf(OUT,\"%d\\n\",$ret) ;\n" ; X print C " addlogsn(LOGCURS1," ; X print C "\"do_$func prints OUT\",$ret) ;\n" ; X } X else X { print "I have no type for $ret\n" ; } X } X print C " fflush(OUT) ;\n" ; X $body .= ' return $'. join(', $',@ret) . " ;\n" ; X } X elsif ( $arg eq 'FLUSH' ) X { $body .= " &curFlush ;\n" ; X print C " $func(". join(',',@arg) . ") ;\n" ; X } X else X { print C " $func(". join(',',@arg) . ") ;\n" ; } X X print P $body, "}\n" ; X print C "}\n" ; X $curdef++ ; X } X Xprint P "\n1 ;\n" ; X Xprint C "void (*(funtab[$curdef]))() ;\n" ; Xprint C "void init_funtab() {\n" ; X$i = 0 ; Xfor $func ( @func ) X { print C " funtab[$i] = do_$func ;\n" ; X $i++ ; X } Xprint C "}\n" ; END_OF_FILE if test 4900 -ne `wc -c <'cdefs.mk'`; then echo shar: \"'cdefs.mk'\" unpacked with wrong size! fi chmod +x 'cdefs.mk' # end of 'cdefs.mk' fi if test -f 'cdefs.types' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cdefs.types'\" else echo shar: Extracting \"'cdefs.types'\" \(1134 characters\) sed "s/^X//" >'cdefs.types' <<'END_OF_FILE' X$type{'win'} = 'win' ; X$type{'win1'} = 'win' ; X$type{'win2'} = 'win' ; X$type{'reswin'} = 'win' ; X$type{'resint'} = 'int' ; X$type{'delw'} = 'int' ; X$type{'curpos'} = 'int' ; X$type{'x'} = 'int' ; X$type{'y'} = 'int' ; X$type{'attrs'} = 'int' ; X$type{'flag'} = 'int' ; X$type{'xlen'} = 'int' ; X$type{'ms'} = 'int' ; X$type{'fd'} = 'int' ; X$type{'pad'} = 'int' ; X$type{'top'} = 'int' ; X$type{'bot'} = 'int' ; X$type{'pminrow'} = 'int' ; X$type{'pmincol'} = 'int' ; X$type{'sminrow'} = 'int' ; X$type{'smincol'} = 'int' ; X$type{'smaxrow'} = 'int' ; X$type{'smaxcol'} = 'int' ; X$type{'oldrow'} = 'int' ; X$type{'oldcol'} = 'int' ; X$type{'newrow'} = 'int' ; X$type{'newcol'} = 'int' ; X$type{'num_lines'} = 'int' ; X$type{'num_cols'} = 'int' ; X$type{'chint'} = 'int' ; X$type{'ch'} = 'char' ; X$type{'vert'} = 'char' ; X$type{'hor'} = 'char' ; X$type{'str'} = 'str' ; X$type{'rep'} = 'str' ; X$type{'resstr'} = 'str' ; X$type{'&str'} = 'var' ; X$type{'&y'} = 'var' ; X$type{'&x'} = 'var' ; END_OF_FILE if test 1134 -ne `wc -c <'cdefs.types'`; then echo shar: \"'cdefs.types'\" unpacked with wrong size! fi # end of 'cdefs.types' fi if test -f 'cterm.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cterm.1'\" else echo shar: Extracting \"'cterm.1'\" \(16725 characters\) sed "s/^X//" >'cterm.1' <<'END_OF_FILE' X.TH CTERM 1 "" "Department of Computer Science, RUU" X.SH NAME Xcterm, cterm.pl \- curses terminal emulation (for perl) X.SH SYNOPSIS X.B cterm X.I in out X[ X.I options X] [ X.I logfile X[ X.I loglevel X] ] X X.B cterm.pl X.SH DESCRIPTION X.PP X.B Cterm Xemulates a curses terminal. XOn filedescriptor X.I in Xit expects curses functions+arguments in the format described below. XOn filedescriptor X.IR out, Xsome functions (like getch()) pass back results. XCterm should only be forked by other programs after the proper pipes have Xbeen set up. X XThere are currently no documented X.I options X(see also the section on undocumented features). X XAs optional arguments to cterm, the name of a X.I logfile Xand a X.I loglevel Xmay be specified. XLoglevel 0 only logs strings provided by the application through Xthe curses extension X.BR ctermlog(str) . XLoglevel 1 logs all curses functions, arguments and results Xhandled by cterm. XLoglevel 2 shows even more intestines. XDefault is loglevel 0. X XCterm exits in a controlled fashion when it receives signal SIGINT or SIGPIPE. X X.B Cterm.pl Xis a library of perl subroutines that provides easy interaction with cterm. XCterm.pl defines perl-counterparts for almost all curses functions, Xtables with curses defined constants, Xand subroutines for starting and finishing cterm. X X.SH Communication between cterm.pl and cterm X XThe cterm.pl subroutine X.B &startCterm() Xsets up two (pair of) pipes, forks and execs cterm. XIn the parent (perl application) STDIN and STDOUT are redirected to the pipes. XIn the child (cterm) the pipes are connected to filedescriptors X.I out Xand X.IR in . XSubroutine X.B &finishCterm() Xfinishes cterm and restores STDIN and STDOUT again. X XFor the pupose of communication between cterm.pl and cterm, Xeach curses function supported in the interface is given a number. XA curses routine in cterm.pl prints this number on STDOUT Xfollowed by its parameters. XFunction numbers and parameters are separated by character 034 X(ASCII FS), the default value for X.BR $; . XWhen results are required they are read in from STDIN and Xreturned to the caller. XCterm reads the numbers from X.I in Xand calls appropriate functions which in turn read arguments from X.I in Xand perform the required curses functions. XResults are written to X.IR out , Xeach on a new line. X XCterm always flushes X.I out Xafter writing results to it. XCterm.pl can be used with $|=0 in applications. XAll curses subroutines in cterm.pl that need to return results, Xflush STDOUT before reading the results from STDIN. XThis implies for instance that the screen always gets up to date Xwhen user input is requested. XA curses extension X.B frefresh X(flush/refresh) does a normal refresh but also flushes STDOUT when X.B $flushOn Xis set. XIf you always use frefresh you can set $flushOn in parts Xof the application where you are willing to pay the price for Xa higher flush-rate in order to get a more accurate presentation. XWith subroutine X.B &curFlush() Xthe user can actively flush STDOUT. X XIn order to access curses defined constants, cterm.pl defines two tables: X.B %curcon Xand X.BR %curkey . XAssociative array %curcon contains entries like X('KEY_UP',259) and ('A_BLINK',1024), Xso curses constants (as strings) map to their value. XAssociative array %curkey contains the inverse of %curcon Xrestricted to KEY-codes. XSo, for example, $curkey{259} = 'KEY_UP' if $curcon{'KEY_UP'} = 259. XThe contents of %curcon and %curkey differ from system to system. XThey are created during installation. XThe KEY-associations (KEY_TAB,9) and (KEY_RET,13) are always defined. X XVariables X.BR $LINES , X.BR $COLS , X.B $stdscr Xand X.B $curscr Xare set by &initscr. X X.SH Arguments and results, representation X XLike in curses, in cterm.pl characters are really integers. XSo, for instance, X.B &addch(c) Xshould be provided with an integer and X.B &getch Xsupplies one. X XWindows are really pointers in curses. XSince mixing pointers and integers is potentially dangerous X(espcially printing and reading them in again) Xan indirection is introduced. XCterm stores the result of curses functions returning windows Xin a table and returns the index in the table to cterm.pl. XWhen curses returns window NULL, cterm returns -1. XSubroutine X.B &delwin(win) Xdeletes the window and the entry in the table. XSubroutine X.B &initscr Xclears the table and sets variables X.B $stdscr Xand X.BR $curscr. X XString arguments are printed on STDOUT as they are handed to cterm.pl. XThings break if a string contains character 034 (ASCII FS) Xbecause cterm will get out of sync. XNo mechanism was implemented to check and/or repair synchronization. X XCurses subroutines in cterm.pl return values by result Xand not by modifying parameters. XThe 'return-parameters' may be omitted in the call. XThis implies that for instance X.B getyx Xshould be called like '($a,$b) = &getyx($win)', Xalthough in C one would write 'getyx(win,a,b)'. XThe same holds for the X.B getstr Xfunction family. X XCurses subroutines in cterm.pl don't check their parameters, Xthey just pass 'em on. X X.SH Using cterm X XCterm is started up with X.B &startCterm() Xand finished with X.BR &finishCterm . XIn addition to proper values for X.I in Xand X.IR out , Xall arguments of startCterm are passed as arguments to the exec'ed cterm. XSo, if cterm logging is required, the name of the logfile Xshould be passed as an argument to startCterm. XIf cterm should log internals too, an integer loglevel greater than 0 Xshould be passed as well. XVariable X.B $ctermPid Xholds the pid of the forked cterm process. XSince cterm only performs curses calls, one usually has to go through Xthe customary proceedings: &initscr ; &nonl ; &cbreak ; &noecho. XSubroutine endwin() should be called before finishing cterm. X.br XIf the perl application does not call finishCterm before exit'ing, Xas in the case of a runtime error, cterm can't reset the terminal Xand hangs. XThis is a nuisance. XWhen X.B &safeCterm Xis called before &startCterm, cterm will be exec'ed in the parent process. XThis has the advantage that cterm wil always cleanup when the Xperl application suddenly dies. XThe disadvantage is that the application has no control over the terminal Xafter &finishCterm because the shell takes over when cterm exits. XIt should be used while developing that part of the application that Xruns between &startCterm and &finishCterm. X XSubroutine X.B ch2str(c) Xtakes an integer argument X.I c Xand, depending on its value, Xreturns a string consisting of the correspondig ASCII character, Xor a string like 'KEY_LEFT' or 'KEY_HOME' if X.I c Xis a KEY-code in curses, Xor the argument otherwise. XThe subroutine X.B getchint() Xis defined as X.BR ch2str(&getch()) . XThe KEY-associations (KEY_TAB,9) and (KEY_RET,13) are always defined. X XSubroutine X.B clrreg(top,bot) Xclears the screen from lines X.I top Xto X.IR bot . XSubroutine X.B wclrreg(win,top,bot) Xclears window X.I win Xfrom X.I top Xto X.IR bot . X XSubroutine X.B ctermlog(str) Xadds string X.I str Xto the cterm logfile if one was specified in &startCterm(). X XAssociative array X.B %curcon Xmaps curses constants (as strings) to their (integer) values. XThe contents of %curcon is determined by the installer. X XAssociative array X.B %curkey Xmaps curses KEY-codes (as strings) to their integer values. XIt is the inverse of %curcon restricted to keys matching /^KEY/. XThe contents of %curkey is determined by the installer. X XAssociative array X.B %curfun Xmaps curses functions (as strings) in the cterm interface Xto a string listing their parameters and results (if any). XTable %curfun can be used to determine if a curses function is available. XThe installer determines which functions are supported in the interface. X XFunction X.B edit(str,curpos,y,x,xlen,rep) Xreturns X.B (str,quitkey) Xand constitutes a local edit mode of cterm. XThe subroutine allows one to edit a string (initially X.IR str ). XIt shows (part of) the string in an edit window Xin line X.I y Xusing X.I xlen Xcolumns, starting from column X.IR x . XThe initial cursor position in X.I str Xis X.IR curpos . XEdit-mode is left and the resulting string returned to the caller Xwhen a 'special' is typed in. XThe set of 'special' characters can be specified as follows. XFunction X.B editreset() Xclears the set. XFunction X.B editq(chint) Xadds a character (supply an int) to the set. XThe 'special' character (really an int) Xwhich caused edit() to leave is returned to the caller too. X.br XEdit facilities are limited. XArrow-left and arrow-right work if keypad is enabled. XTyping in 'Kill' (as defined by curses killchar()) Xwill delete the character pointed to by the cursor. XTyping in 'Erase' (as defined by curses erasechar()) Xwill delete the character left of the cursor. XWhen the cursor points to the first character in X.I str Xand 'Erase' is typed in, X.I str Xwill be swapped with an initially empty save-buffer. XIt can be used to present a user with a default wich he/she Xcan edit or discard by typing 'Erase'. XPrintable ASCII characters are inserted. XAll others are rejected. X.br XArgument X.I rep Xmust be a string of four characters. XThey are used by edit to indicate which part of X.I str Xis shown on the screen. XOne of the first two characters in X.I rep Xis shown in the first column of the edit window. XOne of the last two characters in X.I rep Xis shown in the last column of the edit window. XEdit can only use X.I xlen-2 Xcolumns to present (part of) X.IR str . XFor the sake of simplicity, let us assume that X.IR rep ='[<>]'. XIf lenght(\fIstr\fP)<=\fIxlen-2\fP, then X.I str Xis shown on the screen like '[\fIstr\fP]'. XIf lenght(\fIstr\fP)>\fIxlen-2\fP, then Xonly a substring X.I sub Xof X.I str Xcan be shown on the screen. XIf X.I sub Xis a prefix of X.I str Xthen it is shown like '[\fIsub\fP>'. XIf it is a suffix it is shown like '<\fIsub\fP]'. XIt is shown like '<\fIsub\fP>' otherwise. X.br XThe cursor position will be held at the middle of the edit window Xif X.I sub Xis neither a prefix nor a suffix of X.IR str . X.br XSubroutine X.B wedit(win,str,curpos,y,x,xlen,rep) Xdoes edit() in a window. X XSubroutine X.B editreset() Xclears the set of 'special' characters (see edit()). X XSubroutine X.B editq(chint) Xadds a character (supply an int) X.I chint Xto the set of 'special' characters (see edit()). X XSubroutine X.B endwin() Xflushes STDOUT. X XSubroutine X.B frefresh() Xdoes a refresh. XSTDOUT is flushed if X.B $flushOn Xis set. X XFunction X.B getstr(str) Xshould be called like '$str = &getstr', Xmvgetstr(str) should be called like '$str = &mvgetstr($y,$x)', Xand mvwgetstr, wgetstr likewise. X XFunction X.B getyx Xshould be called like '($a,$b) = &getyx($win)'. X XFunction X.B getchR() Xand X.B wgetchR(win) Xact like getch() but redraw the screen if ^L is entered. XThey do getch's until a non-^L is found. X XSubroutine X.B initscr() Xsets $LINES and $COLS and Xforgets about all windows except stdscr and curscr. X XSubroutine X.B refresh() Xdoes not flush STDOUT (see also &frefresh()). X XSubroutine X.B show(str,curpos,y,x,xlen,rep) Xshows X.I str Xon the screen like edit initially would. XIt is handy in applications that are to be independent of the value of COLS. X.br XSubroutine X.B wshow(win,str,curpos,y,x,xlen,rep) Xdoes show() in a window. X X.SH Omissions and limitations XImplementations of curses differ a lot. XA few curses functions that are available on some Xsystems are not supported in this distribution. XSome were documented as obsolete, some are meaningless in this application. XThe ones which take a variable number of arguments don't fit Xthe interface model and can be done in perl more easily anyway. XSome are left out because the author was unable to understand what Xthey were supposed to do. XUse %curfun to find out which curses functions are supported in the interface. X XWhich constants go in %curcon and %curkey is determined by the installer. X XAs distributed, the size of the window table is 100. XThe size of the set of 'special' characters for edit() is 1000. XStrings passed to cterm shouldn't be larger than 10K. X X.SH Installation XEdit the 'Makefile' in the source directory. XDefine BINDIR to be a directory were exec usually looks for executables. XDefine PERLLIB to be a directory where perl's do-statement Xlooks for libraries to include. XThe Makefile variables EDIT_LEFT, EDIT_RIGHT and BEEP are passed to edit.c. XThey are used in edit(). XWhen user input equals EDIT_LEFT (EDIT_RIGHT), edit() moves the Xcursor left (right). XIf your curses recognizes arrow-keys, define EDIT_LEFT (EDIT_RIGHT) to Xwhatever curses getch() returns if the user types in arrow-left (arrow-right). XIf not, define EDIT_LEFT as 2 (^B for Back) Xand EDIT_RIGHT as 6 (^F for Forward). XYou may also comment them out entirely. X.br XBEEP is the function that is used to signal edit errors to the user. XSet it to 'beep' (sound bell) if your curses supports it. XSet it to 'mybeep' if you have nothing better. XIt writes ^G to stderr. XYou may want to change the implementation of 'mybeep' in cursesX.c. XFunction 'nobeep' is defined and does nothing. XIt is used if you don't define BEEP. X XRun 'make' to generate the necessary stuff. XDon't worry about warnings from 'curcon.mk'. XThey simply mean that not all the curses constants suggested Xin 'curcon.in' are available on your system. XYou might want to try the perl programs 'try1' and 'try2' before Xinstalling. XArguments to try1 and try2 are passed to startCterm and thus to cterm. X XRunning 'make install' will copy the stuff to the designated directories. XRunning 'make clean' will remove temporaries. XRunning 'make realclean' will remove all generated stuff. X XThe author has tried to make the system adaptable to local conditions. XThere are two files that the installer can modify. X.br XThe file X.B cdefs.in Xis the input for cdefs.mk which generates the interface between Xcterm and cterm.pl: cdefs.c and cdefs.pl. XIt contains one line for each curses function which is supported in the Xinterface. XIt specifies the name of the function and the parameters that are Xto be passed from cterm.pl to cterm, and in some cases the results Xthat are to be passed back. XIf your curses doesn't support some of them, simply comment them Xout ('#' in the first column). XIf there is a problem with something in the 'extensions' or 'extra's', Xplease contact the author. XCreate your own minicurses if you think it is all too baroque. XOn a Sun, try to use the SYSV C compiler (/usr/5bin/cc on my sun). XIt provides a better curses. XThe file X.B cdefs.in.SUN Xcontains a severely stripped version of cdefs.in that makes cterm run on Xmy standard SunOs.4.0.3 C compiler. X.br XThe file X.B curcon.in Xis the input for curcon.mk which generates curcon.c which Xdefines the contents of %curcon and %curkey in file curcon.pl. XCurcon.in is a wishlist. XComment out constants that are not defined and add others that are. XAs distributed, 10 function keys are defined in the way they should be Xon some systems. X XIf you want to add functionality, define more functions in cdefs.in. XLook at other functions and cdefs.types to see how parameters and results Xare to be specified. XIf you define a function, add an implementation for it in cursesX.c. XFor an example, look at X.IR clrreg . XFunction initscr() calls initCursesX(). XThis is the place to put initialisation stuff for curses additions. X X.SH "Author's note" XI developed cterm as part of a perl project called 'jinx'. XJinx is a simple, not-quite-relational database system. XIt seemed more practical to have a weak implementation of 'full curses' Xin stead of a strong, tested implementation of an ad hoc subset of curses. XIn jinx I have sofar used only some of the curses facilities. XThe newwin and subwin stuff has not been tried a lot. XI've never tried to set up a multi-terminal application. XI want to get it right though, so complaints will be honored. X.br XFor the future I have a wishlist. XI would like to also have sockets for communication available. XI have never used sockets before so I don't see any problems. XA simple synchronisation mechanism would be easy to implement, Xbut I never have problems in that area. XI guess I don't know how serious the FS-in-strings problem is. XIt should be possible to tell cterm how to handle signals while it runs. XCterm should more often be able to reset the terminal. X.br XThanks go to Piet van Oostrum (piet@cs.ruu.nl) for his harsh criticism Xand willingness to discuss technicalities. X X.SH Undocumented features X XIf you supply option X.BR -X , Xtyping ^X to getchR (and wgetchR) will get you IO statistics in line 0. XUse it to see how much setting $flushOn or $| are costing you Xin context switches. XThe curses extension quitcterm makes cterm quit. XIt is used by finishCterm. X X.SH BUGS X XAs explained above, arguments of subroutines in cterm.pl Xshould never contain ASCII character 034 (FS). XFS is used as a separator on the info stream from cterm.pl to cterm. X X.SH AUTHOR XHenk P. Penning (henkp@cs.ruu.nl), Department of Computer Science, XUtrecht University, the Netherlands. END_OF_FILE if test 16725 -ne `wc -c <'cterm.1'`; then echo shar: \"'cterm.1'\" unpacked with wrong size! fi # end of 'cterm.1' fi if test -f 'cterm.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cterm.c'\" else echo shar: Extracting \"'cterm.c'\" \(4646 characters\) sed "s/^X//" >'cterm.c' <<'END_OF_FILE' X#include <curses.h> X#include "cursesX.h" X#include <signal.h> X#include <stdio.h> X#include "defs.h" X XFILE *OUT ; XWINDOW *windows[MAXNUMWINDOWS] ; Xint optX = 0, hasWin = 0 ; X Xstatic int hasOUT = 0 ; Xstatic FILE *LOG ; Xstatic int in = -1, out = -1 ; Xstatic int n, loglevel = -1 ; Xstatic char com[BUFSIZE], buf[BUFSIZE] ; Xstatic int comSize = 0, bufSize = 0, bufhead = 0, buftail = 0 ; Xstatic int numread = 0, numreads = 0 ; Xstatic char outstr[1024] ; X XcurStat() X{ int n,i,y,x ; X char s[80] ; X X sprintf(s,"reads %d, read %d, average %d",numreads,numread,numread/numreads) ; X getyx(stdscr,y,x) ; X mvinsch(0,0,'|') ; X for (i=strlen(s)-1 ; i>=0 ; i--) X { mvinsch(0,0,s[i]) ; } X move(y,x) ; X refresh() ; X} X Xvoid redraw() X{ int i ; X X for ( i = 0 ; i < MAXNUMWINDOWS ; i++ ) X if ( ( windows[i] != NULL ) && ( windows[i] != curscr ) ) X { clearok(windows[i],1) ; X wrefresh(windows[i]) ; X } X} X Xvoid addlogs(level,s) Xint level ; Xchar *s ; X{ if ( level <= loglevel ) X { fprintf(LOG,"%s\n",s) ; X fflush(LOG) ; X } X} X Xvoid addlogsn(level,s,n) Xint level ; Xchar *s ; Xint n ; X{ if ( level <= loglevel ) X { fprintf(LOG,"%s %d\n",s,n) ; X fflush(LOG) ; X } X} X Xvoid addlogss(level,s1,s2) Xint level ; Xchar *s1, *s2 ; X{ if ( level <= loglevel ) X { fprintf(LOG,"%s %s\n",s1,s2) ; X fflush(LOG) ; X } X} X Xvoid quit() X{ addlogs(LOGCURS1,"quit") ; X if ( hasWin ) { addlogs(LOGCURS1,"endwin") ; endwin() ; } X if ( hasOUT ) fclose(OUT) ; else close(out) ; X addlogs(LOGCURS1,"gone") ; X exit(1) ; X} X Xvoid sig_quit() X{ addlogs(LOGCURS1,"sig_quit") ; X quit() ; X} X Xint incMod(x,y) int *x, y ; { *x = ((*x)+1) % y ; return(*x) ; } X Xint isemptyq() { return(bufSize == 0) ; } X Xvoid enqueue(c) Xchar c ; X{ buf[buftail] = c ; bufSize++ ; incMod(&buftail,BUFSIZE) ; } X Xint dequeue() X{ char c ; X c = buf[bufhead] ; bufSize-- ; incMod(&bufhead,BUFSIZE) ; return(c) ; X} X Xint getCom() X{ int res, c, i, found ; X char row[BUFSIZE2] ; X char mes[100] ; X X res = 1 ; X found = 0 ; X comSize = 0 ; X X do { c = 'x' ; X while ( ( !isemptyq() ) && ( (c = dequeue()) != SEP ) ) X { com[comSize++] = c ; } X if (c == SEP) X { com[comSize] = 0 ; X found = 1 ; X } X else X { res = read(in,row,BUFSIZE2) ; X if (res < 0) X { addlogs(LOGCURS1,"read error") ; X quit() ; X } X if ( res ) X { numread += res ; X numreads++ ; X for (i=0 ; i<res ; i++) X { enqueue(row[i]) ; } X } X else X { addlogs(LOGCURS1,"read 0 chars") ; X found = 1 ; X } X } X } X while ( ! found ) ; X X addlogs(LOGCURS2,com) ; X X return(res) ; X} X Xint nextInt() X{ int n ; X if ( ! getCom() ) quit() ; X sscanf(com,"%d",&n) ; X addlogsn(LOGCURS1,"nextInt",n) ; X return(n) ; X} X Xint nextCom() X{ int n ; X if ( ! getCom() ) quit() ; X sscanf(com,"%d",&n) ; X addlogsn(LOGCURS2,"nextCom",n) ; X return(n) ; X} X Xint nextChr() X{ int c = 0 ; X if ( ! getCom() ) quit() ; X addlogsn(LOGCURS1,"nextChr",com[0]) ; X return(com[0]) ; X} X Xchar *nextStr() X{ if ( ! getCom() ) quit() ; X addlogss(LOGCURS1,"nextStr",com) ; X return(&(com[0])) ; X} X Xvoid initWindows() X{ int i ; X for ( i = 0 ; i < MAXNUMWINDOWS ; i++ ) X { windows[i] = NULL ; } X} X Xvoid unsaveWindow(i) int i ; { windows[i] = NULL ; } X Xint saveWindow(w) XWINDOW *w ; X{ int i ; X for ( i = 0 ; i < MAXNUMWINDOWS && windows[i] != NULL ; i++ ) { ; } X if ( i < MAXNUMWINDOWS ) X { windows[i] = w ; return(i) ; } X else X { delwin(w) ; return(-1) ; } X} X Xmain(argc,argv) Xint argc ; Xchar **argv ; X{ int c ; X char *prog ; X X prog = argv[0] ; argv++ ; argc-- ; X X if ( argc < 2 ) X { fprintf(stderr,"Usage: %s in out [options] [logfile [level]]\n",prog) ; X exit(1) ; X } X else X { in = atoi(*argv) ; argc-- ; argv++ ; X out = atoi(*argv) ; argc-- ; argv++ ; X } X X while ( ( argc > 0 ) && ( argv[0][0] == '-' ) ) X { switch ( argv[0][1] ) { X case 'X' : optX = 1 ; X break ; X case 0 : fprintf(stderr,"unknown option %s\n", "-") ; X exit(1) ; X break ; X default : fprintf(stderr,"unknown option %c\n", argv[0][1]) ; X exit(1) ; X break ; X } X argc-- ; argv++ ; X } X X if ( argc > 0 ) X { LOG = fopen(*argv,"w") ; X if ( LOG == NULL ) X { fprintf(stderr,"cannot open log file %s\n", *argv) ; X exit(1) ; X } X argc-- ; argv++ ; X } X if ( argc > 0 ) X { loglevel = atoi(*argv) ; } X else X { loglevel = 0 ; } X X signal(SIGINT,sig_quit) ; X signal(SIGPIPE,sig_quit) ; X X OUT = fdopen (out,"w") ; hasOUT++ ; X X addlogsn(LOGCURS1,"option X",optX) ; X X init_funtab() ; X X while (1) X { n = nextCom() ; X (*(funtab[n]))() ; X } X X} END_OF_FILE if test 4646 -ne `wc -c <'cterm.c'`; then echo shar: \"'cterm.c'\" unpacked with wrong size! fi # end of 'cterm.c' fi if test -f 'cterm.pl' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cterm.pl'\" else echo shar: Extracting \"'cterm.pl'\" \(1958 characters\) sed "s/^X//" >'cterm.pl' <<'END_OF_FILE' X#! /local/bin/perl X Xdo 'cdefs.pl' || die "cterm.pl can't include cdefs.pl\n" ; Xdo 'curcon.pl' || die "cterm.pl can't include curcon.pl\n" ; X Xsub curFlush X { $oldpipe = $| ; X $| = 1 ; X print "" ; X $| = $oldpipe ; X } X Xsub frefresh { &refresh ; &curFlush if $flushOn ; } X Xsub ch2str X { local($c) = shift ; X if ( (31 < $c) && ($c < 128) ) X { return(sprintf("%c", $c)) ; } X elsif ( defined $curkey{$c} ) X { return($curkey{$c}) ; } X else X { return($c) ; } X } X Xsub getchint { return &ch2str(&getch) ; } X Xsub safeCterm { $safeCterm = 1 ; } X Xsub startCterm X { pipe(CURIN,PERLOUT) || die "cterm.pl can\'t create pipe CURIN/PERLOUT" ; X pipe(PERLIN,CUROUT) || die "cterm.pl can\'t create pipe PERLIN/CUROUT" ; X X $ctermPid = fork ; X X if ( $safeCterm ? ( $ctermPid != 0 ) : ( $ctermPid == 0 ) ) X { close(PERLIN) || die "cterm.pl can\'t close PERLIN" ; X close(PERLOUT) || die "cterm.pl can\'t close PERLOUT" ; X exec('cterm',fileno(CURIN),fileno(CUROUT),@_) ; X die 'cterm.pl can\'t exec cterm' ; X } X else X { close(CURIN) || die "cterm.pl can\'t close CURIN" ; X close(CUROUT) || die "cterm.pl can\'t close CUROUT" ; X open(SAVESTDIN, "<&STDIN") || die 'cterm.pl can\'t save STDIN' ; X open(SAVESTDOUT,">&STDOUT") || die 'cterm.pl can\'t save STDOUT' ; X open(STDIN, "<&PERLIN") || die 'cterm.pl can\'t redirect STDIN' ; X open(STDOUT,">&PERLOUT") || die 'cterm.pl can\'t redirect STDOUT' ; X $preCtermPipe = $| ; X $preCtermSelect = select(STDOUT) ; X $| = 0 ; X $flushOn = 0 ; X } X } X Xsub finishCterm X { &quitcterm ; X close(PERLOUT) ; X sleep 1 ; X close(PERLIN) ; X open(STDIN, "<&SAVESTDIN") || die 'cterm.pl can\'t reredirect STDIN' ; X open(STDOUT,">&SAVESTDOUT") || die 'cterm.pl can\'t reredirect STDOUT' ; X close(SAVESTDIN) ; X close(SAVESTDOUT) ; X select($preCtermSelect) ; X $| = $preCtermPipe ; X } X X1; END_OF_FILE if test 1958 -ne `wc -c <'cterm.pl'`; then echo shar: \"'cterm.pl'\" unpacked with wrong size! fi chmod +x 'cterm.pl' # end of 'cterm.pl' fi if test -f 'curcon.in' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'curcon.in'\" else echo shar: Extracting \"'curcon.in'\" \(1085 characters\) sed "s/^X//" >'curcon.in' <<'END_OF_FILE' XTRUE XFALSE XOK XERR XA_STANDOUT XA_UNDERLINE XA_REVERSE XA_BLINK XA_DIM XA_BOLD XA_ALTCHARSET XA_INVIS XA_PROTECT XA_NORMAL XA_ATTRIBUTES XA_CHARTEXT XKEY_BREAK XKEY_DOWN XKEY_UP XKEY_LEFT XKEY_RIGHT XKEY_HOME XKEY_BACKSPACE XKEY_F0 XKEY_F(1) XKEY_F(2) XKEY_F(3) XKEY_F(4) XKEY_F(5) XKEY_F(6) XKEY_F(7) XKEY_F(8) XKEY_F(9) XKEY_DL XKEY_IL XKEY_DC XKEY_IC XKEY_EIC XKEY_CLEAR XKEY_EOS XKEY_EOL XKEY_SF XKEY_SR XKEY_NPAGE XKEY_PPAGE XKEY_STAB XKEY_CTAB XKEY_CATAB XKEY_ENTER XKEY_SRESET XKEY_RESET XKEY_PRINT XKEY_LL XKEY_A1 XKEY_A3 XKEY_B2 XKEY_C1 XKEY_C3 XKEY_BTAB XKEY_BEG XKEY_CANCEL XKEY_CLOSE XKEY_COMMAND XKEY_COPY XKEY_CREATE XKEY_END XKEY_EXIT XKEY_FIND XKEY_HELP XKEY_MARK XKEY_MESSAGE XKEY_MOVE XKEY_NEXT XKEY_OPEN XKEY_OPTIONS XKEY_PREVIOUS XKEY_REDO XKEY_REFERENCE XKEY_REFRESH XKEY_REPLACE XKEY_RESTART XKEY_RESUME XKEY_SAVE XKEY_SBEG XKEY_SCANCEL XKEY_SCOMMAND XKEY_SCOPY XKEY_SCREATE XKEY_SDC XKEY_SDL XKEY_SELECT XKEY_SEND XKEY_SEOL XKEY_SEXIT XKEY_SFIND XKEY_SHELP XKEY_SHOME XKEY_SIC XKEY_SLEFT XKEY_SMESSAGE XKEY_SMOVE XKEY_SNEXT XKEY_SOPTIONS XKEY_SPREVIOUS XKEY_SPRINT XKEY_SREDO XKEY_SREPLACE XKEY_SRIGHT XKEY_SRSUME XKEY_SSAVE XKEY_SSUSPEND XKEY_SUNDO XKEY_SUSPEND XKEY_UNDO END_OF_FILE if test 1085 -ne `wc -c <'curcon.in'`; then echo shar: \"'curcon.in'\" unpacked with wrong size! fi # end of 'curcon.in' fi if test -f 'curcon.mk' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'curcon.mk'\" else echo shar: Extracting \"'curcon.mk'\" \(936 characters\) sed "s/^X//" >'curcon.mk' <<'END_OF_FILE' X#! /local/bin/perl X Xopen(STDIN,'curcon.in') || die "can't open curcon\n" ; Xopen(STDOUT,'>curcon.c') || die "can't create curcon.c\n" ; X Xprint "#include <curses.h>\n" ; Xprint "#include <stdio.h>\n" ; Xprint "\n" ; Xprint "main() {\n" ; X Xwhile ( $_ = <STDIN> ) X { chop ; X next if $_ =~ /^[ \t]*$/ || $_ =~ /^#/ ; X $arg = ( /^(.*)\(.*\)/ ) ? $1 : $_ ; X print "#ifdef $arg\n" ; X print " printf(\"\$curcon{'$_'} = %d ;\\n\",$_) ;\n" ; X if ( $_ =~ /^KEY/ ) X { print " printf(\"\$curkey{%d} = '$_' ;\\n\",$_) ;\n" ; } X print "#else\n" ; X { print " fprintf(stderr,\"warning: no definition for $_\\n\") ;\n" ; } X print "#endif\n" ; X } X Xprint " printf(\"\$curcon{'KEY_RET'} = %d ;\\n\",13) ;\n" ; Xprint " printf(\"\$curkey{13} = 'KEY_RET' ;\\n\") ;\n" ; Xprint " printf(\"\$curcon{'KEY_TAB'} = %d ;\\n\",9) ;\n" ; Xprint " printf(\"\$curkey{9} = 'KEY_TAB' ;\\n\") ;\n" ; Xprint " exit(0) ;\n" ; Xprint "}\n" ; END_OF_FILE if test 936 -ne `wc -c <'curcon.mk'`; then echo shar: \"'curcon.mk'\" unpacked with wrong size! fi chmod +x 'curcon.mk' # end of 'curcon.mk' fi if test -f 'cursesX.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cursesX.c'\" else echo shar: Extracting \"'cursesX.c'\" \(1951 characters\) sed "s/^X//" >'cursesX.c' <<'END_OF_FILE' X#include <stdio.h> X#include <curses.h> X#include "cursesX.h" X#include "defs.h" X Xvoid initCursesX() X{ /* called by do_initscr ; */ X ; X} X Xint getLINES() { return(LINES) ; } Xint getCOLS() { return(COLS) ; } X Xint wgetchR(w) XWINDOW *w ; X{ int x,y,c ; X for ( c = wgetch(w) X ; ( c == REDRAW_INT ) || ( optX && ( c == OPTX_INT ) ) X ; c = wgetch(w) X ) X { if ( c == REDRAW_INT ) X { getyx(w,y,x) ; X redraw() ; X wmove(w,y,x) ; X wrefresh(w) ; X } X else if ( c == OPTX_INT ) X { curStat() ; } X } X return(c) ; X} X Xint getchR() X{ return(wgetchR(stdscr)) ; } X Xvoid quitcterm() X{ quit() ; X} X Xvoid wshow (win,line,cp,ystart,xstart,xlen,rep) XWINDOW *win ; Xchar *line ; Xint cp, ystart,xstart,xlen ; Xchar *rep ; X{ showline(line,cp,win,ystart,xstart,xlen,rep) ; X} X Xvoid show (line,cp,ystart,xstart,xlen,rep) Xchar *line ; Xint cp, ystart,xstart,xlen ; Xchar *rep ; X{ showline(line,cp,stdscr,ystart,xstart,xlen,rep) ; X} X Xint wedit (win,line,curpos,ystart,xstart,xlen,rep) XWINDOW *win ; Xchar *line ; Xint curpos, ystart, xstart, xlen ; Xchar *rep ; X{ int c ; X c = editline (line,BUFSIZE,&curpos,win,ystart,xstart,xlen,rep) ; X addlogsn(LOGCURS2,"wedit returns",c) ; X return( c ) ; X} X Xint edit (line,curpos,ystart,xstart,xlen,rep) Xchar *line ; Xint curpos, ystart, xstart, xlen ; Xchar *rep ; X{ int c ; X c = editline (line,BUFSIZE,&curpos,stdscr,ystart,xstart,xlen,rep) ; X addlogsn(LOGCURS2,"edit returns",c) ; X return( c ) ; X} X Xvoid mybeep() { fprintf(stderr,"%c",7) ; } Xvoid nobeep() { ; } X Xvoid wclrreg(w,top,bot) XWINDOW *w ; Xint top,bot ; X{ int i ; X for ( i = top ; i <= bot ; i++ ) X { wmove(w,i,0) ; X wclrtoeol(w) ; X } X} X Xvoid clrreg(top,bot) Xint top,bot ; X{ wclrreg(stdscr,top,bot) ; } X Xvoid ctermlog(s) char *s ; { addlogss(LOGAPPL,"LOG",s) ; } X Xint editq(n) int n ; { return(addQuitEdit(n)) ; } Xvoid editreset() { emptyQuitEdit() ; } Xvoid curnop() { ; } Xvoid curflush() { ; } END_OF_FILE if test 1951 -ne `wc -c <'cursesX.c'`; then echo shar: \"'cursesX.c'\" unpacked with wrong size! fi # end of 'cursesX.c' fi if test -f 'cursesX.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cursesX.h'\" else echo shar: Extracting \"'cursesX.h'\" \(374 characters\) sed "s/^X//" >'cursesX.h' <<'END_OF_FILE' Xextern int wgetchR() ; Xextern void show() ; Xextern void wshow() ; Xextern int edit() ; Xextern int wedit() ; Xextern void quitcterm() ; Xextern void ctermlog() ; Xextern int editq() ; Xextern void editreset() ; Xextern void curnop() ; Xextern void curflush() ; Xextern void wclrreg() ; Xextern void clrreg() ; Xextern void mybeep() ; Xextern void nobeep() ; Xextern void initCursesX() ; END_OF_FILE if test 374 -ne `wc -c <'cursesX.h'`; then echo shar: \"'cursesX.h'\" unpacked with wrong size! fi # end of 'cursesX.h' fi if test -f 'defs.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'defs.h'\" else echo shar: Extracting \"'defs.h'\" \(592 characters\) sed "s/^X//" >'defs.h' <<'END_OF_FILE' X#define BUFSIZE 20480 X#define BUFSIZE2 10240 X#define SEP 28 X X#define MAXNUMWINDOWS 100 X#define MAXQUITEDIT 1000 X#define REDRAW_INT '\014' X#define OPTX_INT '\030' X X#define LOGAPPL 0 X#define LOGCURS1 1 X#define LOGCURS2 2 X Xextern FILE *OUT ; Xextern WINDOW *windows[] ; Xextern int optX, hasWin ; X Xextern int saveWindow() ; Xextern void unsaveWindow() ; Xextern void initWindows() ; Xextern void redraw() ; X Xextern char *nextStr() ; Xextern int nextChr() ; Xextern int nextInt() ; X Xextern void emptyQuitEdit() ; Xextern int addQuitEdit() ; Xextern int inQuitEdit() ; X Xextern void (*(funtab[]))() ; END_OF_FILE if test 592 -ne `wc -c <'defs.h'`; then echo shar: \"'defs.h'\" unpacked with wrong size! fi # end of 'defs.h' fi if test -f 'edit.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'edit.c'\" else echo shar: Extracting \"'edit.c'\" \(4335 characters\) sed "s/^X//" >'edit.c' <<'END_OF_FILE' X#include <curses.h> X#include "cursesX.h" X#include <stdio.h> X#include <ctype.h> X#include <string.h> X#include "defs.h" X X#ifndef BEEP X#define BEEP nobeep X#endif X Xstatic int Erase = 0, Kill = 0, initialized = 0 ; Xstatic int quitEdit[MAXQUITEDIT], quitEditSize = 0 ; X Xstatic char save[BUFSIZE], temp[BUFSIZE] ; X Xvoid initEdit() X{ Erase = erasechar() ; X Kill = killchar() ; X} X Xvoid emptyQuitEdit() { quitEditSize = 0 ; } X Xint addQuitEdit(n) Xint n ; X{ if ( quitEditSize >= MAXQUITEDIT ) X return(0) ; X quitEdit[quitEditSize++] = n ; X return(1) ; X} X Xint inQuitEdit(n) Xint n ; X{ int i ; X for ( i = 0 ; i < quitEditSize ; i++ ) X if ( quitEdit[i] == n ) X return(1) ; X return(0) ; X} X Xvoid showline (line,cp,win,ystart,xstart,xlen,rep) Xchar *line ; Xint cp ; XWINDOW* win ; Xint ystart,xstart,xlen ; Xchar rep[4] ; X{ int ll = strlen(line) ; X int i, h = xlen/2 ; X char lc, lo, ro, rc ; X X lc = rep[0] ; X lo = rep[1] ; X ro = rep[2] ; X rc = rep[3] ; X X wmove(win,ystart,xstart) ; X X if ( (ll <= xlen) && (cp < xlen) ) X { waddch(win,lc) ; X for (i=0 ; i<=ll-1 ; i++) X waddch(win,line[i]) ; X for (i=ll ; i<xlen ; i++) X waddch(win,' ') ; X waddch(win,rc) ; X wmove(win,ystart,xstart+1+cp) ; X } X else if ( (ll == xlen) && (cp == xlen) ) X { waddch(win,lo) ; X for (i=1 ; i<=ll-1 ; i++) X waddch(win,line[i]) ; X waddch(win,' ') ; X waddch(win,rc) ; X wmove(win,ystart,xstart+1+cp-1) ; X } X else /* ll > xlen */ X if ( cp < h+1 ) X { waddch(win,lc) ; X for (i=0 ; i<xlen ; i++) X waddch(win,line[i]) ; X waddch(win,ro) ; X wmove(win,ystart,xstart+1+cp) ; X } X else if ( cp < ll-xlen+h ) X { waddch(win,lo) ; X for (i=cp-h ; i<=cp-h+xlen-1 ; i++) X waddch(win,line[i]) ; X waddch(win,ro) ; X wmove(win,ystart,xstart+1+h) ; X } X else if ( cp < ll ) X { waddch(win,lo) ; X for (i=ll-xlen ; i<=ll-1 ; i++) X waddch(win,line[i]) ; X waddch(win,rc) ; X wmove(win,ystart,xstart+1+cp-ll+xlen) ; X } X else /* cp == ll */ X { waddch(win,lo) ; X for (i=ll-xlen+1 ; i<=ll-1 ; i++) X waddch(win,line[i]) ; X waddch(win,' ') ; X waddch(win,rc) ; X wmove(win,ystart,xstart+1+xlen-1) ; X } X wrefresh(win) ; X} X Xvoid doCurRight(ll,cp) Xint *ll,*cp ; X{ if ( *cp < *ll ) X (*cp)++ ; X else X BEEP() ; X} X Xvoid doCurLeft(ll,cp) Xint *ll,*cp ; X{ if ( *cp > 0 ) X (*cp)-- ; X else X BEEP() ; X} X XdoErase(line,ll,cp) Xchar *line ; Xint *ll,*cp ; X{ int i ; X X if (*ll == 0 || *cp == 0) X { strcpy(temp,line) ; X strcpy(line,save) ; X strcpy(save,temp) ; X *ll = strlen(line) ; X *cp = 0 ; X } X else X { for (i=(*cp)-1 ; i<*ll ; i++) X line[i] = line[i+1] ; X (*ll)-- ; X (*cp)-- ; X } X} X Xvoid doDel(line,ll,cp) Xchar *line ; Xint *ll,*cp ; X{ int i ; X X if (*ll == 0) X BEEP() ; X if (*cp == *ll) X doCurLeft(ll,cp) ; X else X { for (i = *cp ; i < *ll ; i++) X line[i] = line[i+1] ; X (*ll)-- ; X if ( *cp > *ll ) X *cp = *ll ; X } X} X Xvoid doInsert(line,maxlinelen,ll,cp,c) Xchar *line ; Xint *ll, *cp, c ; X{ int i ; X X if (*ll > maxlinelen) X BEEP() ; X else X for (i = *ll ; i >= *cp ; i--) X line[i+1] = line[i] ; X line[*cp] = c ; X (*cp)++ ; X (*ll)++ ; X} X Xvoid editCom (line,maxLineLen,linelen,curpos,c) Xchar *line ; Xint maxLineLen, *linelen, *curpos ; Xint c ; X{ if ( c == Kill ) X doDel(line,linelen,curpos) ; X else if ( c == Erase ) X doErase(line,linelen,curpos) ; X#ifdef EDIT_RIGHT X else if ( c == EDIT_RIGHT ) X doCurRight(linelen,curpos) ; X#endif X#ifdef EDIT_LEFT X else if ( c == EDIT_LEFT ) X doCurLeft(linelen,curpos) ; X#endif X else if ( (c < 32) || (c > 127) ) X BEEP() ; X else X doInsert(line,maxLineLen,linelen,curpos,c) ; X} X Xint editline (line,maxlinelen,curpos,win,ystart,xstart,xlen,rep) Xchar *line ; Xint maxlinelen, *curpos ; XWINDOW *win ; Xint ystart, xstart, xlen ; Xchar *rep ; X{ int linelen = strlen(line) ; X int c ; X X if ( ! initialized ) { initEdit() ; initialized = 1 ; } X X strcpy(save,"") ; X X showline(line,*curpos,win,ystart,xstart,xlen,rep) ; X X for ( c=wgetchR(win) X ; ( c != EOF) && ( ! inQuitEdit(c) ) X ; c=wgetchR(win) X ) X { editCom(line,maxlinelen,&linelen,curpos,c) ; X showline(line,*curpos,win,ystart,xstart,xlen,rep) ; X } X X showline(line,0,win,ystart,xstart,xlen,rep) ; X return(c) ; X} END_OF_FILE if test 4335 -ne `wc -c <'edit.c'`; then echo shar: \"'edit.c'\" unpacked with wrong size! fi # end of 'edit.c' fi if test -f 'try1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'try1'\" else echo shar: Extracting \"'try1'\" \(448 characters\) sed "s/^X//" >'try1' <<'END_OF_FILE' X X# cterm example application X# usage: perl try1 X# 'perl try1 LOG 1' will produce a cterm logfile LOG. X Xdo 'cterm.pl' || die "$0 can't include cterm.pl\n" ; X&startCterm(@ARGV) ; X&initscr ; &nonl ; &cbreak ; &noecho ; X$japh = "just another perl hacker" ; X&mvaddstr(int($LINES/2),int(($COLS-length($japh))/2),$japh) ; X&mvaddstr($LINES-1,0,'hit any key to continue ') ; X&refresh ; X&getchR ; X&clear ; X&move(0,0) ; X&refresh() ; X&endwin ; X&finishCterm ; END_OF_FILE if test 448 -ne `wc -c <'try1'`; then echo shar: \"'try1'\" unpacked with wrong size! fi chmod +x 'try1' # end of 'try1' fi if test -f 'try2' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'try2'\" else echo shar: Extracting \"'try2'\" \(1043 characters\) sed "s/^X//" >'try2' <<'END_OF_FILE' Xdo 'cterm.pl' || die "$0 can't include cterm.pl\n" ; X X&startCterm(@ARGV) ; X X&initscr ; &nonl ; &cbreak ; &noecho ; X&leaveok($stdscr,0) ; &refresh ; X&keypad($stdscr,1) if defined $curfun{'keypad'} ; X X&editq($curcon{'KEY_UP'}) if defined $curcon{'KEY_UP'} ; X&editq($curcon{'KEY_DOWN'}) if defined $curcon{'KEY_DOWN'} ; X&editq($curcon{'KEY_RET'}) ; X X$japh = 'just another perl hacker' ; X$len = length($japh) ; X X$win = &newwin(5,$len+4,int($LINES/2)-2,int(($COLS-$len)/2)-2) ; X&box($win,ord('|'),ord('-')) ; X&mvwaddstr($win,2,2,$japh) ; X&wrefresh($win) ; X X&mvaddstr(2,4,'quit edit mode by KEY_RET, KEY_DOWN or KEY_UP') ; X X($string,$quitKey) = &edit('hello world',0,4,4,20,'|<>|') ; X X$killchar = &killchar ; X$erasechar = &erasechar ; X X&endwin ; X&finishCterm ; X X$quitKey = &ch2str($quitKey) ; X Xprint "hello again, cterm is gone, we are back in perl\n" ; Xprint "edit returned ($string,$quitKey)\n" ; Xprint "cterm used:\n" ; Xprint "LINES: $LINES\n" ; Xprint "COLS: $COLS\n" ; Xprint "killchar: $killchar\n" ; Xprint "erasechar: $erasechar\n" ; END_OF_FILE if test 1043 -ne `wc -c <'try2'`; then echo shar: \"'try2'\" unpacked with wrong size! fi chmod +x 'try2' # end of 'try2' fi echo shar: End of shell archive. exit 0 -- Henk P. Penning, Dept of Computer Science, Utrecht University. Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands. Telephone: +31-30-534106 e-mail : henkp@cs.ruu.nl (uucp to hp4nl!ruuinf!henkp)