/***********************************************\
*                                               *
*                     Snap                      *
*           (c) Mikael Karlsson 1988              *
*                                               *
\***********************************************/
/* Auto: make
*/

#ifdef SNAPREXX
#include "minrexx.h"
#endif

#define ARGVAL() (*++(*argv) || (--argc && *++argv))

/* signals */
LONGBITS startsignal, insertsignal, cancelsignal, donesignal;
LONGBITS movesignal, clicksignal, timersignal, initsignal, cwsignal;
ULONG startsignum = -1L;
ULONG insertsignum = -1L;
ULONG cancelsignum = -1L;
ULONG donesignum = -1L;
ULONG movesignum = -1L;
ULONG clicksignum = -1L;
ULONG timersignum = -1L;
ULONG initsignum = -1L;
ULONG cwsignum = -1L;
ULONG WaitSignal;

/* program */
struct SnapRsrc *SnapRsrc = NULL;
struct Task *MyTask;

/* Snap state machine */
WORD action;
WORD state;

/* clipboard */
struct IOClipReq *ClipReq = NULL;
struct MsgPort *ClipPort = NULL;

/* timer device */
struct MsgPort *TimerPort = NULL;
struct timerequest MyTR;

/* input device */
struct MsgPort *inputDevPort = NULL;
struct Interrupt handlerStuff;
struct IOStdReq *inputRequestBlock = NULL;
struct InputEvent SimEvent;
WORD textqual;
WORD gfxqual;
WORD insertkey;
WORD cwkey;
WORD modinsert;

UBYTE *CharData = NULL;
UBYTE TrueUnderscore;

/* console */
struct MsgPort *ConPort = NULL;
struct IOStdReq *ConIOR = NULL;
struct KeyMap keymap;

/* windows */
struct MsgPort *Sharedport = NULL;
SHORT Sharedrefs;
IMPORT UBYTE *WindowTitle;
IMPORT struct Window *ControlWindow;
struct Window *SaveWin = NULL;
IMPORT struct Gadget SaveGad;
IMPORT struct Gadget NameGad;
struct GfxSnap *SwapGS = NULL;
struct MinList CachedWindows;
IMPORT struct StringInfo TranspSI;

/* libraries */
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase       *GfxBase = NULL;
struct LayersBase    *LayersBase = NULL;
struct ArpBase       *ArpBase = NULL;
/* struct DosLibrary    *DosBase = NULL; */

/* graphics */
struct Screen *theScreen;
struct Layer *theLayer;
struct RastPort rp, TempRp, MyRP;
struct BitMap TempBM, MyBM;
UBYTE *TempRaster = NULL;

IMPORT struct FileRequester NameFR;
IMPORT UBYTE SaveName[256];
IMPORT UBYTE SaveDirName[256];
BPTR SnapFile;

/* ARexx stuff */
#ifdef SNAPREXX
ULONG rexxsignal;
IMPORT struct rexxCommandList rcl[];
WORD disp();
#endif

/* detaching */
ULONG _BackGroundIO = 0;
ULONG _stack = 4096L;
ULONG _priority = 4L;
char *_procname = "Snap";
#ifdef LATTICE
extern BPTR _Backstdout;
#endif LATTICE

WORD isdigit(c)
REGISTER char c;
{
    return (WORD)(c>='0' && c<='9');
}

#ifdef AZTEC_C
char *strupr(str)
char *str;
{
    register char *p = str;
    register char c;
    while (c = *p) {
        if ('a' <= c && c <= 'z') {
            *p = c - ('a' - 'A');
        }
        ++p;
    }
    return str;
}
#endif AZTEC_C

LONG dectoint(str)
REGISTER char *str;
{
    REGISTER long val = 0;
    REGISTER char c;
    while (isdigit(c = *str)) {
        val = (((val<<2)+val)<<1) + c-'0';
        str++;
    }
    return(val);
}

LONG hextoint(str)
REGISTER char *str;
{
    REGISTER long val = 0;
    REGISTER char c;
    while (c = *str) {
        val <<= 4;
        val |= (c & 15) + (isdigit(c) ? 0 : 9);
        str++;
    }
    return(val);
}

