[comp.sources.amiga] v90i070: Snap 1.4 - cut, store, and paste between windows, Part04/04

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.