/* File: DummyScan.c Copyright 1990 by Thomas Knoll. Think C source file for DummyScan example. */ #include #include "AcquireInterface.h" #define Length(string) (*(unsigned char *)(string)) /* The value of global variables are not preserved between invocations of the plug-in, since the plug-in's resource file is closed. To keep values around longer, make them part of the following structure. */ typedef struct TPermanent { short lastRows; short lastCols; short lastMode; } TPermanent; TPermanent gPermanent; short gResult; AcquireRecordPtr gStuff; short gNextRow; short gNextPlane; /*****************************************************************************/ /* Calls the host's TestAbort function */ Boolean TestAbort (void) { return CallPascalB (gStuff->abortProc); } /*****************************************************************************/ /* Calls the host's UpdateProgress procedure */ void UpdateProgress (done, total) long done; long total; { CallPascal (done, total, gStuff->progressProc); } /*****************************************************************************/ /* Sets the global variables to their default values. */ void InitGlobals (void) { gPermanent.lastRows = 256; gPermanent.lastCols = 256; gPermanent.lastMode = acquireModeRGBColor; } /*****************************************************************************/ /* Centers a dialog template 1/3 of the way down on the main screen. */ void CenterDialog (dt) DialogTHndl dt; #define menuHeight 20 { Rect r; short width; short height; width = screenBits.bounds.right; height = screenBits.bounds.bottom; r = (**dt).boundsRect; OffsetRect (&r, -r.left, -r.top); OffsetRect (&r, (width - r.right) / 2, (height - r.bottom - menuHeight) / 3 + menuHeight); (**dt).boundsRect = r; } #undef menuHeight /*****************************************************************************/ /* Displays the about dialog box for the plug-in module. */ void DoAbout (void) #define dialogID 16000 { short item; DialogPtr dp; DialogTHndl dt; dt = (DialogTHndl) GetResource ('DLOG', dialogID); HNoPurge ((Handle) dt); CenterDialog (dt); dp = GetNewDialog (dialogID, nil, (WindowPtr) -1); ModalDialog (nil, &item); DisposDialog (dp); HPurge ((Handle) dt); } #undef dialogID /*****************************************************************************/ /* Prepare to acquire an image. If the plug-in module needs only a limited amount of memory, it can lower the value of the 'maxData' field. */ void DoPrepare (void) { if (gStuff->maxData > 0x80000) gStuff->maxData = 0x80000; } /*****************************************************************************/ /* UserItem to outline the OK button in a dialog box. */ pascal void OutlineOK (dp, item) DialogPtr dp; short item; { Rect r; Handle h; short itemType; SetUpA4 (); item = OK; GetDItem (dp, item, &itemType, &h, &r); PenNormal (); PenSize (3, 3); InsetRect (&r, -4, -4); FrameRoundRect (&r, 16, 16); PenNormal (); RestoreA4 (); } /*****************************************************************************/ /* Converts a string to a number between 1 and 30000. Returns false if not a valid number or out of range. */ Boolean ConvertString (s, n) Str255 s; short *n; { long x; short j; for (j = 1; j <= Length (s); j++) if (s [j] < '0' || s [j] > '9') return false; StringToNum (s, &x); if (x < 1 || x > 30000) return false; *n = x; return true; } /*****************************************************************************/ /* Prompt the user for the image parameters. Returns false if the user cancels. */ Boolean GetParameters (rows, cols, mode) short *rows; short *cols; short *mode; #define dialogID 16001 #define hookItem 3 #define rowsItem 4 #define colsItem 5 #define bModeItem 6 #define gModeItem 7 #define iModeItem 8 #define cModeItem 9 { Rect r; Str255 s; Handle h; short item; DialogPtr dp; DialogTHndl dt; short itemType; Handle rowsText; Handle colsText; ControlHandle gButton; ControlHandle bButton; ControlHandle iButton; ControlHandle cButton; dt = (DialogTHndl) GetResource ('DLOG', dialogID); HNoPurge ((Handle) dt); CenterDialog (dt); dp = GetNewDialog (dialogID, nil, (WindowPtr) -1); RememberA4 (); GetDItem (dp, hookItem, &itemType, &h , &r); SetDItem (dp, hookItem, itemType, (Handle) &OutlineOK, &r); GetDItem (dp, rowsItem, &itemType, &rowsText, &r); GetDItem (dp, colsItem, &itemType, &colsText, &r); NumToString (*rows, s); SetIText (rowsText, s); NumToString (*cols, s); SetIText (colsText, s); SelIText (dp, rowsItem, 0, 32767); GetDItem (dp, bModeItem, &itemType, (Handle *) &bButton, &r); GetDItem (dp, gModeItem, &itemType, (Handle *) &gButton, &r); GetDItem (dp, iModeItem, &itemType, (Handle *) &iButton, &r); GetDItem (dp, cModeItem, &itemType, (Handle *) &cButton, &r); do { SetCtlValue (bButton, *mode == acquireModeBitmap); SetCtlValue (gButton, *mode == acquireModeGrayScale); SetCtlValue (iButton, *mode == acquireModeIndexedColor); SetCtlValue (cButton, *mode == acquireModeRGBColor); ModalDialog (nil, &item); if (item >= bModeItem && item <= cModeItem) *mode = item - bModeItem; if (item == OK) { GetIText (rowsText, s); if (!ConvertString (s, rows)) { SelIText (dp, rowsItem, 0, 32767); SysBeep (1); item = 0; } } if (item == OK) { GetIText (colsText, s); if (!ConvertString (s, cols)) { SelIText (dp, colsItem, 0, 32767); SysBeep (1); item = 0; } } } while (item != OK && item != Cancel); DisposDialog (dp); HPurge ((Handle) dt); return item == OK; } #undef dialogID #undef hookItem #undef rowsItem #undef colsItem #undef bModeItem #undef gModeItem #undef iModeItem #undef cModeItem /*****************************************************************************/ /* Asks the user and the returns to the calling program the image parmaters. */ void DoStart (void) { short j; gStuff->imageSize.v = gPermanent.lastRows; gStuff->imageSize.h = gPermanent.lastCols; gStuff->imageMode = gPermanent.lastMode; if (!GetParameters (&gStuff->imageSize.v, &gStuff->imageSize.h, &gStuff->imageMode)) { gResult = 1; return; } gPermanent.lastRows = gStuff->imageSize.v; gPermanent.lastCols = gStuff->imageSize.h; gPermanent.lastMode = gStuff->imageMode; gNextRow = 0; gNextPlane = 0; if (gStuff->imageMode == acquireModeBitmap) gStuff->depth = 1; else gStuff->depth = 8; if (gStuff->imageMode == acquireModeRGBColor) gStuff->planes = 3; else gStuff->planes = 1; if (gStuff->depth == 1) { gStuff->imageHRes = FixRatio (300, 1); gStuff->imageVRes = FixRatio (300, 1); } else { gStuff->imageHRes = FixRatio (72, 1); gStuff->imageVRes = FixRatio (72, 1); } if (gStuff->imageMode == acquireModeIndexedColor) for (j = 0; j < 256; j++) { gStuff->redLUT [j] = j; gStuff->greenLUT [j] = 255 - j; gStuff->blueLUT [j] = j; } gStuff->data = nil; } /*****************************************************************************/ /* Returns the next hunk of the image to the calling program. */ void DoContinue (void) { Ptr p; short row; short col; long count; if (gStuff->data) { DisposPtr (gStuff->data); gStuff->data = nil; } if (gNextPlane != gStuff->planes) { gStuff->colBytes = 1; if (gStuff->depth == 8) gStuff->rowBytes = gStuff->imageSize.h; else gStuff->rowBytes = (gStuff->imageSize.h + 7) >> 3; gStuff->loPlane = gNextPlane; gStuff->hiPlane = gNextPlane; count = gStuff->maxData / gStuff->rowBytes; if (count < 1) { gResult = memFullErr; return; } if (count > gStuff->imageSize.v - gNextRow) count = gStuff->imageSize.v - gNextRow; gStuff->data = NewPtr (count * gStuff->rowBytes); if (!gStuff->data) { gResult = memFullErr; return; } SetRect (&gStuff->theRect, 0, gNextRow, gStuff->imageSize.h, gNextRow + count); p = gStuff->data; for (row = gNextRow; row < gNextRow + count; row++) { if (TestAbort ()) { gResult = 1; return; } UpdateProgress (gNextPlane * ((long) gStuff->imageSize.v) + row, gStuff->planes * ((long) gStuff->imageSize.v)); for (col = 0; col < gStuff->rowBytes; col++) { if (gStuff->depth == 1) *(p++) = 0xFF << (row & 7); else if (gStuff->planes == 1) *(p++) = row + col; else if (gNextPlane == 0) *(p++) = col; else if (gNextPlane == 1) *(p++) = row; else *(p++) = row + col; } } gNextRow = gNextRow + count; if (gNextRow == gStuff->imageSize.v) { gNextRow = 0; gNextPlane = gNextPlane + 1; } } } /*****************************************************************************/ /* This routine will always be called if DoStart does not return an error (even if DoContinue returns an error or the user aborts the operation). This allows the module to perform any needed cleanup. */ void DoFinish (void) { if (gStuff->data) { DisposPtr (gStuff->data); gStuff->data = nil; } } /*****************************************************************************/ /* Main dispatching routine. Initializes and sets up the global variables, and performs the operation specified by the selector. */ pascal void main (selector, stuff, data, result) short selector; AcquireRecordPtr stuff; long *data; short *result; { Boolean firstTime; /* Allow access to global variables */ RememberA0 (); SetUpA4 (); /* Copy the current quickdraw globals into the plug-in local copy */ asm { MOVE.L (A5),A0 ; Get address of real quickdraw globals SUB.L #126,A0 ; Move to start LEA randSeed,A1 ; Get address of local copy MOVE.W #64,D0 ; Globals are 65 words long @1 MOVE.W (A0)+,(A1)+ ; Copy a word DBF D0,@1 ; Move to next word } /* See if this is the first time called */ if (!*data) { /* Allocate a handle to hold permanent values */ *data = (long) NewHandle ((long) sizeof (TPermanent)); if (!*data) { *result = memFullErr; RestoreA4 (); return; } /* Initialize the permanent values */ InitGlobals (); } /* Else restore permanent values */ else BlockMove (*((Handle) *data), (Ptr) &gPermanent, (long) sizeof (TPermanent)); /* Perform the requested operation */ gStuff = stuff; gResult = noErr; switch (selector) { case acquireSelectorAbout: DoAbout (); break; case acquireSelectorPrepare: DoPrepare (); break; case acquireSelectorStart: DoStart (); break; case acquireSelectorContinue: DoContinue (); break; case acquireSelectorFinish: DoFinish (); break; default: gResult = acquireBadParameters; } *result = gResult; /* Save permanent values */ BlockMove ((Ptr) &gPermanent, *((Handle) *data), (long) sizeof (TPermanent)); /* Restore the application's A4 register */ RestoreA4 (); }