WORD insertcount;

VOID InsertAscii(ascii)
ULONG ascii;
{
    if (insertcount == 1) {   /* Time for second char */
          /* Not necessary to patch here but it guarantees
             that all inserted chars end up in the same window. */
        SafePatch();
    }
    InvertKeyMap(ascii, &SimEvent, &keymap);
    DoIO(inputRequestBlock);
    if (SnapRsrc->chardelay) {
        MyTR.tr_node.io_Command = TR_ADDREQUEST;
        MyTR.tr_time.tv_micro = SnapRsrc->chardelay;
        MyTR.tr_time.tv_secs = 0;
        DoIO((struct IOStdReq *)&MyTR);
    }
    ++insertcount;
}

VOID GadText(Gad, Str, Len)
struct Gadget *Gad;
char *Str;
LONG Len;
{
    char temp[256];
    SHORT i;

    SetDrMd(ControlWindow->RPort, JAM2);
    SetAPen(ControlWindow->RPort, 0L);
    RectFill(ControlWindow->RPort, (LONG)Gad->LeftEdge, (LONG)Gad->TopEdge,
      (LONG)Gad->LeftEdge + Gad->Width - 1, (LONG)Gad->TopEdge + Gad->Height - 1);
    SetAPen(ControlWindow->RPort, 1L);
    SetBPen(ControlWindow->RPort, 0L);
    Move(ControlWindow->RPort,
      (LONG)Gad->LeftEdge + 1,
      (LONG)Gad->TopEdge + ControlWindow->RPort->Font->tf_Baseline + 1);
    if (TextLength(ControlWindow->RPort, Str, Len) > Gad->Width) {
        i = Len;
        strncpy(temp, Str, i - 3);
        strcat(temp, "...");
        while (TextLength(ControlWindow->RPort, temp, (LONG)i) > Gad->Width) {
            --i;
            temp[i] = '\0';
            temp[i-3] = '.';
        }
        Text(ControlWindow->RPort, temp, (LONG)i);
    } else {
        Text(ControlWindow->RPort, Str, Len);
    }
}

VOID SwapColorMap(GS)
struct GfxSnap *GS;
{
    struct ViewPort *vp = &GS->window->WScreen->ViewPort;
    LONG i = (GS->viewmode & HAM ? 16 : 1L << GS->depth);
    ULONG col;

    while (i-- && (col = GetRGB4(vp->ColorMap, i)) != -1L) {
        SetRGB4(vp, i,
          (LONG)GS->rgb[i][0] >> 4,
          (LONG)GS->rgb[i][1] >> 4,
          (LONG)GS->rgb[i][2] >> 4);
        GS->rgb[i][0] = ((col >> 8) & 0x0f) << 4;
        GS->rgb[i][1] = ((col >> 4) & 0x0f) << 4;
        GS->rgb[i][2] = ((col >> 0) & 0x0f) << 4;
    }
}

