argv@island.uu.net (Dan Heller) (12/06/89)
Submitted-by: uunet!zax!sci!jimmc (Jim McBeath) Posting-number: Volume 5, Issue 37 Archive-name: macstr/part01 #! /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". If this archive is complete, you will ## see the following message at the end: # "End of shell archive." # Contents: README.macrostr xterm.man.diff Imakefile.diff # Makefile.diff ptyx.h.diff charproc.c.diff macrostr.c # Wrapped by jimmc@zax on Mon Nov 13 17:14:21 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f README.macrostr -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README.macrostr\" else echo shar: Extracting \"README.macrostr\" \(553 characters\) sed "s/^X//" >README.macrostr <<'END_OF_README.macrostr' XThe macro string package is intended to allow xterm to generate the character Xsequences for button presses on just about any terminal you can think of. XIt is a general enough mechanism that you may find other uses for it as well. XInstallation requires the addition of one major new file (macrostr.c) and some Xone-line changes to a few other files. See the updated man pages for details Xon how the macro string capability is used. Copyright has been donated to XMIT using their standard copyright notice. X XJim McBeath 13.Nov.89 Xsci!jimmc@decwrl.dec.com END_OF_README.macrostr if test 553 -ne `wc -c <README.macrostr`; then echo shar: \"README.macrostr\" unpacked with wrong size! fi # end of overwriting check fi if test -f xterm.man.diff -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"xterm.man.diff\" else echo shar: Extracting \"xterm.man.diff\" \(14424 characters\) sed "s/^X//" >xterm.man.diff <<'END_OF_xterm.man.diff' X1c1 X< .TH XTERM 1 "25 October 1988" "X Version 11" X--- X> .TH XTERM 1 " 7 November 1989" "X Version 11" X222c222 X< cause the window to be repositioned automatically in the normal postion at the X--- X> cause the window to be repositioned automatically in the normal position at the X264c264 X< This option indicates that a visual bell is prefered over an audible one. X--- X> This option indicates that a visual bell is preferred over an audible one. X286c286 X< This option specifies the prefered size and position of the Tektronix window. X--- X> This option specifies the preferred size and position of the Tektronix window. X290c290 X< This option specifies the prefered position of the icon window. X--- X> This option specifies the preferred position of the icon window. X316c316 X< instead of the user's shell. \fBThis option has been superceeded by the new X--- X> instead of the user's shell. \fBThis option has been superceded by the new X358c358 X< This option specifies the prefered size and position of the VT102 window; X--- X> This option specifies the preferred size and position of the VT102 window; X376c376 X< Specifies the prefered size and position of the application when iconified. X--- X> Specifies the preferred size and position of the application when iconified. X457c457 X< Specifies the prefered size and position of the VT102 window. X--- X> Specifies the preferred size and position of the VT102 window. X460c460 X< Specifies the prefered size and position of the Tektronix window. X--- X> Specifies the preferred size and position of the Tektronix window. X713c713 X< To distinquish a pointer button from a key, the high bit of the character is X--- X> To distinguish a pointer button from a key, the high bit of the character is X785c785 X< X environments differ in their security conciousness. The servers provided X--- X> X environments differ in their security consciousness. The servers provided X911a912,919 X> .B macro-string(\fImacro-string\fB) X> Rebinds the key or key sequence to the macro-string value. X> When this action is executed, the macro string is processed, which normally X> inserts a string into the input stream. X> This capability is useful for emulating the wide variety of character sequences X> that are produced by a button press on various terminals. X> For more details, see the section "MACRO STRINGS" below. X> .TP 15 X994a1003,1368 X> .SH "MACRO STRINGS" X> .PP X> Xterm includes a fairly general macro-string processing capability intended X> to allow emulation of the button-press sequences of just about any terminal X> type. X> The macro-string processor is a simple stack machine which interprets a X> macro string. X> The macro string can contain commands which access state information X> (such as the X and Y location of the mouse), manipulate the stack (such X> as doing arithmetic operations), and insert text into the terminal X> input buffer (which is the desired end result of the macro string). X> There are rudimentary programming commands (conditional execution, X> subroutine calls), built-in primitives and macro strings, and user-definable X> macro strings. X> .PP X> A macro string is interpreted one token at a time. X> Operations are expressed in RPN, i.e. operands first (which are placed onto X> the stack) followed by operation (which operates on the stack). X> White space in a macro string is ignored. X> If there is an error in processing a macro string, the Bell() function X> is called. X> .PP X> There are two data types: integer and string. X> Boolean operations result in an integer where FALSE is represented by X> 0 and TRUE is represented by 1. X> When interpreting an integer as a Boolean, 0 is considered X> FALSE and anything else is considered TRUE. X> When interpreting a string as a Boolean, NULL or the empty string is X> considered FALSE and anything else is considered TRUE. X> .PP X> In the descriptions below, the term TOS represents the value of the X> top item on the stack, TOS-1 is the next-to-top, etc. X> .PP X> The macro-string commands are as follows: X> .TP 15 X> .B "\'string\'" X> Single-quoted string. X> Pushes the quoted string onto the stack. X> The string can contain any character except NULL and single quote. X> There is no backslash notation and no provision for including a single X> quote within a single-quoted string. X> You can use a double-quoted string if you need to include a single X> quote in your string. X> Note also that the various parsers used to load this string (i.e. the X> C compiler if it is a built-in macro string, or the resource manager if X> it is from a resource or default file) can handle backslash notation, so X> you can include control characters in a quoted string. X> .TP 15 X> .ft 3 X> "string" X> .}N X> Double-quoted string. X> Pushes the quoted string onto the stack. X> This behaves in exactly the same way as a single-quoted string, except that X> when using a double-quoted string you can include single quotes in the X> string but not double quotes. X> .TP 15 X> .B "printf formatting" X> You can convert TOS to a string using standard printf formatting commands. X> For example, if TOS is the integer 123, then the command "%04d" would X> replace TOS with the string "0123", and the command "%X" would replace X> TOS with the string "7B". X> The formatting string is only a single "%" sequence, and only converts X> the top item on the stack to a string. X> .TP 15 X> .B "+" X> Add or catenate. X> If TOS and TOS-1 are both integers, X> replaces TOS and TOS-1 with (TOS-1 + TOS). X> If TOS and TOS-1 are both strings, replaces TOS and TOS-1 with X> the catenation of TOS-1 and TOS. X> .TP 15 X> .B "-" X> Subtract. X> Replaces TOS and TOS-1 with (TOS-1 - TOS). X> TOS and TOS-1 must both be integers. X> .TP 15 X> .B "*" X> Multiply. X> Replaces TOS and TOS-1 with (TOS-1 * TOS). X> TOS and TOS-1 must both be integers. X> .TP 15 X> .B "/" X> Integer divide. X> Replaces TOS and TOS-1 with (TOS-1 / TOS). X> TOS and TOS-1 must both be integers. X> .TP 15 X> .B "<<" X> Left shift. X> Replaces TOS and TOS-1 with (TOS-1 << TOS). X> TOS and TOS-1 must both be integers. X> .TP 15 X> .B ">>" X> Right shift. X> Replaces TOS and TOS-1 with (TOS-1 >> TOS). X> TOS and TOS-1 must both be integers. X> .TP 15 X> .B "|" X> Bitwise OR. X> Replaces TOS and TOS-1 with (TOS-1 | TOS). X> TOS and TOS-1 must both be integers. X> .TP 15 X> .B "||" X> Logical OR. X> Replaces TOS and TOS-1 with (TOS-1 || TOS). X> TOS and TOS-1 are independently considered as Booleans. X> .TP 15 X> .B "&" X> Bitwise AND. X> Replaces TOS and TOS-1 with (TOS-1 & TOS). X> TOS and TOS-1 must both be integers. X> .TP 15 X> .B "&&" X> Logical AND. X> Replaces TOS and TOS-1 with (TOS-1 && TOS). X> TOS and TOS-1 are independently considered as Booleans. X> .TP 15 X> .B "^" X> Bitwise XOR. X> Replaces TOS and TOS-1 with (TOS-1 ^ TOS). X> TOS and TOS-1 must both be integers. X> .TP 15 X> .B "^^" X> Logical XOR. X> Replaces TOS and TOS-1 with (TOS-1 ^^ TOS). X> TOS and TOS-1 are independently considered as Booleans. X> .TP 15 X> .B "!" X> Logical NOT. X> Replaces TOS by the logical inverse of TOS when considered as a Boolean. X> .TP 15 X> .B "~" X> Bitwise invert. X> Replaces TOS by the bitwise inversion of TOS. X> TOS must be an integer. X> .TP 15 X> .B number X> Numbers can be entered in decimal, octal or hexadecimal radix. X> A simple string of digits, not starting with a 0, pushes a decimal X> value onto the stack. X> If the first digit in the string is 0 and the remainder of digits are X> between 0 and 7, the number is input as an octal number and pushed onto X> the stack. X> If the first digit in the string is 0 and it is immediately followed X> by x or X, the number is input as a hexadecimal number and pushed onto X> the stack. X> .TP 15 X> .B b X> Pushes the button field from a button event onto the stack. X> .TP 15 X> .B c X> Pushes the cursor column from a key or button event onto the stack. X> The leftmost column is column 0. X> .TP 15 X> .B C X> Pushes the column width of the screen onto the stack. X> .TP 15 X> .B h X> Pushes the pixel height of a character onto the stack. X> .TP 15 X> .B H X> Pushes the pixel height of the screen onto the stack. X> .TP 15 X> .B i X> Places TOS (must be a string) into the terminal input buffer X> and pops it off the stack. X> .TP 15 X> .B k X> Pushes the keycode field from a key event onto the stack. X> .TP 15 X> .B l X> Puts the results of XLookupString on a key event onto the stack. X> If XLookupString returns an error or no string, an empty string is X> pushed onto the stack. X> .TP 15 X> .B M X> Pop TOS (which must be a string) and interpret the macro of that name. X> The macro may be either a primitive or built-in (both compiled into xterm) X> or a user-defined macro. X> User defined macros override built-in macros, but not primitives. X> The list of primitives and built-in macros is given below. X> .TP 15 X> .B r X> Pushes the cursor row from a key or button event onto the stack. X> The topmost row is 0. X> .TP 15 X> .B R X> Pushes the row height of the screen onto the stack. X> .TP 15 X> .B s X> Pushes the state field from a key or button event onto the stack. X> .TP 15 X> .B w X> Pushes the pixel width of a character onto the stack. X> .TP 15 X> .B W X> Pushes the pixel width of the screen onto the stack. X> .TP 15 X> .B x X> Pushes the x pixel value from a key or button event onto the stack. X> .TP 15 X> .B X X> Pushes to x_root pixel value from a key or button event onto the stack. X> .TP 15 X> .B y X> Pushes the y pixel value from a key or button event onto the stack. X> .TP 15 X> .B Y X> Pushes the y_root pixel value from a key or button event onto the stack. X> .TP 15 X> .B Z X> Conditionally returns from (terminates) a macro. X> Pops TOS and interprets it as a Bool; if TRUE, returns from the macro, X> else does nothing. X> .PP X> Primitive functions are compiled into Xterm and can not be overridden. X> The primitives are: X> .TP 15 X> .B error X> Generates an error; calls Bell() and aborts all macro string processing. X> This is typically used with an "if" statement to abort a macro if X> an error condition occurs. X> .TP 15 X> .B exch X> Exchanges TOS with TOS-1. X> .TP 15 X> .B if X> Examines TOS-1 as a Boolean; if TRUE, executes the macro named at TOS, X> else does nothing. X> In either case, the two values are popped off the stack before the X> test is performed. X> .TP 15 X> .B ifElse X> Examines TOS-2 as a Boolean; if TRUE, executes the macro named at TOS-1, X> else executes the macro named at TOS. X> In either case, the three values are popped off the stack before the X> test is performed. X> .TP 15 X> .B limit X> Limits TOS-2 to be between TOS-1 and TOS. X> If TOS-2 is less than TOS-1, replaces it with TOS-1. X> If TOS-2 is greater than TOS, replaces it with TOS. X> All three items must be integers. X> Pops two items off the stack, leaving only the limited number. X> .TP 15 X> .B ord X> Converts a one-character string at TOS to an integer with the X> equivalent integer value (essentially a "scanf %c"). X> .TP 15 X> .B pop X> Pops one item off the stack and discards it. X> .TP 15 X> .B push X> Pushes the top item onto the stack again, duplicating it. X> .TP 15 X> .B tekScale X> Pushes the tekScale field of the screen onto the stack. X> Useful for emulating the Tektronix mode buttons. X> .TP 15 X> .B toBool X> Converts TOS to a Boolean (integer 0 or 1). X> X> .PP X> There are a number of built-in macros, which are simply macro strings X> which are compiled into xterm. X> These built-ins can be overridden by a user defined macro. X> The built-ins are listed below, with the definitions of some given X> as examples. X> .TP 15 X> .B SeikoButton X> Generates the character sequence for button presses on a Seiko terminal. X> There are a number of associated built-ins that are a part of this package: X> SeikoGetX, SeikoGetY, SeikoSub1, SeikoEnd. X> To set up your xterm so that it generates Seiko character sequences for X> the buttons when the shift key is held down, you could add the following X> lines to your resource file: X> .sp X> .Ds X> *VT100.translations: #override \\n\\ X> Shift <BtnDown> : macro-string("'SeikoButton'M") \\n\\ X> Shift <BtnUp> : ignore() X> .De X> .TP 15 X> .B X10Button X> Generates the character sequence that the X10 xterm generated for button X> pushes. X> This macro is implemented with this string: X> .sp X> .Ds X> '\\033[M'i31b+%ci33c+%ci33r+%ci X> .De X> .TP 15 X> .B VT200ButtonPress X> Generates the character sequence for a VT200 button press. X> This macro is implemented with this string: X> .sp X> .Ds X> '\\033['iM31'VT200KeyState'M+b+%ci33c+%ci33r+%ci X> .De X> .TP 15 X> .B VT200KeyState X> Called by the VT200ButtonPress macro. X> This macro is implemented with this string: X> .sp X> .Ds X> s5&s8&2>>+ X> .De X> .TP 15 X> .B TekButton X> Generates the character sequence for a Tektronix button press. X> Associated macros are TekGetBchar, TekGetlbchar, TekUcase, and TekSub1. X> .TP 15 X> .B TestConst X> Generates a character string with a number of screen-dependent values, X> implemented with this string: X> .sp X> .Ds X> 'h='ih%di' w='iw%di' H='iH%di' W='iW%di' R='iR%di' C='iC%di'\\n'i X> .De X> .TP 15 X> .B TestButton X> Generates a character string with a number of position-dependent values, X> suitable for binding to a button, X> implemented with this string: X> .sp X> .Ds X> 'x='ix%di' y='iy%di' X='iX%di' Y='iY%di\\ X> ' r='ir%di' c='ic%di' b='ib%di' s='is%xi'\\n'i X> .De X> .TP 15 X> .B TestKey X> Generates a character string with a number of position-dependent values, X> suitable for binding to a key, X> implemented with this string: X> .sp X> .Ds X> 'x='ix%di' y='iy%di' X='iX%di' Y='iY%di\\ X> ' r='ir%di' c='ic%di' k='ik%di' s='is%xi' l=\\"'ili'\\"\\n'i X> .De X> .PP X> You could add the following bindings to execute the test macros to X> see how the values look: X> .sp X> .Ds X> *VT100.translations: #override \\n\\ X> <Key>F5 : macro-string("'TestConst'M") \\n\\ X> <Key>F6 : macro-string("'TestKey'M") X> .De X> .PP X> User defined macros can be specified in your resource or Xdefaults file. X> Macros are searched for as subresources of the xterm widget, where the X> subobject name is "macroString" and the subresource name is the macro name. X> For example, to define a macro named foo that prints out the string X> "button" and the button number, you could put this line in your resource file: X> .sp X> .Ds X> *VT100.macroString.foo: 'button 'i b%di X> .De X> .PP X> You could then bind this macro to a key with a line like: X> .sp X> .Ds X> *VT100.translations: #override \\n\\ X> <Key>F7 : macro-string("'foo'M") X> .De X> X1125c1499 X< Consortium), Dave Serisky (HP) X--- X> Consortium), Dave Serisky (HP), Jim McBeath (Silicon Compilers) END_OF_xterm.man.diff if test 14424 -ne `wc -c <xterm.man.diff`; then echo shar: \"xterm.man.diff\" unpacked with wrong size! fi # end of overwriting check fi if test -f Imakefile.diff -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Imakefile.diff\" else echo shar: Extracting \"Imakefile.diff\" \(1173 characters\) sed "s/^X//" >Imakefile.diff <<'END_OF_Imakefile.diff' X*** Imakefile.orig Thu May 18 19:57:44 1989 X--- Imakefile Fri Oct 27 13:44:02 1989 X*************** X*** 27,36 **** X /* add -DWTMP and -DLASTLOG if you want them */ X DEFINES = -DMODEMENU -DUTMP -DBcopy=bcopy GettyProgram X SRCS1 = button.c charproc.c cursor.c data.c input.c \ X! main.c menu.c misc.c screen.c scrollbar.c tabs.c \ X TekPrsTbl.c Tekproc.c util.c VTPrsTbl.c X OBJS1 = main.o input.o charproc.o cursor.o util.o tabs.o \ X! screen.o scrollbar.o button.o Tekproc.o misc.o \ X VTPrsTbl.o TekPrsTbl.o data.o menu.o X SRCS2 = resize.c X OBJS2 = resize.o X--- 27,36 ---- X /* add -DWTMP and -DLASTLOG if you want them */ X DEFINES = -DMODEMENU -DUTMP -DBcopy=bcopy GettyProgram X SRCS1 = button.c charproc.c cursor.c data.c input.c \ X! macrostr.c main.c menu.c misc.c screen.c scrollbar.c tabs.c \ X TekPrsTbl.c Tekproc.c util.c VTPrsTbl.c X OBJS1 = main.o input.o charproc.o cursor.o util.o tabs.o \ X! screen.o scrollbar.o button.o Tekproc.o misc.o macrostr.o \ X VTPrsTbl.o TekPrsTbl.o data.o menu.o X SRCS2 = resize.c X OBJS2 = resize.o END_OF_Imakefile.diff if test 1173 -ne `wc -c <Imakefile.diff`; then echo shar: \"Imakefile.diff\" unpacked with wrong size! fi # end of overwriting check fi if test -f Makefile.diff -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Makefile.diff\" else echo shar: Extracting \"Makefile.diff\" \(1055 characters\) sed "s/^X//" >Makefile.diff <<'END_OF_Makefile.diff' X*** Makefile.orig Fri Oct 27 12:58:09 1989 X--- Makefile Fri Oct 27 15:39:17 1989 X*************** X*** 167,176 **** X X DEFINES = -DMODEMENU -DUTMP -DBcopy=bcopy X SRCS1 = button.c charproc.c cursor.c data.c input.c \ X! main.c menu.c misc.c screen.c scrollbar.c tabs.c \ X TekPrsTbl.c Tekproc.c util.c VTPrsTbl.c X OBJS1 = main.o input.o charproc.o cursor.o util.o tabs.o \ X! screen.o scrollbar.o button.o Tekproc.o misc.o \ X VTPrsTbl.o TekPrsTbl.o data.o menu.o X SRCS2 = resize.c X OBJS2 = resize.o X--- 167,176 ---- X X DEFINES = -DMODEMENU -DUTMP -DBcopy=bcopy X SRCS1 = button.c charproc.c cursor.c data.c input.c \ X! macrostr.c main.c menu.c misc.c screen.c scrollbar.c tabs.c \ X TekPrsTbl.c Tekproc.c util.c VTPrsTbl.c X OBJS1 = main.o input.o charproc.o cursor.o util.o tabs.o \ X! screen.o scrollbar.o button.o Tekproc.o misc.o macrostr.o \ X VTPrsTbl.o TekPrsTbl.o data.o menu.o X SRCS2 = resize.c X OBJS2 = resize.o END_OF_Makefile.diff if test 1055 -ne `wc -c <Makefile.diff`; then echo shar: \"Makefile.diff\" unpacked with wrong size! fi # end of overwriting check fi if test -f ptyx.h.diff -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"ptyx.h.diff\" else echo shar: Extracting \"ptyx.h.diff\" \(701 characters\) sed "s/^X//" >ptyx.h.diff <<'END_OF_ptyx.h.diff' X*** ptyx.h.orig Thu May 18 19:56:42 1989 X--- ptyx.h Tue Nov 7 09:23:09 1989 X*************** X*** 191,196 **** X--- 191,202 ---- X int height; X } BitmapBits; X X+ typedef struct _userMacro { X+ struct _userMacro *next; X+ String name; X+ String value; X+ } UserMacro; X+ X #define SAVELINES 64 /* default # lines to save */ X X typedef struct { X*************** X*** 344,349 **** X--- 350,356 ---- X Atom* selection_atoms; /* which selections we own */ X Cardinal sel_atoms_size; /* how many atoms allocated */ X Cardinal selection_count; /* how many atoms in use */ X+ UserMacro *userMacros; /* list of user macro-strings */ X } TScreen; X X /* meaning of bits in screen.select flag */ END_OF_ptyx.h.diff if test 701 -ne `wc -c <ptyx.h.diff`; then echo shar: \"ptyx.h.diff\" unpacked with wrong size! fi # end of overwriting check fi if test -f charproc.c.diff -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"charproc.c.diff\" else echo shar: Extracting \"charproc.c.diff\" \(741 characters\) sed "s/^X//" >charproc.c.diff <<'END_OF_charproc.c.diff' X*** charproc.c.orig Thu May 18 19:58:00 1989 X--- charproc.c Fri Oct 27 13:45:47 1989 X*************** X*** 164,169 **** X--- 164,170 ---- X extern void HandleLeaveWindow(); X extern void HandleFocusChange(); X void HandleKeymapChange(); X+ extern void HandleMacroString(); X extern void HandleModeMenu(); X extern void HandleInsertSelection(); X extern void HandleSelectStart(); X*************** X*** 210,215 **** X--- 211,217 ---- X { "insert", HandleKeyPressed }, X { "insert-selection", HandleInsertSelection }, X { "keymap", HandleKeymapChange }, X+ { "macro-string", HandleMacroString }, X { "mode-menu", HandleModeMenu }, X { "secure", HandleSecure }, X { "select-start", HandleSelectStart }, END_OF_charproc.c.diff if test 741 -ne `wc -c <charproc.c.diff`; then echo shar: \"charproc.c.diff\" unpacked with wrong size! fi # end of overwriting check fi if test -f macrostr.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"macrostr.c\" else echo shar: Extracting \"macrostr.c\" \(24964 characters\) sed "s/^X//" >macrostr.c <<'END_OF_macrostr.c' X/* macrostr.c - handle macro string capability X * X * 26.Oct.89 Jim McBeath Initial definition X */ X X/* X * Copyright 1989 Massachusetts Institute of Technology X * X * Permission to use, copy, modify, distribute, and sell this software and its X * documentation for any purpose is hereby granted without fee, provided that X * the above copyright notice appear in all copies and that both that X * copyright notice and this permission notice appear in supporting X * documentation, and that the name of M.I.T. not be used in advertising or X * publicity pertaining to distribution of the software without specific, X * written prior permission. M.I.T. makes no representations about the X * suitability of this software for any purpose. It is provided "as is" X * without express or implied warranty. X * X * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. X * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES X * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION X * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X * X * Author: Jim McBeath, Silicon Compiler Systems X * sci!jimmc@decwrl.dec.com X */ X X#include <X11/Intrinsic.h> X#include <X11/StringDefs.h> X#include <ctype.h> X#include "ptyx.h" X X#define TOS (stackCount-1) X#define PUSHINT(n) if (!StackPushInt(n)) return FALSE X X/* inverse of CursorX and CursorY macros (except no topline used in Row) */ X#define CursorRow(screen,Y) (((Y) - screen->border)/FontHeight(screen)) X#define CursorCol(screen,X) (((X) - screen->scrollbar - screen->border) \ X / FontWidth(screen)) X Xextern char *malloc(), *realloc(); X Xenum MacStackType { MacStackNull, MacStackInt, MacStackString }; X Xtypedef struct _macstackentry { X enum MacStackType type; X union { X char *s; X int n; X } d; X} MacStackEntry; X X/* The static variables in this module have a lifetime which is limited X * to a single call to HandleMacroString. X */ X Xstatic Widget stackWidget; Xstatic TScreen *stackScreen; Xstatic XEvent *stackEvent; X X/* The value stack used by all of the macro processing functions */ Xstatic int stackAlloc; Xstatic int stackCount; Xstatic MacStackEntry *stack; X X/* A string buffer used by various parsing functions */ Xstatic int stackQAlloc; Xstatic int stackQCount; Xstatic char *Qstr; X X/* forward references for PrimTab */ Xextern int PrimToBool(); Xextern int PrimNot(); Xextern int PrimIfTrue(); Xextern int PrimIfElse(); Xextern int PrimPop(); Xextern int PrimPush(); Xextern int PrimExch(); Xextern int PrimLimit(); Xextern int PrimOrd(); Xextern int PrimReturn(); Xextern int PrimError(); Xextern int PrimTekScale(); X X/* Table of named primitive functions */ Xstatic struct { X char *name; /* name of the primitive function */ X int (*func)(); /* returns TRUE if all OK, FALSE if problem */ X} PrimTab[] = { X {"error", PrimError}, X {"exch", PrimExch}, X {"if", PrimIfTrue}, X {"ifElse", PrimIfElse}, X {"limit", PrimLimit}, X {"ord", PrimOrd}, X {"pop", PrimPop}, X {"push", PrimPush}, X {"tekScale", PrimTekScale}, X {"toBool", PrimToBool}, X}; X X/* Table of built-in macro strings */ Xstatic struct { X char *name; /* name of the built-in macro string */ X char *str; /* contents of the macro string */ X} BuiltinTab[] = { X {"SeikoButton", X"'\033J'i'SeikoGetX'M'SeikoSub1'M'SeikoGetY'M'SeikoSub1'M'SeikoEnd'M"}, X {"SeikoGetX", "x48*w/1890-"}, X {"SeikoGetY", "1537y64*h/-"}, X {"SeikoSub1", X"'push'M'push'M10>>037&0140|%ci5>>037&0100|%ci037&040|%ci"}, X {"SeikoEnd", "' 'i31b3&+%ci'! !\r'i"}, X {"X10Button", "'\033[M'i31b+%ci33c+%ci33r+%ci"}, X {"VT200KeyState", "s5&s8&2>>+"}, X {"VT200ButtonPress", "'\033['iM31'VT200KeyState'M+b+%ci33c+%ci33r+%ci"}, X {"VT200ButtonOther", "'\033['iM32'VT200KeyState'M+3+%ci33c+%ci33r+%ci"}, X {"TekButton", "'TekGetBchar'M%ci\ Xx'tekScale'M/0 4096 1- 'limit'M'TekSu1'M \ X3072 34+ y'tekScale'/- 0 3072 1- 'limit'M'TekSub1'M"}, X {"TekGetBchar", "'TekGetlbchar'M s 1 & 'TekUcase' 'if'M 0x80 |"}, X {"TekGetlbchar", "\ X'r' 'ord'M b 1 == Z 'pop'M \ X'm' 'ord'M b 2 == Z 'pop'M \ X'l' 'ord'M b 3 == Z 'error'M"}, X {"TekUcase", "32 -"}, X {"TekSub1", "'push'M 7>>037&040|%ci 2>>037&040|%ci"}, X {"TestConst", X"'h='ih%di' w='iw%di' H='iH%di' W='iW%di' R='iR%di' C='iC%di'\n'i"}, X {"TestButton", X"'x='ix%di' y='iy%di' X='iX%di' Y='iY%di\ X' r='ir%di' c='ic%di' b='ib%di' s='is%xi'\n'i"}, X {"TestKey", X"'x='ix%di' y='iy%di' X='iX%di' Y='iY%di\ X' r='ir%di' c='ic%di' k='ik%di' s='is%xi' l=\"'ili'\"\n'i"}, X}; X X Xstatic int Xishexalpha(c) Xchar c; X{ X return (c>='a'&&c<='f' || c>='A'&&c<='F'); X} X X/* Value stack manipulation functions */ X Xstatic void XStackClear() /* clear the stack */ X{ X int i; X X for (i=0; i<stackCount; i++) { /* free all strings */ X if (stack[i].type == MacStackString) { X if (stack[i].d.s) X free(stack[i].d.s); X } X } X stackCount = 0; X} X Xstatic void XStackPop(n) Xint n; /* pop N items off the top of the stack */ X{ X while (n>0 && stackCount>0) { X if (stack[TOS].type == MacStackString) { X if (stack[TOS].d.s) X free(stack[TOS].d.s); X } X n--; X stackCount--; X } X} X Xstatic Bool /* TRUE if successful, FALSE it not (no more memory) */ XStackPush(e) XMacStackEntry *e; X{ X int nbytes; X X if (stackCount>=stackAlloc) { X /* need more room */ X if (stackAlloc) X stackAlloc *= 2; X else X stackAlloc = 15; X nbytes = stackAlloc * sizeof(stack[0]); X if (stack) X stack = (MacStackEntry *)realloc((char *)stack,nbytes); X else X stack = (MacStackEntry *)malloc(nbytes); X if (!stack) X return FALSE; X } X stack[stackCount] = *e; /* copy in structure */ X /* note that we do not do any string copies here */ X stackCount++; X return TRUE; X} X Xstatic Bool /* TRUE if successful, FALSE it not (no more memory) */ XStackPushString(s) Xchar *s; /* the string becomes the property of the stack */ X{ X MacStackEntry e; X Bool t; X X e.type = MacStackString; X e.d.s = s; X t = StackPush(&e); X if (!t) { X free(s); /* it's our string - don't leak the memory */ X } X return t; X} X Xstatic Bool /* TRUE if successful, FALSE it not (no more memory) */ XStackPushStringCopy(s) Xchar *s; /* makes a copy of the string to put onto the stack */ X{ X char *newstr; X X newstr = malloc(strlen(s)+1); X if (!newstr) X return FALSE; X strcpy(newstr,s); X return (StackPushString(newstr)); X} X Xstatic Bool /* TRUE if successful, FALSE it not (no more memory) */ XStackPushInt(n) Xint n; X{ X MacStackEntry e; X Bool t; X X e.type = MacStackInt; X e.d.n = n; X t = StackPush(&e); X return t; X} X X X/* String buffer manipulation functions */ X Xstatic void XStackQclear() X{ X stackQCount = 0; X} X Xstatic Bool /* TRUE is successful, FALSE if not (no more memory) */ XStackQchar(c) Xchar c; X{ X int nbytes; X X if (stackQCount>=stackQAlloc) { X /* need more room */ X if (stackQAlloc) X stackQAlloc *= 2; X else X stackQAlloc = 120; X nbytes = stackQAlloc; X if (Qstr) X Qstr = realloc(Qstr,nbytes); X else X Qstr = malloc(nbytes); X if (!Qstr) X return FALSE; X } X Qstr[stackQCount++] = c; X return TRUE; X} X X/* handles quoted strings; parses string and pushes it onto the stack */ X/* Note that we do NOT do any backslash processing */ Xstatic char * /* returns pointer to the closing quote char or NULL on error */ XStackQstr(p,stopchar) Xchar *p; /* pointer to first data char */ Xchar stopchar; /* the character to stop on */ X{ X StackQclear(); X while (*p && *p!=stopchar) { X if (!StackQchar(*p)) X return NULL; /* no more memory */ X p++; X } X if (!*p) X return NULL; /* no terminating quote */ X if (!StackQchar(0)) X return NULL; X if (!StackPushStringCopy(Qstr)) X return NULL; X return p; X} X X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XStackToBool(n) /* converts stack item n to a bool (int 0/1) */ Xint n; X{ X int f; X X switch (stack[n].type) { X case MacStackInt: X stack[n].d.n = !!stack[n].d.n; X break; X case MacStackString: X if (stack[n].d.s && stack[n].d.s[0]) { X f = 1; X } else { X f = 0; X } X if (stack[n].d.s) X free(stack[n].d.s); X stack[n].type = MacStackInt; X stack[n].d.n = f; X break; X default: X return FALSE; X } X return TRUE; X} X X/* Primitives */ X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimToBool() /* converts TOS to a bool (int 0/1) */ X{ X if (stackCount<1) X return FALSE; X return (StackToBool(TOS)); X} X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimNot() /* converts TOS to Bool and then invert it */ X{ X int f; X X if (stackCount<1) X return FALSE; X switch (stack[TOS].type) { X case MacStackInt: X stack[TOS].d.n = !stack[TOS].d.n; X break; X case MacStackString: X if (stack[TOS].d.s && stack[TOS].d.s[0]) { X f = 0; X } else { X f = 1; X } X StackPop(1); X PUSHINT(f); X break; X default: X return FALSE; X } X return TRUE; X} X X/* The IfTrue primitive requires a macro name at TOS and a value at TOS-1. X * Both values are first removed from the stack. X * If the value is TRUE, then the macro is executed, otherwise nothing X * else happens. X */ Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimIfTrue() X{ X char *macroname; X int b,t; X X if (stackCount<2) X return FALSE; X if (stack[TOS].type!=MacStackString) X return FALSE; X macroname = stack[TOS].d.s; X stack[TOS].d.s = 0; X StackPop(1); X if (!PrimToBool()) X return FALSE; /* error testing truth */ X b = stack[TOS].d.n; X StackPop(1); X if (b) X t = StackDoNamedMacro(macroname); X else X t = TRUE; X free(macroname); X return t; X} X X/* The IfElse primitive requires a macro name at TOS, X * a macro name at TOS-1, and a condition value at TOS-2. X * All three items are first removed from the stack. X * If the condition is TRUE, then the macro is which was at TOS-1 is executed, X * otherwise the macro which was at TOS is executed. X * Thus, you first push the condition value, then the name of the TRUE macro, X * then the name of the FALSE macro, then "ifElse", then M. X */ Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimIfElse() X{ X char *truemacro, *falsemacro; X int b,t; X X if (stackCount<3) X return FALSE; X if (stack[TOS].type!=MacStackString || X stack[TOS-1].type!=MacStackString) X return FALSE; X falsemacro = stack[TOS].d.s; X stack[TOS].d.s = 0; X truemacro = stack[TOS-1].d.s; X stack[TOS-1].d.s = 0; X StackPop(2); X if (!PrimToBool()) X return FALSE; /* error testing truth */ X b = stack[TOS].d.n; X StackPop(1); X if (b) X t = StackDoNamedMacro(truemacro); X else X t = StackDoNamedMacro(falsemacro); X free(truemacro); X free(falsemacro); X return t; X} X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimPop() /* throws away the top item on the stack */ X{ X if (stackCount<1) X return FALSE; X StackPop(1); X return TRUE; X} X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimPush() /* duplicates the top item on the stack by pushing a copy */ X{ X if (stackCount<1) X return FALSE; X switch (stack[TOS].type) { X case MacStackInt: X PUSHINT(stack[TOS].d.n); X break; X case MacStackString: X if (!StackPushStringCopy(stack[TOS].d.s)) X return FALSE; X break; X default: X return FALSE; X } X return TRUE; X} X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimExch() /* exchanges the top two items on the stack */ X{ X MacStackEntry e; X X if (stackCount<2) X return FALSE; X e = stack[TOS]; /* structure copy */ X stack[TOS] = stack[TOS-1]; X stack[TOS-1] = e; X return TRUE; X} X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimLimit() /* limits TOS-2 to be between TOS-1 and TOS */ X{ X int high,low; X X if (stackCount<3) X return FALSE; X if (stack[TOS].type != MacStackInt || X stack[TOS-1].type != MacStackInt || X stack[TOS-2].type != MacStackInt) X return FALSE; X high = stack[TOS].d.n; X low = stack[TOS-1].d.n; X StackPop(2); X if (stack[TOS].d.n>high) X stack[TOS].d.n = high; X else if (stack[TOS].d.n<low) X stack[TOS].d.n = low; X return TRUE; X} X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimOrd() /* converts a char (string of len 1) to an int */ X{ X int ord; X X if (stackCount<1) X return FALSE; X if (stack[TOS].type != MacStackString || X strlen(stack[TOS].d.s)!=1) X return FALSE; X ord = stack[TOS].d.s[0]; X StackPop(1); X PUSHINT(ord); X return TRUE; X} X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimError() /* generates an error (aborts) */ X{ X return FALSE; /* simple enough */ X} X Xstatic Bool /* returns TRUE if all OK, FALSE if any problems */ XPrimTekScale() /* generates an error (aborts) */ X{ X PUSHINT(TekScale(stackScreen)); X return TRUE; X} X X X/* Macro processing functions */ X Xtypedef struct { X char *value; X} UmInfo, *UmInfoPtr; Xstatic XtResource umresource[] = { X { "", "", XtRString, sizeof(String), X XtOffset(UmInfoPtr,value),XtRString,NULL}, X}; X Xstatic String /* returns macro string or NULL if not found */ XStackFindUserMacro(name) XString name; X{ X UserMacro *umlist; X UmInfo uminfo; X X umlist = stackScreen->userMacros; X for (; umlist; umlist=umlist->next) { X if (strcmp(umlist->name,name)==0) X return(umlist->value); X } X /* not a macro that is already loaded, see if we can load it */ X umresource[0].resource_name = name; X umresource[0].resource_class = name; X XtGetSubresources(stackWidget,(caddr_t)&uminfo, X "macroString","MacroString", X umresource,(Cardinal)1,(ArgList)NULL,(Cardinal)0); X if (!uminfo.value) X return NULL; /* can't find the macro */ X umlist = (UserMacro *)malloc(sizeof(UserMacro)); X if (!umlist) X return NULL; /* can't get memory */ X umlist->name = malloc(strlen(name)+1); X if (!umlist->name) { X free((char *)umlist); X return NULL; X } X umlist->value = malloc(strlen(uminfo.value)+1); X if (!umlist->value) { X free(umlist->name); X free((char *)umlist); X return NULL; X } X strcpy(umlist->name,name); X strcpy(umlist->value,uminfo.value); X umlist->next = stackScreen->userMacros; X stackScreen->userMacros = umlist; X return(umlist->value); X} X X/* handles the "%" formatting; parses format string and operates on stack */ Xstatic char * /* returns pointer to the last char of the fmt string or NULL */ XStackFstr(p) Xchar *p; /* pointer to first char of formatting string */ X{ X static char *fmtchars="-+#*.0123456789"; X char *buf; X X if (stackCount<1) X return NULL; X StackQclear(); X if (!StackQchar('%')) X return NULL; X while (*p && (index(fmtchars,*p))) { X if (!StackQchar(*p)) X return NULL; X p++; X } X if (!StackQchar(*p)) /* add the final formatting char */ X return NULL; X if (!StackQchar(0)) /* null terminate the format string */ X return NULL; X switch (*p) { X case 0: X return NULL; X case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': case 'c': X if (stack[TOS].type!=MacStackInt) X return NULL; X buf = malloc(100); X if (!buf) X return NULL; X sprintf(buf,Qstr,stack[TOS].d.n); X break; X case 's': X if (stack[TOS].type!=MacStackString) X return NULL; X buf = malloc(strlen(stack[TOS].d.s)+100); X if (!buf) X return NULL; X sprintf(buf,Qstr,stack[TOS].d.s); X break; X default: X return NULL; X } X StackPop(1); /* get rid of converted value */ X if (!StackPushStringCopy(buf)) { X free(buf); X return NULL; X } X free(buf); X return p; X} X X/* handles primitives */ XBool /* returns TRUE if OK, FALSE is any errors */ XStackDoPrimitive(name) Xchar *name; X{ X int i; X X for (i=0; i<XtNumber(PrimTab); i++) { X if (strcmp(PrimTab[i].name,name)==0) { X return (*PrimTab[i].func)(); X } X } X return FALSE; X} X X/* handles built-in macro strings */ XBool /* returns TRUE if OK, FALSE is any errors */ XStackDoBuiltin(name) Xchar *name; X{ X int i; X X for (i=0; i<XtNumber(BuiltinTab); i++) { X if (strcmp(BuiltinTab[i].name,name)==0) { X return ProcessMacroString(BuiltinTab[i].str); X } X } X return FALSE; X} X X/* handles user defined macro strings */ XBool /* returns TRUE if OK, FALSE is any errors */ XStackDoUserMacro(name) Xchar *name; X{ X String macrostr; X X macrostr = StackFindUserMacro(name); X if (!macrostr) X return FALSE; /* no such macro */ X return ProcessMacroString(macrostr); X} X X/* handles macro as named at TOS */ XBool /* returns TRUE if OK, FALSE if any errors */ XStackDoMacro() X{ X char *macroname; X int t; X X if (stackCount<1 || stack[TOS].type!=MacStackString) X return FALSE; /* no macro name */ X macroname = stack[TOS].d.s; X stack[TOS].d.s = 0; X StackPop(1); /* remove the macro name from the stack */ X t = StackDoNamedMacro(macroname); X free(macroname); X return t; X} X X/* handles macros (primitives, built-in macros, or user macros) */ XBool /* returns TRUE if OK, FALSE if any errors */ XStackDoNamedMacro(macroname) XString macroname; X{ X /* User macros can override builtin macro strings, but not primitives */ X if (StackDoPrimitive(macroname) || X StackDoUserMacro(macroname) || X StackDoBuiltin(macroname)) { X return TRUE; X } X return FALSE; /* no such macro */ X} X Xstatic int /* returns TRUE if all OK, FALSE if problem (syntax, no memory) */ XProcessMacroString(macrostring) Xchar *macrostring; X{ X char *p; X char *newstr; X int newnum; X int l; X int n; X Bool b; X int radix, hc; X KeySym ks; X char buf[100]; X X for (p=macrostring;*p;p++) { /* process commands */ X switch (*p) { X case ' ': /* ignore spaces */ X break; X case '"': /* quoted string */ X case '\'': X p = StackQstr(p+1,*p); X if (!p) X return FALSE; /* error */ X break; X case '%': /* formatted print onto TOS */ X p = StackFstr(p+1); X if (!p) X return FALSE; /* error */ X break; X case '+': /* add two numbers or cat two strings */ X if (stackCount<2) X return FALSE; X if (stack[TOS].type == MacStackString && X stack[TOS-1].type == MacStackString) { X l = strlen(stack[TOS].d.s) + X strlen(stack[TOS-1].d.s) + 1; X newstr = malloc(l); X if (!newstr) X return FALSE; X strcpy(newstr,stack[TOS-1].d.s); X strcat(newstr,stack[TOS].d.s); X StackPop(1); X free(stack[TOS].d.s); X stack[TOS].d.s = newstr; X } X else if (stack[TOS].type == MacStackInt || X stack[TOS-1].type == MacStackInt) { X newnum = stack[TOS-1].d.n + stack[TOS].d.n; X StackPop(1); X stack[TOS].d.n = newnum; X } X else X return FALSE; X break; X case '-': /* subtract two numbers */ X if (stackCount<2) X return FALSE; X if (stack[TOS].type == MacStackInt || X stack[TOS-1].type == MacStackInt) { X newnum = stack[TOS-1].d.n - stack[TOS].d.n; X StackPop(1); X stack[TOS].d.n = newnum; X } X else X return FALSE; X break; X case '*': /* multiply two numbers */ X if (stackCount<2) X return FALSE; X if (stack[TOS].type == MacStackInt || X stack[TOS-1].type == MacStackInt) { X newnum = stack[TOS-1].d.n * stack[TOS].d.n; X StackPop(1); X stack[TOS].d.n = newnum; X } X else X return FALSE; X break; X case '/': /* divide two numbers */ X if (stackCount<2) X return FALSE; X if (stack[TOS].type == MacStackInt || X stack[TOS-1].type == MacStackInt) { X newnum = stack[TOS-1].d.n / stack[TOS].d.n; X StackPop(1); X stack[TOS].d.n = newnum; X } X else X return FALSE; X break; X case '<': /* left shift (<<) */ X if ((*(++p))!='<') X return FALSE; X if (stackCount<2) X return FALSE; X if (stack[TOS].type == MacStackInt && X stack[TOS-1].type == MacStackInt) { X newnum = stack[TOS-1].d.n << stack[TOS].d.n; X StackPop(1); X stack[TOS].d.n = newnum; X } X else X return FALSE; X break; X case '>': /* right shift (>>) */ X if ((*(++p))!='>') X return FALSE; X if (stackCount<2) X return FALSE; X if (stack[TOS].type == MacStackInt && X stack[TOS-1].type == MacStackInt) { X newnum = stack[TOS-1].d.n >> stack[TOS].d.n; X StackPop(1); X stack[TOS].d.n = newnum; X } X else X return FALSE; X break; X case '|': /* logical or bitwise OR */ X if (stackCount<2) X return FALSE; X if (p[1]=='|') { /* logical */ X p++; X if (!(StackToBool(TOS) && StackToBool(TOS-1))) X return FALSE; X newnum = stack[TOS-1].d.n || stack[TOS].d.n; X } else { /* bitwise */ X if (stack[TOS].type != MacStackInt || X stack[TOS-1].type != MacStackInt) X return FALSE; X newnum = stack[TOS-1].d.n | stack[TOS].d.n; X } X StackPop(1); X stack[TOS].d.n = newnum; X break; X case '&': /* logical or bitwise AND */ X if (stackCount<2) X return FALSE; X if (p[1]=='&') { /* logical */ X p++; X if (!(StackToBool(TOS) && StackToBool(TOS-1))) X return FALSE; X newnum = stack[TOS-1].d.n && stack[TOS].d.n; X } else { /* bitwise */ X if (stack[TOS].type != MacStackInt || X stack[TOS-1].type != MacStackInt) X return FALSE; X newnum = stack[TOS-1].d.n & stack[TOS].d.n; X } X StackPop(1); X stack[TOS].d.n = newnum; X break; X case '^': /* logical or bitwise XOR */ X if (stackCount<2) X return FALSE; X if (p[1]=='^') { /* logical */ X p++; X if (!(StackToBool(TOS) && StackToBool(TOS-1))) X return FALSE; X newnum = stack[TOS-1].d.n ^ stack[TOS].d.n; X } else { /* bitwise */ X if (stack[TOS].type != MacStackInt || X stack[TOS-1].type != MacStackInt) X return FALSE; X newnum = stack[TOS-1].d.n ^ stack[TOS].d.n; X } X StackPop(1); X stack[TOS].d.n = newnum; X break; X case '!': /* logical not */ X if (!PrimNot()) X return FALSE; X break; X case '~': /* bitwise invert */ X if (stackCount<1) X return FALSE; X if (stack[TOS].type == MacStackInt) { X newnum = ~stack[TOS-1].d.n; X stack[TOS].d.n = newnum; X } X else X return FALSE; X break; X case '0': case '1': case '2': case '3': case '4': X case '5': case '6': case '7': case '8': case '9': X newnum = 0; X if ((*p)=='0') { X if (p[1]=='x' || p[1]=='X') { X radix = 16; X p+=2; X } X else X radix = 8; X } X else X radix = 10; X while (isdigit(*p) || (radix==16&&ishexalpha(*p))) { X newnum *= radix; X if (radix==16&&ishexalpha(*p)) { X hc = *p; X if (islower(hc)) X hc = toupper(hc); X newnum += hc - 'A' + 10; X } X else X newnum += *p - '0'; X p++; X } X --p; /* have to leave it pointing to last char */ X PUSHINT(newnum); X break; X case 'b': /* put button field from event onto stack */ X PUSHINT(stackEvent->xbutton.button); X break; X case 'c': /* put cursor col onto stack (0 is leftmost) */ X PUSHINT(CursorCol(stackScreen,stackEvent->xbutton.x)); X break; X case 'C': /* put number of cols on screen onto stack */ X PUSHINT(stackScreen->max_col+1); X break; X case 'h': /* put pixel height of a char on stack */ X PUSHINT(FontHeight(stackScreen)); X break; X case 'H': /* put pixel height of screen on stack */ X PUSHINT(stackScreen->fullVwin.height); X break; X case 'i': /* send TOS as input */ X if (stackCount<1) X return FALSE; X if (stack[TOS].type == MacStackString) X StringInput(stackScreen,stack[TOS].d.s); X else X return FALSE; X StackPop(1); X break; X case 'k': /* put keycode field from event onto stack */ X PUSHINT(stackEvent->xkey.keycode); X break; X case 'l': /* put results of XLookupString on stack */ X n = XLookupString(stackEvent,buf,sizeof(buf)-1,&ks,0); X if (n>0) { X newstr = malloc(n+1); X if (!newstr) X return FALSE; X strcpy(newstr,buf); X if (!StackPushString(newstr)) X return FALSE; X } else { /* no translation, use null string */ X if (!StackPushStringCopy("")) X return FALSE; X } X break; X case 'M': /* execute macro */ X if (!StackDoMacro()) X return FALSE; X break; X case 'r': /* put cursor row onto stack (0 is topmost) */ X PUSHINT(CursorRow(stackScreen,stackEvent->xbutton.y)); X break; X case 'R': /* put number of rows on screen onto stack */ X PUSHINT(stackScreen->max_row+1); X break; X case 's': /* put state field from event onto stack */ X PUSHINT(stackEvent->xbutton.state); X break; X case 'w': /* put pixel width of a char on stack */ X PUSHINT(FontWidth(stackScreen)); X break; X case 'W': /* put pixel width of screen on stack */ X PUSHINT(stackScreen->fullVwin.width); X break; X case 'x': /* put x pixel value of cursor on stack */ X PUSHINT(stackEvent->xbutton.x - stackScreen->border - X stackScreen->scrollbar); X break; X case 'y': /* put y pixel value of cursor on stack */ X PUSHINT(stackEvent->xbutton.y - stackScreen->border); X break; X case 'X': /* put x_root pixel value of cursor on stack */ X PUSHINT(stackEvent->xbutton.x_root); X break; X case 'Y': /* put y_root pixel value of cursor on stack */ X PUSHINT(stackEvent->xbutton.y_root); X break; X case 'Z': /* conditional return/end of macro */ X if (stackCount<1) X return FALSE; /* error */ X if (!PrimToBool()) X return FALSE; /* error testing truth */ X b = stack[TOS].d.n; X StackPop(1); X if (b) X return TRUE; /* if true, end of this macro */ X /* else do nothing */ X break; X default: X return FALSE; X } X } X return TRUE; /* finished without errors */ X} X X/* This is the action function called from the translation table */ Xvoid XHandleMacroString(w,event,params,param_count) XWidget w; XXEvent *event; XString *params; Xint *param_count; X{ X X if (*param_count != 1) X return; X StackClear(); /* clear the stack machine */ X stackScreen = &((XtermWidget)w)->screen; X stackWidget = w; X stackEvent = event; X if (!ProcessMacroString(params[0])) { X Bell(); /* some sort of error */ X } X} X X/* end */ END_OF_macrostr.c if test 24964 -ne `wc -c <macrostr.c`; then echo shar: \"macrostr.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0