Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (02/12/90)
Submitted-by: micke@slaka.sirius.se (Mikael Karlsson) Posting-number: Volume 90, Issue 070 Archive-name: util/snap-1.4/part04 #!/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 archive 4 (of 4)." # Contents: snap.doc source/snap.c # Wrapped by tadguy@xanth on Sun Feb 11 17:48:49 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'snap.doc' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'snap.doc'\" else echo shar: Extracting \"'snap.doc'\" \(22295 characters\) sed "s/^X//" >'snap.doc' <<'END_OF_FILE' X Snap 1.4 X ======== X (c) Mikael Karlsson 1989 X Keymap inverting courtesy of Jim Mackraz X X XIs it Public Domain? X X Snap is NOT Public Domain. Snap is 'Freely distributable X copyrighted software with a shareware option'. X X "Permission is hereby granted to copy Snap provided that X the copyright notice and this document is left intact. X Copies may not be made for profit." X X I don't know if the above should hold in court but what X I mean is: Copy Snap if you want to but don't make a X business of it. It is of course free to include it on X public domain disks or putting it on a BBS. X If you find Snap useful, please feel free to send a X donation ($10 is a nice round number) or a nice program (PD). X Or you can buy me a beer or two when we meet. X If you wish to include Snap with a commercial product, X please contact me first. I just want to make sure that X my ego can stand for it. Of course it would also be nice X with a registred copy of the product. X (How about including it with a '030 card? ;-) X X Also read this message that Jim Mackraz sent to me regarding X some code used in Snap: X X "You may use ikm.c in your product Snap. X You may not distribute the source to ikm.c for profit, X and any distribution of ikm.c must retain the original X copyright message. X X You should also be warned that IKM() has not been X substantially verified in either design or implementation, X and that it will be made obsolete in version V1.4 by a X new OS function call. X X There is no explicit or implied guarantee that ikm.c contains X only supported algorithms. It may have problems in a future X release of the system. X X jimm X X Jim Mackraz X Aug 18, 1989" X X XWhat is it? X X Snap is the perfect tool for the lazy typer. Isn't it X irritating when you look at something on the screen X and think: "That is what I'm going to type."? X What if you could just point at it and get the computer to X type it for you? That's where Snap comes to the rescue. X Another thing that irritates me is that I'm sitting in X front of THE computer and still I must have pen and X paper available to scribble down something from the screen X that I know I will need later. Snap provides a solution X to that problem also. Just frame it and Snap creates a X window with a copy of the screen contents. Perfect for X snapping text from later on. This is another idea borrowed X from the computer scientists at Xerox Palo Alto Research X Center (you know, the ones who invented the mouse, windows, X icons and stuff like that). X X XWhy use Snap instead? X X a. Snap finds out the character coordinates automatically. X b. Snap uses the RastPort's current font, not just Topaz 8. X c. Snap was written by me. X d. Snap supports all fixed width fonts with width and height<16. X e. Snap supports accented characters (128-255). X f. Snap supports keymaps, thanks to Jim Mackraz. X g. Snap does both column and text oriented snapping. X h. Snap snaps graphics. X i. Snap uses the clipboard, making it compatible with TxED (and NotePad). X j. Snap understands inverted characters. X k. Snap understands bold characters. X l. Snap understands underlined characters X m. Snap does word oriented snapping. X n. Snap has ants. X o. Snap has a key combination to do insert. X p. Snap supports Xerox style snapping with immediate insert. X q. Snap prepends and appends characters. X r. Snap saves graphics. X s. Snap caches the character offsets between windows. X t. Snap joins long lines. X u. Snap supports ARexx to read and set prepend and append strings. X v. Snap handles an extra pixel line between character rows. X X XStarting and Stopping X X Start Snap with 'snap'. That's it. Snap detaches itself X from the CLI, making it possible to close the CLI. X Make sure that you have 'clipboard.device' in devs:. X To get rid of Snap, execute 'snap -Q' (or snap QUIT). X Note that you can't remove Snap if you have any 'snapped' X windows left. X X XCommand line arguments X X Snap accepts a couple of command line arguments. You can X use either unix or Amiga style arguments. X XX is hex. NN is decimal. str is a string. X X Usage: X snap -pNN -tXX -gXX -iXX -wXX -Pstr -Astr -cNN -lNN -aXXXX X -x -X -e -E -r -R -j -J -uN -bXX -oNN -CNN -BNN -Q X or X snap PRIORITY/k TEXTQUAL/k GFXQUAL/k INSERTKEY/k CWKEY/k X PREPEND/k APPEND/k CHARDELAY/k LINEDELAY/k CRAWLPTRN/k X XEROX/s NOXEROX/s EARLYPATCH/s NOEARLYPATCH/s STARTUNIT/k X TRUEUNDERSCORE/k FAKEUNDERSCORE/s JOINLONG/s NOJOINLONG/s X PLANEMASK/k GADOFFSET/k CACHESIZE/k BADCHAR/s QUIT/s X X -pNN X PRIORITY NN X where NN is the priority to use when installing X the input handler. Default is 51. Note that it's X not possible to change the priority of the input X handler while Snap is running. X -tXX X TEXTQUAL XX X where XX is the text qualifier to use in text X operations. Default is the left Amiga key. X -gXX X GFXQUAL XX X where XX is the graphics qualifier to use in X graphics operations. Default is the right Amiga key. X -iXX X INSERTKEY XX X where XX is the raw key code for the key to be used X together with the left Amiga key as insert key. X Use together with Shift to get modidified inserts. X Use 0 to disable. Default is hex 17 ("I"). X -wXX X CWKEY XX X where XX is the raw key code for the key to be used X together with the left Amiga key to open the Snap X control window. Default is hex 11 ("W"). X -Pstr X PREPEND str X where str is the string that will be inserted in X front of every line in a modified insert. Max X length of the string is 16. Default is "> ". X -Astr X APPEND str X where str is the string that will be inserted after X every line in a modified insert. Max length of the X string is 16. Default is "". X -cNN X CHARDELAY NN X where NN is the amount of time that Snap should X wait after each character inserted into the input X stream. Default is 0. X -lNN X LINEDELAY NN X where NN is the amount of time that Snap should X wait after each carriage return inserted into the X input stream. Default is 0. X -aXXXX X CRAWLPTRN XXXX X where XXXX is a 16 bit number that specifies the X pattern for the crawling ants. Use FFFF to turn X the crawling off. If you specify 0 as the crawl X pattern, Snap will use different patterns for X each snapping mode (box/char/word/line). X Default is 7777. X -x X XEROX X tells Snap to use Xerox style snapping instead. X The snapped text is inserted immediately it has X been snapped. X -X X NOXEROX X turns off Xerox style snapping. X -e X EARLYPATCH X tells Snap to patch dangerous functions as soon as X the text qualifier goes down. This is done automatically X when you use Xerox style snapping. X -E X NOEARLYPATCH X turns off early patching. This is default. X -j X JOINLONG X tells Snap to join long lines. This means that Snap X joins (removes the line feed between) two lines if X the first line has a non-blank in the last position. X This is not done in rectangular snapping. X -J X NOJOINLONG X disables the join-long-lines behavior. This is default. X -uN X STARTUNIT N X tells Snap which unit to use when you start snapping. X 0 is rectangular snapping (FRAME). X 1 is character snapping (CHAR). Default is 0. X -r X TRUEUNDERSCORE X tells Snap to do true checking of underscores when X snapping characters. X -R X FAKEUNDERSCORE X turns off true checking of underscores. Instead Snap X just skips the underscore line and hopes that the rest X of the character will provide correct matching. This X option is provided since there is a bug in the rendering X of underscored characters. X -bXX X PLANEMASK XX X where XX is the bit plane mask used when drawing the X selection frame for character snapping. This does not X affect graphics snapping. Default is 1. X -oNN X GADOFFSET NN X where NN is the offset for the save gadget. This may X be necessary to use if you use some kind of iconifier X program that puts a gadget where Snap usually puts the X save gadget. Default is 52. X -CNN X CACHESIZE NN X where NN is the number of windows that Snap will cache X character offsets for. Specifying a new value while Snap X is running means that you increase the cache size by N. X Default size is 10, default increase is 0. X -BNN X BADCHAR NN X where NN is the ascii value of the character that will X be used when Snap doesn't recognize a character. X Default is 63, a '?'. X -Q X QUIT X removes Snap. X XQUALIFIERS (always entered in HEX) (This list borrowed from Matt Dillon) X X 0001 Left Shift X 0002 Right Shift X 0004 Caps Lock X 0008 Control X 0010 Left Alt X 0020 Right Alt X 0040 Left Amiga Key X 0080 Right Amiga Key X 0100 Numeric Key Pad Key (not useful) X 0200 Repeat (not useful) X 0400 Interrupt (not useful) X 0800 Multibroadcast (not useful) X 1000 Middle Mouse Button (not normally implemented by intuition) X 2000 Right Mouse Button X 4000 Left Mouse Button X X Note: Combinations are allowed, in which case any one of the X elected qualifiers along with the left, right mouse button X will cause the appropriate action to occur. X X Some useful raw key codes: X 17 I seems to become the Amiga standard X 34 V for you Macintosh freaks X 15 Y good ol' Emacs X X XModified inserts X X Modified insert means that extra characters are added in front of X and after each line as it is inserted. The characters in front X are set via the -P/PREPEND command line argument, the characters X after via the -A/APPEND command line argument. X These strings can also be set from ARexx using the commands X 'PREPEND newstring' and X 'APPEND newstring'. X These commands should be addressed to Snap using the ARexx command X 'ADDRESS SNAP'. X The old string is returned in the RESULT variable, provided that X 'OPTIONS RESULTS' is given. X If no newstring is given then no change is made. X A small example: X X /* Change PREPEND and APPEND strings for my mail answering program */ X X PARSE ARG ReplyTo X X OPTIONS RESULTS X X ADDRESS SNAP 'prepend' ReplyTo'>' X oldprepend = RESULT X ADDRESS SNAP 'append' "" X oldappend = RESULT X X XDelays X X The character and line delay may be necessary with some programs X that can't handle the amount of characters the Snap insert into X the input stream. CygnusEd is known to have problems with this. X TxED and UEdit handles inserted characters very nicely. X The delay is specified in milliseconds, eg a value of 1000 gives X a delay of 1 second. X X XWatch out for X X The Early Patch behavior may cause problems if you use the Left X Amiga key as the text qualifier together with MachII. What X happens is that MachII can't activate a new window when you do X a Left Amiga-M. X Underscored characters can give problems. Apart from the bug X mentioned above there's another problem. In some fonts the X underscore character (_) and an underscored space looks the X same. Snap tries to be smart and usually gets it right. The X algorithm used is the following: X An underscore/underscored space is interpreted as an underscored X space if the previous character was underscored, otherwise it's X interpreted as a true underscore character. X X XSnapping X X Snapping comes in two flavors; characters and graphics. X Snapping graphics simply means that you can frame an X area on screen and that area is copied into a window. X Character snapping can be made in four different ways: X * rectangular snapping X * character oriented snapping X * word oriented snapping X * line oriented snapping X X Rectangular snapping makes it possible to snap a column X of text. A carriage return is inserted after each row, X except the last one. X X Line oriented snapping is much the same as rectangular X snapping, except that the width of the rectangle is the X width of the window. X X Character oriented snapping is much harder to explain than X to use. Character oriented snapping starts at one character, X extends to the right edge of the window, goes on with X complete lines, and ends at another character. The select box X can look like this: ________________________ X __________________| | X | | X | __________________________| X |________________| X X or like this: _________ X _____ |_________| X |_____| X X and of course like this: ________________ X |________________| X X Word oriented snapping works the same way as character X oriented, except that you can only extend the selection X word by word. A word is defined as non-blanks surrounded X by blanks. X X X Let's define some actions used when controlling snap. X X CLICK X 1. Press the mouse button. X 2. Release the mouse button. X X MOVE X 1. Move the mouse. X X PREPARE_TEXT X 1. If you are using Xerox style snapping, make sure that your X intended destination window is active. X 2. Press and hold the text qualifier (Default: Left Amiga key). X 3. MOVE to the first character you want to copy. X X PREPARE_GFX X 1. Press and hold the graphics qualifier (Default: Right Amiga key). X 2. MOVE to the upper left corner of the area you want to copy X X EXTEND X 1. MOVE X 5. (Press and) Release the mouse button. X X END X 1. Release the mouse button. X 2. Release the qualifier. X X CANCEL X 1. Release the qualifier. X 2. Release the mouse button. X X X Ways to use these actions: X This is with starting unit FRAME. Selecting starting unit CHAR will X skip rectangular snapping and take you directly to character oriented X snapping. To do rectangular snapping you have to click through char, X word and line oriented back to rectangular snapping. X X To do rectangular snapping: X 1. PREPARE_TEXT. X 2. Press the left mouse button. X 3. MOVE. X 4. EXTEND until satisfied. X 5. END or CANCEL. X X To do character oriented snapping X 1. PREPARE_TEXT. X 2. CLICK the left mouse button. X 3. EXTEND until satisfied. X 4. END or CANCEL. X X To do word oriented snapping X 1. PREPARE_TEXT. X 2. Double-CLICK left mouse button. X 3. EXTEND until satisfied. X 4. END or CANCEL. X X To do line oriented snapping X 1. PREPARE_TEXT. X 2. Triple-CLICK left mouse button. X 3. EXTEND until satisfied. X 4. END or CANCEL. X X To insert snapped characters (BKSYSBUF "You know ;-)") X 1. PREPARE_TEXT. X 2. CLICK the right mouse button. X or X 1. Press and hold the left amiga key. X 2. Type the insert key as specified with -i (Default "I"). X X To insert snapped characters including prepend and append strings X 1. Press and hold the left amiga key and either shift key. X 2. Type the insert key as specified with -i (Default "I"). X X To abort insertion X 1. CLICK the left mouse button. X X To snap graphics X 1. PREPARE_GFX. X 2. Press the left mouse button. X 3. MOVE. X 4. EXTEND until satisfied. X 5. END or CANCEL. X X To open the Snap Control Window X 1. Press and hold the left amiga key. X 2. Type the control window key as specified with -w (Default "W"). X X When snapping text you can go directly from snapping to X inserting by replacing "END or CANCEL" above with X "Release left mouse button - CLICK right mouse button". X If you are using Xerox style snapping, the snapped text X will be inserted as soon as you END. X When selecting snapping unit a fourth click takes you X back to character oriented snapping. Each click steps X one unit. Note that rectangular snapping only is available X if you MOVE before you release the mouse button. X X XSnapping characters, character coordinates and caching X X You must always start snapping at a character, otherwise X Snap won't get the coordinates right. This applies to all X kinds of snapping including line snapping. X Snap caches the character coordinates for the N last used X windows, where N is specified by the -C/CACHESIZE parameter. X When you start snapping in a window Snap checks it's cache X to see whether you have snapped in this window before. X If the window is in the cache then Snap first tries to find X a character at the previous coordinates. If no character is X found at the cached coordinates then Snap goes through the X complete lookup process. Of course this is transparent to X the user, so you don't have to worry about it. The size of X the cache can be specified by the user and is managed on a X Least Recently Used basis. X The caching makes it possible for Snap to get the correct X character coordinates even if you start snapping on a space, X provided that you've snapped in that window before. X X Trailing blanks are removed on each line when you're snapping X characters, words or lines, but not when doing rectangular X snapping. Trailing blanks are only removed in line mode if X you're snapping a single line. X X XSnapping and Saving Graphics X X Windows with graphic snaps are always opened on the Workbench X screen. If you've snapped graphics from a screen with different X colors then you can switch to the graphic snap's original colors X by holding down the left mouse button inside the snap window. X Saving of graphics is done via the Snap Control Window (SCW). X To the left of a Snap window's window-to-front and window-to-back X gadgets is a small gadget that looks like a disk. Clicking this X disk gadget has different effects according to a two conditions. X X SCW Graphics Window X not open not selected Opens the SCW, selects the Graphics Window X open not selected Selects the Graphics Window. X open selected Saves the contents of the Graphics Window X X The Snap Control Window looks something like this: X _______________________________ X |x|Snap_Control_Window________||| X | ____ __________________ | X ||Save| as |Name gadget | | X | ~~~~ ~~~~~~~~~~~~~~~~~~ | X | Transparent color |0~~| | X | ~~~ | X ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ X The Save gadget will be ghosted if no window is selected. X Clicking the Save gadget will save the contents of the X selected Graphics Window as an IFF file. X The Transparent color gadget is used to specify which color X will be transparent in the saved IFF file. X The Name gadget is used to specify the name of the IFF file X to save. The Name gadget is a string gadget if arp.library X isn't available. If arp.library is available it will be a X click-gadget that brings up an Arp File Requester. X X XCompiling X X A 'makefile' is provided. Depending on which compiler you X use, remove and insert '#'s. X I seem to have some problem with the detaching when using X Lattice. Everything works ok, except that you can't close X the CLI-window. If anybody solves it, I'd be very grateful X to know about it. X X XSome things to remember X X a. The text is sent to the active window. Make sure that X the correct window is active. X b. Don't interfere when the text is being inserted. Any key X pressed by you will be inserted in the middle of the text X being inserted. X c. Snap begins with an attempt to find the character coordinates. X Therefore if you begin snapping on a space, Snap will almost X certainly get the wrong coordinates, unless Snap has cached X the character coordinates from a previous snap. X d. To be able to do Xerox style snapping, Snap disables X ActivateWindow when the text qualifier is held down. X By doing this Snap makes sure that the destination window X remains active when you move out of it, even if you are X using DMouse or another Sun mouse utility. X X XBugs X X Of course, what did you think. Well, as far as I know there X are no explicit bugs. Oh yes, there is one that I don't know X how to solve. The problem is that some font editors optimize X the character image data. The result is that two characters X with the same image (e.g. I and l in some fonts) uses the X same image data, thereby making it impossible for Snap to X determine which character was printed in the first place. X This can be solved by editing the font so that each character X is unique. X X XAcknowledgements X X Thanks to: X X o Amiga-Lorraine for the machine. X o Jim Mackraz for the keymap inverting code. X o Radical Eye Software for "minrexx". X o William Hawes for ARexx, WShell, ConMan, etc. X o Bjorn Knutsson, Dominic Giampal, Marc Boucher, Eddy Carroll X and Jonas Petersson for testing. X o All of you who has sent or will send comments, contributions X or questions. X XImprovements X X I've been thinking about adding a way for programs to "register" X their windows with Snap so that Snap can let the program handle X the snapping by itself. As an example: Snapping an icon as text X doesn't make much sense, so the program displaying the icon X could take over and put the name of the file in the clipboard. X A character-mapped window could also benefit from this. X X Xs-mail: Mikael Karlsson X Lovsattersvagen 10 X S-585 98 LINKOPING X SWEDEN X Xe-mail: micke@slaka.sirius.se X micke@slaka.UUCP X {mcvax|munnari|seismo}!sunic!liuida!slaka!micke X XPhone: +46-13 50479 X +46-431 50623 (in the summer) END_OF_FILE if test 22295 -ne `wc -c <'snap.doc'`; then echo shar: \"'snap.doc'\" unpacked with wrong size! fi # end of 'snap.doc' fi if test -f 'source/snap.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'source/snap.c'\" else echo shar: Extracting \"'source/snap.c'\" \(29507 characters\) sed "s/^X//" >'source/snap.c' <<'END_OF_FILE' X/***********************************************\ X* * X* Snap * X* (c) Mikael Karlsson 1988 * X* * X\***********************************************/ X/* Auto: make X*/ X X#ifdef SNAPREXX X#include "minrexx.h" X#endif X X#define ARGVAL() (*++(*argv) || (--argc && *++argv)) X X/* signals */ XLONGBITS startsignal, insertsignal, cancelsignal, donesignal; XLONGBITS movesignal, clicksignal, timersignal, initsignal, cwsignal; XULONG startsignum = -1L; XULONG insertsignum = -1L; XULONG cancelsignum = -1L; XULONG donesignum = -1L; XULONG movesignum = -1L; XULONG clicksignum = -1L; XULONG timersignum = -1L; XULONG initsignum = -1L; XULONG cwsignum = -1L; XULONG WaitSignal; X X/* program */ Xstruct SnapRsrc *SnapRsrc = NULL; Xstruct Task *MyTask; X X/* Snap state machine */ XWORD action; XWORD state; X X/* clipboard */ Xstruct IOClipReq *ClipReq = NULL; Xstruct MsgPort *ClipPort = NULL; X X/* timer device */ Xstruct MsgPort *TimerPort = NULL; Xstruct timerequest MyTR; X X/* input device */ Xstruct MsgPort *inputDevPort = NULL; Xstruct Interrupt handlerStuff; Xstruct IOStdReq *inputRequestBlock = NULL; Xstruct InputEvent SimEvent; XWORD textqual; XWORD gfxqual; XWORD insertkey; XWORD cwkey; XWORD modinsert; X XUBYTE *CharData = NULL; XUBYTE TrueUnderscore; X X/* console */ Xstruct MsgPort *ConPort = NULL; Xstruct IOStdReq *ConIOR = NULL; Xstruct KeyMap keymap; X X/* windows */ Xstruct MsgPort *Sharedport = NULL; XSHORT Sharedrefs; XIMPORT UBYTE *WindowTitle; XIMPORT struct Window *ControlWindow; Xstruct Window *SaveWin = NULL; XIMPORT struct Gadget SaveGad; XIMPORT struct Gadget NameGad; Xstruct GfxSnap *SwapGS = NULL; Xstruct MinList CachedWindows; XIMPORT struct StringInfo TranspSI; X X/* libraries */ Xstruct IntuitionBase *IntuitionBase = NULL; Xstruct GfxBase *GfxBase = NULL; Xstruct LayersBase *LayersBase = NULL; Xstruct ArpBase *ArpBase = NULL; X/* struct DosLibrary *DosBase = NULL; */ X X/* graphics */ Xstruct Screen *theScreen; Xstruct Layer *theLayer; Xstruct RastPort rp, TempRp, MyRP; Xstruct BitMap TempBM, MyBM; XUBYTE *TempRaster = NULL; X XIMPORT struct FileRequester NameFR; XIMPORT UBYTE SaveName[256]; XIMPORT UBYTE SaveDirName[256]; XBPTR SnapFile; X X/* ARexx stuff */ X#ifdef SNAPREXX XULONG rexxsignal; XIMPORT struct rexxCommandList rcl[]; XWORD disp(); X#endif X X/* detaching */ XULONG _BackGroundIO = 0; XULONG _stack = 4096L; XULONG _priority = 4L; Xchar *_procname = "Snap"; X#ifdef LATTICE Xextern BPTR _Backstdout; X#endif LATTICE X XWORD isdigit(c) XREGISTER char c; X{ X return (WORD)(c>='0' && c<='9'); X} X X#ifdef AZTEC_C Xchar *strupr(str) Xchar *str; X{ X register char *p = str; X register char c; X while (c = *p) { X if ('a' <= c && c <= 'z') { X *p = c - ('a' - 'A'); X } X ++p; X } X return str; X} X#endif AZTEC_C X XLONG dectoint(str) XREGISTER char *str; X{ X REGISTER long val = 0; X REGISTER char c; X while (isdigit(c = *str)) { X val = (((val<<2)+val)<<1) + c-'0'; X str++; X } X return(val); X} X XLONG hextoint(str) XREGISTER char *str; X{ X REGISTER long val = 0; X REGISTER char c; X while (c = *str) { X val <<= 4; X val |= (c & 15) + (isdigit(c) ? 0 : 9); X str++; X } X return(val); X} X XWORD insertcount; X XVOID InsertAscii(ascii) XULONG ascii; X{ X if (insertcount == 1) { /* Time for second char */ X /* Not necessary to patch here but it guarantees X that all inserted chars end up in the same window. */ X SafePatch(); X } X InvertKeyMap(ascii, &SimEvent, &keymap); X DoIO(inputRequestBlock); X if (SnapRsrc->chardelay) { X MyTR.tr_node.io_Command = TR_ADDREQUEST; X MyTR.tr_time.tv_micro = SnapRsrc->chardelay; X MyTR.tr_time.tv_secs = 0; X DoIO((struct IOStdReq *)&MyTR); X } X ++insertcount; X} X XVOID GadText(Gad, Str, Len) Xstruct Gadget *Gad; Xchar *Str; XLONG Len; X{ X char temp[256]; X SHORT i; X X SetDrMd(ControlWindow->RPort, JAM2); X SetAPen(ControlWindow->RPort, 0L); X RectFill(ControlWindow->RPort, (LONG)Gad->LeftEdge, (LONG)Gad->TopEdge, X (LONG)Gad->LeftEdge + Gad->Width - 1, (LONG)Gad->TopEdge + Gad->Height - 1); X SetAPen(ControlWindow->RPort, 1L); X SetBPen(ControlWindow->RPort, 0L); X Move(ControlWindow->RPort, X (LONG)Gad->LeftEdge + 1, X (LONG)Gad->TopEdge + ControlWindow->RPort->Font->tf_Baseline + 1); X if (TextLength(ControlWindow->RPort, Str, Len) > Gad->Width) { X i = Len; X strncpy(temp, Str, i - 3); X strcat(temp, "..."); X while (TextLength(ControlWindow->RPort, temp, (LONG)i) > Gad->Width) { X --i; X temp[i] = '\0'; X temp[i-3] = '.'; X } X Text(ControlWindow->RPort, temp, (LONG)i); X } else { X Text(ControlWindow->RPort, Str, Len); X } X} X XVOID SwapColorMap(GS) Xstruct GfxSnap *GS; X{ X struct ViewPort *vp = &GS->window->WScreen->ViewPort; X LONG i = (GS->viewmode & HAM ? 16 : 1L << GS->depth); X ULONG col; X X while (i-- && (col = GetRGB4(vp->ColorMap, i)) != -1L) { X SetRGB4(vp, i, X (LONG)GS->rgb[i][0] >> 4, X (LONG)GS->rgb[i][1] >> 4, X (LONG)GS->rgb[i][2] >> 4); X GS->rgb[i][0] = ((col >> 8) & 0x0f) << 4; X GS->rgb[i][1] = ((col >> 4) & 0x0f) << 4; X GS->rgb[i][2] = ((col >> 0) & 0x0f) << 4; X } X} X XVOID CheckWindowMsgs() X{ X struct IntuiMessage *Msg; X struct IntuiMessage *QdMsg = NULL; X ULONG Class; X USHORT Code; X struct Window *Win; X struct Gadget *Gad; X X while (Sharedport && X (QdMsg || (Msg = (struct IntuiMessage *)GetMsg(Sharedport)))) { X if (QdMsg) { X Msg = QdMsg; X QdMsg = NULL; X } X Class = Msg->Class; X Code = Msg->Code; X Win = Msg->IDCMPWindow; X Gad = (struct Gadget *)Msg->IAddress; X ReplyMsg((struct Message *)Msg); X switch (Class) { X case CLOSEWINDOW: { X if (Win == ControlWindow) { X ControlWindow = NULL; X if (SaveWin) { X struct GfxSnap *GS; X SetWindowTitles(SaveWin, WindowTitle, NULL); X GS = (struct GfxSnap *)SaveWin->UserData; X RefreshGList(&GS->DiskGad, GS->window, NULL, 1L); X SaveWin = NULL; X } X } else { X struct GfxSnap *GS; X GS = (struct GfxSnap *)Win->UserData; X FreePlanes(&GS->BM, GS->width, GS->height); X Kill(GS); X if (Win == SaveWin) { X if (ControlWindow) { X OffGadget(&SaveGad, ControlWindow, NULL); X } X SaveWin = NULL; X } X } X closesharedwindow(Win); X break; X } X case NEWSIZE: { X AdjustSize((struct GfxSnap *)Win->UserData); X break; X } X case MOUSEMOVE: { X /* Collapse all consecutively queued MOUSEMOVE msgs */ X while ((QdMsg = (struct IntuiMessage *)GetMsg(Sharedport)) X && (QdMsg->Class == MOUSEMOVE)) { X ReplyMsg((struct Message *)QdMsg); X } X SyncGS((struct GfxSnap *)Win->UserData); X break; X } X case ACTIVEWINDOW: { X if (Win != ControlWindow) { X struct GfxSnap *GS; X GS = (struct GfxSnap *)Win->UserData; X RefreshGList(&GS->DiskGad, GS->window, NULL, 1L); X } X break; X } X case INACTIVEWINDOW: { X if (Win != ControlWindow) { X struct GfxSnap *GS; X if (SwapGS) { X SwapColorMap(SwapGS); X SwapGS = NULL; X } X GS = (struct GfxSnap *)Win->UserData; X RefreshGList(&GS->DiskGad, GS->window, NULL, 1L); X } X break; X } X case GADGETUP: { X switch (Gad->GadgetID) { X case VPROP: X case HPROP: { X SyncGS((struct GfxSnap *)Win->UserData); X break; X } X case SAVEGAD: { Xsavepic: X if (SaveWin) { X WORD success; X if (SaveName[0] == '\0') { X DisplayBeep(NULL); X ActivateGadget(&NameGad, ControlWindow, NULL); X break; X } X SnapFile = (BPTR)Open(SaveName, MODE_NEWFILE); X success = SaveGS((struct GfxSnap *)SaveWin->UserData); X Close(SnapFile); X if (success) { X SetWindowTitles(ControlWindow, "Saved ok", NULL); X } else { X DeleteFile(SaveName); X DisplayBeep(NULL); X SetWindowTitles(ControlWindow, "Save failed", NULL); X } X } X break; X } X case NAMEGAD: { /* Should only happen with Arp */ X strcpy(SaveDirName, SaveName); X strcpy(SaveName, BaseName(SaveDirName)); X *(BaseName(SaveDirName)) = '\0'; X NameFR.fr_Window = ControlWindow; X (VOID)FileRequest(&NameFR); X TackOn(SaveDirName, SaveName); X strcpy(SaveName, SaveDirName); X GadText(&NameGad, SaveName, (LONG)strlen(SaveName)); X break; X } X case DISKGAD: { X struct GfxSnap *GS; X if (!ControlWindow && !OpenCW()) { X DisplayBeep(NULL); X break; X } X if (Win == SaveWin) { X goto savepic; X } X if (SaveWin) { X SetWindowTitles(SaveWin, WindowTitle, NULL); X GS = (struct GfxSnap *)SaveWin->UserData; X RefreshGList(&GS->DiskGad, GS->window, NULL, 1L); X } else { X GadText(&SaveGad, "Save", 4L); X OnGadget(&SaveGad, ControlWindow, NULL); X } X SaveWin = Win; X SetWindowTitles(SaveWin, "Selected", NULL); X GS = (struct GfxSnap *)SaveWin->UserData; X RefreshGList(&GS->DiskGad, GS->window, NULL, 1L); X break; X } X default: { X break; X } X } X break; X } X case MOUSEBUTTONS: { X if (Win != ControlWindow) { X if (Code == SELECTDOWN && !SwapGS) { X SwapGS = (struct GfxSnap *)Win->UserData; X SwapColorMap(SwapGS); X } else if (Code == SELECTUP && SwapGS) { X SwapColorMap(SwapGS); X SwapGS = NULL; X } X } X break; X } X default: { X break; X } X } X } X if (QdMsg) { X ReplyMsg((struct Message *)QdMsg); X } X} X X#define WriteStdOut(str) Write(StdOut, str, (LONG)strlen(str)) X XVOID main(argc, argv) Xint argc; Xchar **argv; X{ X WORD create = 0, usage = 0; X X BPTR StdOut = (BPTR)Open("*", MODE_OLDFILE); X X#ifdef LATTICE X if(_Backstdout) X Close(_Backstdout); X X _Backstdout = 0; X#endif LATTICE X X#ifdef AZTEC_C X Enable_Abort = 0; X#endif AZTEC_C X if (!(SnapRsrc = (struct SnapRsrc *)OpenResource(SNAPRSRC))) { X create = 1; X SnapRsrc = Create(SnapRsrc); X SnapRsrc->node.ln_Type = NT_RESOURCE; X SnapRsrc->node.ln_Name = SNAPRSRC; X SnapRsrc->Task = FindTask(NULL); X SnapRsrc->Priority = 51; X SnapRsrc->textqual = IEQUALIFIER_LCOMMAND; X SnapRsrc->gfxqual = IEQUALIFIER_RCOMMAND; X SnapRsrc->insertkey = 0x17; X SnapRsrc->cwkey = 0x11; X strcpy(&SnapRsrc->Prepend[0], "> "); X strcpy(&SnapRsrc->Append[0], ""); X SnapRsrc->flags = TRUEUNDERSCORE; X SnapRsrc->chardelay = 0; X SnapRsrc->linedelay = 0; X SnapRsrc->CrawlPtrn = 0x7777; X SnapRsrc->StartUnit = UNIT_FRAME; X SnapRsrc->FrameMask = 1; X SnapRsrc->GadOffset = 52; X SnapRsrc->CacheSize = 10; X SnapRsrc->BadChar = '?'; X AddResource(SnapRsrc); X } X X if (!argc) { /* WB Startup */ X if (!create) { /* Second time from WB -- Remove Snap */ X Signal(SnapRsrc->Task, SIGBREAKF_CTRL_C); X goto exitpoint; X } else { X goto skipargs; X } X } X X if (create && StdOut) { X WriteStdOut("Snap 1.4 (c) 1990 Mikael Karlsson\n"); X } X X for (argc--, argv++; argc > 0; argc--, argv++) { X if (**argv == '-') { /* Argument coming up */ X switch(*++(*argv)) { X case 'p': priority: { /* Priority */ X if (ARGVAL()) { X WORD pri = dectoint(*argv); X if (pri>50 && pri<128) { X SnapRsrc->Priority = pri; X } X } else { X usage = 1; X } X break; X } X case 't': textqual: { X if (ARGVAL()) { X SnapRsrc->textqual = hextoint(*argv); X } else { X usage = 1; X } X break; X } X case 'g': gfxqual: { X if (ARGVAL()) { X SnapRsrc->gfxqual = hextoint(*argv); X } else { X usage = 1; X } X break; X } X case 'i': insertkey: { X if (ARGVAL()) { X SnapRsrc->insertkey = hextoint(*argv); X } else { X usage = 1; X } X break; X } X case 'w': cwkey: { X if (ARGVAL()) { X SnapRsrc->cwkey = hextoint(*argv); X } else { X usage = 1; X } X break; X } X case 'c': chardelay: { X if (ARGVAL()) { X SnapRsrc->chardelay = dectoint(*argv) * 1000; X } else { X usage = 1; X } X break; X } X case 'l': linedelay: { X if (ARGVAL()) { X SnapRsrc->linedelay = dectoint(*argv) * 1000; X } else { X usage = 1; X } X break; X } X case 'a': crawlptrn: { X if (ARGVAL()) { X SnapRsrc->CrawlPtrn = hextoint(*argv); X } else { X usage = 1; X } X break; X } X case 'X': noxerox: { X SnapRsrc->flags &= ~XEROX; X break; X } X case 'x': xerox: { X SnapRsrc->flags |= XEROX; X break; X } X case 'E': noearlypatch: { X SnapRsrc->flags &= ~EARLYPATCH; X break; X } X case 'e': earlypatch: { X SnapRsrc->flags |= EARLYPATCH; X break; X } X case 'R': fakeunderscore: { X SnapRsrc->flags &= ~TRUEUNDERSCORE; X break; X } X case 'r': realunderscore: { X SnapRsrc->flags |= TRUEUNDERSCORE; X break; X } X case 'J': nojoinlong: { X SnapRsrc->flags &= ~JOINLONG; X break; X } X case 'j': joinlong: { X SnapRsrc->flags |= JOINLONG; X break; X } X case 'A': append: X case 'P': prepend: { X char *dest = (**argv == 'A' ? X &SnapRsrc->Append[0] : &SnapRsrc->Prepend[0]); X if (*++(*argv) || (--argc && ++argv)) { /* "" is ok */ X char *src = *argv; X WORD i = 16; X while (*src && i--) { X *dest++ = *src++; X } X *dest = '\0'; X } else { X usage = 1; X } X break; X } X case 'u': startunit: { X if (ARGVAL()) { X switch(dectoint(*argv)) { X case 1: { X SnapRsrc->StartUnit = UNIT_CHAR; X break; X } X case 0: X default: { X SnapRsrc->StartUnit = UNIT_FRAME; X break; X } X } X } else { X usage = 1; X } X break; X } X case 'b': planemask: { X if (ARGVAL()) { X SnapRsrc->FrameMask = hextoint(*argv); X } else { X usage = 1; X } X break; X } X case 'o': gadoffset: { X if (ARGVAL()) { X SnapRsrc->GadOffset = dectoint(*argv); X } else { X usage = 1; X } X break; X } X case 'C': cachesize: { X if (ARGVAL()) { X SnapRsrc->CacheSize = dectoint(*argv); X } else { X usage = 1; X } X break; X } X case 'B': badchar: { X if (ARGVAL()) { X SnapRsrc->BadChar = dectoint(*argv); X } else { X usage = 1; X } X break; X } X case 'Q': quit: { X Close(StdOut); X if (create) { X goto close; X } else { X Signal(SnapRsrc->Task, SIGBREAKF_CTRL_C); X goto exitpoint; X } X } X case '?': { X usage = 1; X break; X } X default: { X if (StdOut) { X WriteStdOut("Bad option: -"); X Write(StdOut, *argv, 1L); X WriteStdOut(".\n"); X } X usage = 1; X break; X } X } X } else { X (VOID)strupr(*argv); X if (!strcmp(*argv, "PRIORITY")) { X (*argv)[1] = '\0'; /* Fake no argument */ X goto priority; /* Terrible, ain't it? */ X } else if (!strcmp(*argv, "TEXTQUAL")) { X (*argv)[1] = '\0'; X goto textqual; X } else if (!strcmp(*argv, "GFXQUAL")) { X (*argv)[1] = '\0'; X goto gfxqual; X } else if (!strcmp(*argv, "INSERTKEY")) { X (*argv)[1] = '\0'; X goto insertkey; X } else if (!strcmp(*argv, "CWKEY")) { X (*argv)[1] = '\0'; X goto cwkey; X } else if (!strcmp(*argv, "PREPEND")) { X (*argv)[1] = '\0'; X goto prepend; X } else if (!strcmp(*argv, "APPEND")) { X (*argv)[1] = '\0'; X goto append; X } else if (!strcmp(*argv, "CHARDELAY")) { X (*argv)[1] = '\0'; X goto chardelay; X } else if (!strcmp(*argv, "LINEDELAY")) { X (*argv)[1] = '\0'; X goto linedelay; X } else if (!strcmp(*argv, "CRAWLPTRN")) { X (*argv)[1] = '\0'; X goto crawlptrn; X } else if (!strcmp(*argv, "XEROX")) { X goto xerox; X } else if (!strcmp(*argv, "NOXEROX")) { X goto noxerox; X } else if (!strcmp(*argv, "EARLYPATCH")) { X goto earlypatch; X } else if (!strcmp(*argv, "NOEARLYPATCH")) { X goto noearlypatch; X } else if (!strcmp(*argv, "TRUEUNDERSCORE")) { X goto realunderscore; X } else if (!strcmp(*argv, "FAKEUNDERSCORE")) { X goto fakeunderscore; X } else if (!strcmp(*argv, "JOINLONG")) { X goto joinlong; X } else if (!strcmp(*argv, "NOJOINLONG")) { X goto nojoinlong; X } else if (!strcmp(*argv, "STARTUNIT")) { X (*argv)[1] = '\0'; X goto startunit; X } else if (!strcmp(*argv, "PLANEMASK")) { X (*argv)[1] = '\0'; X goto planemask; X } else if (!strcmp(*argv, "GADOFFSET")) { X (*argv)[1] = '\0'; X goto gadoffset; X } else if (!strcmp(*argv, "CACHESIZE")) { X (*argv)[1] = '\0'; X goto cachesize; X } else if (!strcmp(*argv, "BADCHAR")) { X (*argv)[1] = '\0'; X goto badchar; X } else if (!strcmp(*argv, "QUIT")) { X goto quit; X } else if (strcmp(*argv, "?") && StdOut) { X WriteStdOut("Bad switch/keyword: "); X WriteStdOut(*argv); X WriteStdOut(".\n"); X } X usage = 1; X } X } X X if (usage && StdOut) { X WriteStdOut("Usage:\n"); X WriteStdOut(" snap -pNN -tXX -gXX -iXX -wXX -Pstr -Astr -cNN -lNN -aXXXX\n"); X WriteStdOut(" -x -X -e -E -uN -r -R -j -J -bXX -oNN -CNN -BNN -Q\n"); X WriteStdOut(" or\n"); X WriteStdOut(" snap PRIORITY/k TEXTQUAL/k GFXQUAL/k INSERTKEY/k CWKEY/k\n"); X WriteStdOut(" PREPEND/k APPEND/k CHARDELAY/k LINEDELAY/k CRAWLPTRN/k\n"); X WriteStdOut(" XEROX/s NOXEROX/s EARLYPATCH/s NOEARLYPATCH/s STARTUNIT/k\n"); X WriteStdOut(" TRUEUNDERSCORE/s FAKEUNDERSCORE/s JOINLONG/s NOJOINLONG/s\n"); X WriteStdOut(" PLANEMASK/k GADOFFSET/k CACHESIZE/k BADCHAR/s QUIT/s\n"); X } X Xskipargs: X if (StdOut) { X Close(StdOut); X } X X if (!create) { X /* Tell him there are new settings available */ X Signal(SnapRsrc->Task, SIGBREAKF_CTRL_F); X goto exitpoint; X } X X textqual = SnapRsrc->textqual; X gfxqual = SnapRsrc->gfxqual; X insertkey = SnapRsrc->insertkey; X cwkey = SnapRsrc->cwkey; X TrueUnderscore = SnapRsrc->flags & TRUEUNDERSCORE ? 1 : 0; X X if (!OpenStuff()) { X goto close; X } X X#ifdef SNAPREXX X rexxsignal = upRexxPort("SNAP", &rcl, NULL, &disp); X#endif X X /* This is what we're waiting for */ X WaitSignal = startsignal | insertsignal | initsignal | cancelsignal | X#ifdef SNAPREXX X rexxsignal | X#endif X cwsignal | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F; X X FOREVER { X REGISTER LONGBITS sig = X Wait(WaitSignal | X (Sharedport ? (1L << Sharedport->mp_SigBit) : 0L)); X CheckWindowMsgs(); X#ifdef SNAPREXX X if (sig & rexxsignal) { X dispRexxPort(); X } X#endif X if (sig & SIGBREAKF_CTRL_C) { X /* This is my cue. Exit if there are no open windows depending on us */ X if (Sharedrefs) { X DisplayBeep(NULL); X } else { X goto close; X } X } X if (sig & SIGBREAKF_CTRL_F) { X /* Hey, seems like there are new settings available. */ X textqual = SnapRsrc->textqual; X gfxqual = SnapRsrc->gfxqual; X insertkey = SnapRsrc->insertkey; X cwkey = SnapRsrc->cwkey; X TrueUnderscore = SnapRsrc->flags & TRUEUNDERSCORE ? 1 : 0; X } X if (sig & initsignal) { X if (SnapRsrc->flags & (XEROX | EARLYPATCH)) { X SafePatch(); /* Patch dangerous functions */ X } X } X if (sig & cancelsignal) { X SafeRestore(); X } X if (sig & startsignal) { /* The handler wants a word in. */ X SafePatch(); X if (action == snapgfx) { /* Check user action */ X HandleGfx(); /* Get the picture :-) */ X } else if (action == snaptext) { X if (HandleChars()) { /* Snap some chars */ X if (SnapRsrc->flags & XEROX) { X sig |= insertsignal; X } X } X } else { X /* Previous snap wasn't finished when this one started. */ X SetSignal(0L, X movesignal|cancelsignal|donesignal|clicksignal|timersignal); X DisplayBeep(NULL); X action = noaction; X } X if (!(sig & insertsignal)) { X SafeRestore(); /* Layers unlocked - all safe */ X } X } X X if (sig & insertsignal) { X LONG i; X struct Snap *Snap; X ULONG ascii; X X action = insert; X if (Snap = FetchClip()) { /* Get clipboard data */ X /* get the current keymap */ X ConIOR->io_Command = CD_ASKDEFAULTKEYMAP; X ConIOR->io_Length = sizeof (struct KeyMap); X ConIOR->io_Data = (APTR) &keymap; X ConIOR->io_Flags = 1; /* no IOQuick */ X DoIO(ConIOR); X /* Set up an input request */ X inputRequestBlock->io_Command = IND_WRITEEVENT; X inputRequestBlock->io_Flags = 0L; X inputRequestBlock->io_Length = (long)sizeof(struct InputEvent); X inputRequestBlock->io_Data = (APTR)&SimEvent; X /* Translate chars in SnapSpace and insert them X into the input stream. */ X insertcount = 0; X ascii = 13; /* Simulate start of new line */ X for (i = 0; Snap->Chars[i] && (action == insert); ++i) { X if (ascii == 13 && modinsert) { X int cnt = 0; X while (ascii = SnapRsrc->Prepend[cnt++]) { X InsertAscii(ascii); X } X } X X ascii = Snap->Chars[i]; X if (ascii == 10) { X if (modinsert) { X int cnt = 0; X while (ascii = SnapRsrc->Append[cnt++]) { X InsertAscii(ascii); X } X } X ascii = 13; /* WYSIWYG? Hah! */ X if (SnapRsrc->linedelay) { X MyTR.tr_node.io_Command = TR_ADDREQUEST; X MyTR.tr_time.tv_micro = SnapRsrc->linedelay; X MyTR.tr_time.tv_secs = 0; X DoIO((struct IOStdReq *)&MyTR); X } X } X InsertAscii(ascii); X } X if (modinsert) { X int cnt = 0; X while (ascii = SnapRsrc->Append[cnt++]) { X InsertAscii(ascii); X } X } X SafeRestore(); /* "Depatch" */ X /* Free memory given to us by FetchClip() */ X FreeMem(Snap, Snap->Size); X } X action = noaction; X modinsert = 0; X } X X if (sig & cwsignal) { X if (!ControlWindow && !OpenCW()) { X DisplayBeep(NULL); X } X } X } X Xclose: X#ifdef SNAPREXX X dnRexxPort(); X#endif X CloseStuff(); /* Guess what */ Xexitpoint: ; X} X END_OF_FILE if test 29507 -ne `wc -c <'source/snap.c'`; then echo shar: \"'source/snap.c'\" unpacked with wrong size! fi # end of 'source/snap.c' fi echo shar: End of archive 4 \(of 4\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@cs.odu.edu>. Mail comments to the moderator at <amiga-request@cs.odu.edu>. Post requests for sources, and general dicussion to comp.sys.amiga.