VOID CheckWindowMsgs()
{
    struct IntuiMessage *Msg;
    struct IntuiMessage *QdMsg = NULL;
    ULONG Class;
    USHORT Code;
    struct Window *Win;
    struct Gadget *Gad;

    while (Sharedport &&
      (QdMsg || (Msg = (struct IntuiMessage *)GetMsg(Sharedport)))) {
        if (QdMsg) {
            Msg = QdMsg;
            QdMsg = NULL;
        }
        Class = Msg->Class;
        Code  = Msg->Code;
        Win   = Msg->IDCMPWindow;
        Gad   = (struct Gadget *)Msg->IAddress;
        ReplyMsg((struct Message *)Msg);
        switch (Class) {
            case CLOSEWINDOW: {
                if (Win == ControlWindow) {
                    ControlWindow = NULL;
                    if (SaveWin) {
                        struct GfxSnap *GS;
                        SetWindowTitles(SaveWin, WindowTitle, NULL);
                        GS = (struct GfxSnap *)SaveWin->UserData;
                        RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
                        SaveWin = NULL;
                    }
                } else {
                    struct GfxSnap *GS;
                    GS = (struct GfxSnap *)Win->UserData;
                    FreePlanes(&GS->BM, GS->width, GS->height);
                    Kill(GS);
                    if (Win == SaveWin) {
                        if (ControlWindow) {
                            OffGadget(&SaveGad, ControlWindow, NULL);
                        }
                        SaveWin = NULL;
                    }
                }
                closesharedwindow(Win);
                break;
            }
            case NEWSIZE: {
                AdjustSize((struct GfxSnap *)Win->UserData);
                break;
            }
            case MOUSEMOVE: {
                  /* Collapse all consecutively queued MOUSEMOVE msgs */
                while ((QdMsg = (struct IntuiMessage *)GetMsg(Sharedport))
                  && (QdMsg->Class == MOUSEMOVE)) {
                    ReplyMsg((struct Message *)QdMsg);
                }
                SyncGS((struct GfxSnap *)Win->UserData);
                break;
            }
            case ACTIVEWINDOW: {
                if (Win != ControlWindow) {
                    struct GfxSnap *GS;
                    GS = (struct GfxSnap *)Win->UserData;
                    RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
                }
                break;
            }
            case INACTIVEWINDOW: {
                if (Win != ControlWindow) {
                    struct GfxSnap *GS;
                    if (SwapGS) {
                        SwapColorMap(SwapGS);
                        SwapGS = NULL;
                    }
                    GS = (struct GfxSnap *)Win->UserData;
                    RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
                }
                break;
            }
            case GADGETUP: {
                switch (Gad->GadgetID) {
                    case VPROP:
                    case HPROP: {
                        SyncGS((struct GfxSnap *)Win->UserData);
                        break;
                    }
                    case SAVEGAD: {
savepic:
                        if (SaveWin) {
                            WORD success;
                            if (SaveName[0] == '\0') {
                                DisplayBeep(NULL);
                                ActivateGadget(&NameGad, ControlWindow, NULL);
                                break;
                            }
                            SnapFile = (BPTR)Open(SaveName, MODE_NEWFILE);
                            success = SaveGS((struct GfxSnap *)SaveWin->UserData);
                            Close(SnapFile);
                            if (success) {
                                SetWindowTitles(ControlWindow, "Saved ok", NULL);
                            } else {
                                DeleteFile(SaveName);
                                DisplayBeep(NULL);
                                SetWindowTitles(ControlWindow, "Save failed", NULL);
                            }
                        }
                        break;
                    }
                    case NAMEGAD: { /* Should only happen with Arp */
                        strcpy(SaveDirName, SaveName);
                        strcpy(SaveName, BaseName(SaveDirName));
                        *(BaseName(SaveDirName)) = '\0';
                        NameFR.fr_Window = ControlWindow;
                        (VOID)FileRequest(&NameFR);
                        TackOn(SaveDirName, SaveName);
                        strcpy(SaveName, SaveDirName);
                        GadText(&NameGad, SaveName, (LONG)strlen(SaveName));
                        break;
                    }
                    case DISKGAD: {
                        struct GfxSnap *GS;
                        if (!ControlWindow && !OpenCW()) {
                            DisplayBeep(NULL);
                            break;
                        }
                        if (Win == SaveWin) {
                            goto savepic;
                        }
                        if (SaveWin) {
                            SetWindowTitles(SaveWin, WindowTitle, NULL);
                            GS = (struct GfxSnap *)SaveWin->UserData;
                            RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
                        } else {
                            GadText(&SaveGad, "Save", 4L);
                            OnGadget(&SaveGad, ControlWindow, NULL);
                        }
                        SaveWin = Win;
                        SetWindowTitles(SaveWin, "Selected", NULL);
                        GS = (struct GfxSnap *)SaveWin->UserData;
                        RefreshGList(&GS->DiskGad, GS->window, NULL, 1L);
                        break;
                    }
                    default: {
                        break;
                    }
                }
                break;
            }
            case MOUSEBUTTONS: {
                if (Win != ControlWindow) {
                    if (Code == SELECTDOWN && !SwapGS) {
                        SwapGS = (struct GfxSnap *)Win->UserData;
                        SwapColorMap(SwapGS);
                    } else if (Code == SELECTUP && SwapGS) {
                        SwapColorMap(SwapGS);
                        SwapGS = NULL;
                    }
                }
                break;
            }
            default: {
                break;
            }
        }
    }
    if (QdMsg) {
        ReplyMsg((struct Message *)QdMsg);
    }
}

#define WriteStdOut(str) Write(StdOut, str, (LONG)strlen(str))

VOID main(argc, argv)
int argc;
char **argv;
{
    WORD create = 0, usage = 0;

    BPTR StdOut = (BPTR)Open("*", MODE_OLDFILE);

#ifdef LATTICE
	if(_Backstdout)
		Close(_Backstdout);

	_Backstdout = 0;
#endif LATTICE

#ifdef AZTEC_C
    Enable_Abort = 0;
#endif AZTEC_C
    if (!(SnapRsrc = (struct SnapRsrc *)OpenResource(SNAPRSRC))) {
        create = 1;
        SnapRsrc = Create(SnapRsrc);
        SnapRsrc->node.ln_Type = NT_RESOURCE;
        SnapRsrc->node.ln_Name = SNAPRSRC;
        SnapRsrc->Task = FindTask(NULL);
        SnapRsrc->Priority = 51;
        SnapRsrc->textqual = IEQUALIFIER_LCOMMAND;
        SnapRsrc->gfxqual = IEQUALIFIER_RCOMMAND;
        SnapRsrc->insertkey = 0x17;
        SnapRsrc->cwkey = 0x11;
        strcpy(&SnapRsrc->Prepend[0], "> ");
        strcpy(&SnapRsrc->Append[0], "");
        SnapRsrc->flags = TRUEUNDERSCORE;
        SnapRsrc->chardelay = 0;
        SnapRsrc->linedelay = 0;
        SnapRsrc->CrawlPtrn = 0x7777;
        SnapRsrc->StartUnit = UNIT_FRAME;
        SnapRsrc->FrameMask = 1;
        SnapRsrc->GadOffset = 52;
        SnapRsrc->CacheSize = 10;
        SnapRsrc->BadChar = '?';
        AddResource(SnapRsrc);
    }

    if (!argc) {    /* WB Startup */
        if (!create) {     /* Second time from WB -- Remove Snap */
            Signal(SnapRsrc->Task, SIGBREAKF_CTRL_C);
            goto exitpoint;
        } else {
            goto skipargs;
        }
    }

    if (create && StdOut) {
        WriteStdOut("Snap 1.4 (c) 1990 Mikael Karlsson\n");
    }

    for (argc--, argv++; argc > 0; argc--, argv++) {
        if (**argv == '-') { /* Argument coming up */
            switch(*++(*argv)) {
                case 'p': priority: {  /* Priority */
                    if (ARGVAL()) {
                        WORD pri = dectoint(*argv);
                        if (pri>50 && pri<128) {
                            SnapRsrc->Priority = pri;
                        }
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 't': textqual: {
                    if (ARGVAL()) {
                        SnapRsrc->textqual = hextoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'g': gfxqual: {
                    if (ARGVAL()) {
                        SnapRsrc->gfxqual = hextoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'i': insertkey: {
                    if (ARGVAL()) {
                        SnapRsrc->insertkey = hextoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'w': cwkey: {
                    if (ARGVAL()) {
                        SnapRsrc->cwkey = hextoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'c': chardelay: {
                    if (ARGVAL()) {
                        SnapRsrc->chardelay = dectoint(*argv) * 1000;
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'l': linedelay: {
                    if (ARGVAL()) {
                        SnapRsrc->linedelay = dectoint(*argv) * 1000;
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'a': crawlptrn: {
                    if (ARGVAL()) {
                        SnapRsrc->CrawlPtrn = hextoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'X': noxerox: {
                    SnapRsrc->flags &= ~XEROX;
                    break;
                }
                case 'x': xerox: {
                    SnapRsrc->flags |= XEROX;
                    break;
                }
                case 'E': noearlypatch: {
                    SnapRsrc->flags &= ~EARLYPATCH;
                    break;
                }
                case 'e': earlypatch: {
                    SnapRsrc->flags |= EARLYPATCH;
                    break;
                }
                case 'R': fakeunderscore: {
                    SnapRsrc->flags &= ~TRUEUNDERSCORE;
                    break;
                }
                case 'r': realunderscore: {
                    SnapRsrc->flags |= TRUEUNDERSCORE;
                    break;
                }
                case 'J': nojoinlong: {
                    SnapRsrc->flags &= ~JOINLONG;
                    break;
                }
                case 'j': joinlong: {
                    SnapRsrc->flags |= JOINLONG;
                    break;
                }
                case 'A': append:
                case 'P': prepend: {
                    char *dest = (**argv == 'A' ?
                      &SnapRsrc->Append[0] : &SnapRsrc->Prepend[0]);
                    if (*++(*argv) || (--argc && ++argv)) { /* "" is ok */
                        char *src = *argv;
                        WORD i = 16;
                        while (*src && i--) {
                            *dest++ = *src++;
                        }
                        *dest = '\0';
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'u': startunit: {
                    if (ARGVAL()) {
                        switch(dectoint(*argv)) {
                            case 1: {
                                SnapRsrc->StartUnit = UNIT_CHAR;
                                break;
                            }
                            case 0:
                            default: {
                                SnapRsrc->StartUnit = UNIT_FRAME;
                                break;
                            }
                        }
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'b': planemask: {
                    if (ARGVAL()) {
                        SnapRsrc->FrameMask = hextoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'o': gadoffset: {
                    if (ARGVAL()) {
                        SnapRsrc->GadOffset = dectoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'C': cachesize: {
                    if (ARGVAL()) {
                        SnapRsrc->CacheSize = dectoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'B': badchar: {
                    if (ARGVAL()) {
                        SnapRsrc->BadChar = dectoint(*argv);
                    } else {
                        usage = 1;
                    }
                    break;
                }
                case 'Q': quit: {
                    Close(StdOut);
                    if (create) {
                        goto close;
                    } else {
                        Signal(SnapRsrc->Task, SIGBREAKF_CTRL_C);
                        goto exitpoint;
                    }
                }
                case '?': {
                    usage = 1;
                    break;
                }
                default: {
                    if (StdOut) {
                        WriteStdOut("Bad option: -");
                        Write(StdOut, *argv, 1L);
                        WriteStdOut(".\n");
                    }
                    usage = 1;
                    break;
                }
            }
        } else {
            (VOID)strupr(*argv);
            if (!strcmp(*argv, "PRIORITY")) {
                (*argv)[1] = '\0';                  /* Fake no argument */
                goto priority;                      /* Terrible, ain't it? */
            } else if (!strcmp(*argv, "TEXTQUAL")) {
                (*argv)[1] = '\0';
                goto textqual;
            } else if (!strcmp(*argv, "GFXQUAL")) {
                (*argv)[1] = '\0';
                goto gfxqual;
            } else if (!strcmp(*argv, "INSERTKEY")) {
                (*argv)[1] = '\0';
                goto insertkey;
            } else if (!strcmp(*argv, "CWKEY")) {
                (*argv)[1] = '\0';
                goto cwkey;
            } else if (!strcmp(*argv, "PREPEND")) {
                (*argv)[1] = '\0';
                goto prepend;
            } else if (!strcmp(*argv, "APPEND")) {
                (*argv)[1] = '\0';
                goto append;
            } else if (!strcmp(*argv, "CHARDELAY")) {
                (*argv)[1] = '\0';
                goto chardelay;
            } else if (!strcmp(*argv, "LINEDELAY")) {
                (*argv)[1] = '\0';
                goto linedelay;
            } else if (!strcmp(*argv, "CRAWLPTRN")) {
                (*argv)[1] = '\0';
                goto crawlptrn;
            } else if (!strcmp(*argv, "XEROX")) {
                goto xerox;
            } else if (!strcmp(*argv, "NOXEROX")) {
                goto noxerox;
            } else if (!strcmp(*argv, "EARLYPATCH")) {
                goto earlypatch;
            } else if (!strcmp(*argv, "NOEARLYPATCH")) {
                goto noearlypatch;
            } else if (!strcmp(*argv, "TRUEUNDERSCORE")) {
                goto realunderscore;
            } else if (!strcmp(*argv, "FAKEUNDERSCORE")) {
                goto fakeunderscore;
            } else if (!strcmp(*argv, "JOINLONG")) {
                goto joinlong;
            } else if (!strcmp(*argv, "NOJOINLONG")) {
                goto nojoinlong;
            } else if (!strcmp(*argv, "STARTUNIT")) {
                (*argv)[1] = '\0';
                goto startunit;
            } else if (!strcmp(*argv, "PLANEMASK")) {
                (*argv)[1] = '\0';
                goto planemask;
            } else if (!strcmp(*argv, "GADOFFSET")) {
                (*argv)[1] = '\0';
                goto gadoffset;
            } else if (!strcmp(*argv, "CACHESIZE")) {
                (*argv)[1] = '\0';
                goto cachesize;
            } else if (!strcmp(*argv, "BADCHAR")) {
                (*argv)[1] = '\0';
                goto badchar;
            } else if (!strcmp(*argv, "QUIT")) {
                goto quit;
            } else if (strcmp(*argv, "?") && StdOut) {
                WriteStdOut("Bad switch/keyword: ");
                WriteStdOut(*argv);
                WriteStdOut(".\n");
            }
            usage = 1;
        }
    }

    if (usage && StdOut) {
        WriteStdOut("Usage:\n");
        WriteStdOut(" snap -pNN -tXX -gXX -iXX -wXX -Pstr -Astr -cNN -lNN -aXXXX\n");
        WriteStdOut("   -x -X -e -E -uN -r -R -j -J -bXX -oNN -CNN -BNN -Q\n");
        WriteStdOut(" or\n");
        WriteStdOut(" snap PRIORITY/k TEXTQUAL/k GFXQUAL/k INSERTKEY/k CWKEY/k\n");
        WriteStdOut("   PREPEND/k APPEND/k CHARDELAY/k LINEDELAY/k CRAWLPTRN/k\n");
        WriteStdOut("   XEROX/s NOXEROX/s EARLYPATCH/s NOEARLYPATCH/s STARTUNIT/k\n");
        WriteStdOut("   TRUEUNDERSCORE/s FAKEUNDERSCORE/s JOINLONG/s NOJOINLONG/s\n");
        WriteStdOut("   PLANEMASK/k GADOFFSET/k CACHESIZE/k BADCHAR/s QUIT/s\n");
    }

skipargs:
    if (StdOut) {
        Close(StdOut);
    }

    if (!create) {
          /* Tell him there are new settings available */
        Signal(SnapRsrc->Task, SIGBREAKF_CTRL_F);
        goto exitpoint;
    }

    textqual = SnapRsrc->textqual;
    gfxqual = SnapRsrc->gfxqual;
    insertkey = SnapRsrc->insertkey;
    cwkey = SnapRsrc->cwkey;
    TrueUnderscore = SnapRsrc->flags & TRUEUNDERSCORE ? 1 : 0;

    if (!OpenStuff()) {
        goto close;
    }

#ifdef SNAPREXX
    rexxsignal = upRexxPort("SNAP", &rcl, NULL, &disp);
#endif

    /* This is what we're waiting for */
    WaitSignal = startsignal | insertsignal | initsignal | cancelsignal |
#ifdef SNAPREXX
                 rexxsignal |
#endif
                 cwsignal | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F;

    FOREVER {
        REGISTER LONGBITS sig =
          Wait(WaitSignal |
               (Sharedport ? (1L << Sharedport->mp_SigBit) : 0L));
        CheckWindowMsgs();
#ifdef SNAPREXX
        if (sig & rexxsignal) {
            dispRexxPort();
        }
#endif
        if (sig & SIGBREAKF_CTRL_C) {
            /* This is my cue. Exit if there are no open windows depending on us */
            if (Sharedrefs) {
                DisplayBeep(NULL);
            } else {
                goto close;
            }
        }
        if (sig & SIGBREAKF_CTRL_F) {
            /* Hey, seems like there are new settings available. */
            textqual = SnapRsrc->textqual;
            gfxqual = SnapRsrc->gfxqual;
            insertkey = SnapRsrc->insertkey;
            cwkey = SnapRsrc->cwkey;
            TrueUnderscore = SnapRsrc->flags & TRUEUNDERSCORE ? 1 : 0;
        }
        if (sig & initsignal) {
            if (SnapRsrc->flags & (XEROX | EARLYPATCH)) {
                SafePatch();               /* Patch dangerous functions */
            }
        }
        if (sig & cancelsignal) {
            SafeRestore();
        }
        if (sig & startsignal) { /* The handler wants a word in. */
            SafePatch();
            if (action == snapgfx) {       /* Check user action */
                HandleGfx();               /* Get the picture :-) */
            } else if (action == snaptext) {
                if (HandleChars()) {             /* Snap some chars */
                    if (SnapRsrc->flags & XEROX) {
                        sig |= insertsignal;
                    }
                }
            } else {
                  /* Previous snap wasn't finished when this one started. */
                SetSignal(0L,
                  movesignal|cancelsignal|donesignal|clicksignal|timersignal);
                DisplayBeep(NULL);
                action = noaction;
            }
            if (!(sig & insertsignal)) {
                SafeRestore();             /* Layers unlocked - all safe */
            }
        }

        if (sig & insertsignal) {
            LONG i;
            struct Snap *Snap;
            ULONG ascii;

            action = insert;
            if (Snap = FetchClip()) {  /* Get clipboard data */
                  /* get the current keymap  */
                ConIOR->io_Command =  CD_ASKDEFAULTKEYMAP;
                ConIOR->io_Length  = sizeof (struct KeyMap);
                ConIOR->io_Data    = (APTR) &keymap;
                ConIOR->io_Flags   = 1;    /* no IOQuick   */
                DoIO(ConIOR);
                  /* Set up an input request */
                inputRequestBlock->io_Command = IND_WRITEEVENT;
                inputRequestBlock->io_Flags   = 0L;
                inputRequestBlock->io_Length  = (long)sizeof(struct InputEvent);
                inputRequestBlock->io_Data    = (APTR)&SimEvent;
                  /* Translate chars in SnapSpace and insert them
                     into the input stream. */
                insertcount = 0;
                ascii = 13;  /* Simulate start of new line */
                for (i = 0; Snap->Chars[i] && (action == insert); ++i) {
                    if (ascii == 13 && modinsert) {
                        int cnt = 0;
                        while (ascii = SnapRsrc->Prepend[cnt++]) {
                            InsertAscii(ascii);
                        }
                    }

                    ascii = Snap->Chars[i];
                    if (ascii == 10) {
                        if (modinsert) {
                            int cnt = 0;
                            while (ascii = SnapRsrc->Append[cnt++]) {
                                InsertAscii(ascii);
                            }
                        }
                        ascii = 13;     /* WYSIWYG? Hah! */
                        if (SnapRsrc->linedelay) {
                            MyTR.tr_node.io_Command = TR_ADDREQUEST;
                            MyTR.tr_time.tv_micro = SnapRsrc->linedelay;
                            MyTR.tr_time.tv_secs = 0;
                            DoIO((struct IOStdReq *)&MyTR);
                        }
                    }
                    InsertAscii(ascii);
                }
                if (modinsert) {
                    int cnt = 0;
                    while (ascii = SnapRsrc->Append[cnt++]) {
                        InsertAscii(ascii);
                    }
                }
                SafeRestore();  /* "Depatch" */
                  /* Free memory given to us by FetchClip() */
                FreeMem(Snap, Snap->Size);
            }
            action = noaction;
            modinsert = 0;
        }

        if (sig & cwsignal) {
            if (!ControlWindow && !OpenCW()) {
                DisplayBeep(NULL);
            }
        }
    }

close:
#ifdef SNAPREXX
    dnRexxPort();
#endif
    CloseStuff();  /* Guess what */
exitpoint: ;
}

