home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * A Generic Desk Accessory written in LightSpeedC¬
- *
- * By David HM Spector
- * Copyright ⌐1986, All Rights Reserved
- *
- * Permission is granted for unlimited non-commercial use.
- * Permission is granted for commercial use provided credit is given in the
- * desk accessory and its documentation.
- *
- *
- * Please mail suggestions, et al to:
- *
- * US Snail: David HM Spector
- * 310 West 18th St. #5A
- * New York, NY 10011
- *
- * ARPAnet: SPECTOR@NYU.EDU
- * USEnet: ...{allegra,siesmo, rocky, ihnp4}!cmcl2!spector
- * MCIMail: DSPECTOR
- * GEnie: XJM21945
- *
- *
- * This is a Generic DA written in LightSpeedC¬. I wrote it because I often
- * write DA's, and I hate to start them from scratch each and every time.
- * Gutting other DA's is also, to say the least, a pain. So I decided to write
- * a complete minimal Desk Accessory that would do everything a real DA
- * could do and still be simple to modify and understand. Hence, the GenericDA.
- *
- * Among other things, GenericDA will do the following:
- * o put up its own window
- * o put up its own menu(s) (with an about box)
- * o respond to update events
- * o respond to activate events (including inserting/removing its menu)
- * o respond to keydown/autokey events (you'll have to write your own edit
- * functions though)
- *
- *
- * What you need:
- * 1. LightSpeedC¬ version 1.05 or later.
- * 2. RMaker1.01b1 or later (for the GenericDA.r file) -or- ResEdit1.0 or later
- *
- * Compiling the DA:
- * 1. Make a new project and add this file, and the MacTraps library.
- * 2. Set the project type to "Desk Accessory" (and pick a name).
- * 3. Edit the GenericDA file to use the correct path names for your system
- * 4. Compile and save the DA.
- * 5. Edit the RMaker file to reflect the path name for the name you gave the
- * DA you just compiled.
- * 6. Run the RMaker on the Rmaker file and install the DA with Font/DA Mover.
- *
- *
- *
- * Revision History
- *
- * Date Version Who What
- * 11/8/86 0.0 DHMS Start. Defined routines, added
- * event handler.
- * 0.5 DHMS Added Menus and owned resources
- * 1.0 DHMS Fixed bug in doEvent.[ Forgot to
- * Cast csParam[0] to be (EventRecord *)
- * -- causes an address error...
- */
-
-
- /* This covers almost all of the available include files, some of these may
- * not be needed by your Desk Accessory... it would speed compilation to
- * remove all but the ones you need.
- *
- * Note: The path name will have to be changed to match your configuration.
- */
- #include "HD╨20:Compilers:LS C:Mac #Includes:MacTypes.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:AppleTalk.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:ControlMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:DeskMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:DeviceMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:DialogMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:EventMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:HFS.h" /* only for LSC 2.0 or later! */
- #include "HD╨20:Compilers:LS C:Mac #Includes:MemoryMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:MenuMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:OSUtil.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:PackageMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:Quickdraw.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:ResourceMgr.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:StdFilePkg.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:TextEdit.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:ToolboxUtil.h"
- #include "HD╨20:Compilers:LS C:Mac #Includes:WindowMgr.h"
-
- /* Misc useful define's */
- #define NIL 0 /* for pointers, etc */
- #define INFRONT -1 /* for windows */
- #define False 0
- #define True 0xFF
- #define OFF 0 /* RadioButton control values */
- #define ON 1
- #define ACTIVE 0 /* For fiddling with other control states */
- #define INACTIVE 255
-
- #define drvrOpen 0
- #define drvrPrime 1
- #define drvrControl 2
- #define drvrStatus 3
- #define drvrClose 4
-
- #define WINDOWTYPE rDocProc
- #define WINDOWTITLE "\pA Generic DA"
- #define THEMENUID 1 /* this is a local ID that must be resolved */
- #define ABOUTBOX 1 /* The About╔ box for this DA */
-
-
- Rect windowRect = {40, 20, 100, 200};
- MenuHandle ourMenu = 0;
- int refNum = 0; /* this is the drivers refnum that is in dce->dCtlRefNum */
-
- /* Routines used by the driver's main routines */
- int resolveid(refNum,theid)
- int refNum;
- int theid;
- /* See Inside Macintosh, Vol.I, Pp.109-110 for info on calculating owned IDs */
- {
- return ( ( 0xC000 | (refNum<<5) ) + theid);
- }
-
- char validWindow(window)
- WindowPtr window;
- {
- WindowPtr nextWindow;
-
- if (window)
- {
- nextWindow = FrontWindow();
- while (nextWindow)
- if (window == nextWindow) return (1);
- else nextWindow = (WindowPtr)(((WindowPeek)nextWindow)->nextWindow);
- }
- return 0;
- }
-
- doAboutBox(window)
- WindowPtr window;
- {
- DialogPtr theDialog;
-
- theDialog = GetNewDialog(resolveid(refNum,ABOUTBOX),NIL,INFRONT);
- SetPort(theDialog);
- DrawDialog(theDialog);
- do
- ;
- while (!Button());
- CloseDialog(theDialog);
- SetPort(window);
- }
-
-
- /* Driver Routines Live Here */
-
- open(iopb,dce)
- cntrlParam *iopb; /* pointer to parameter block */
- DCtlPtr dce; /* the device control entry */
- {
- WindowPtr window;
- GrafPtr oldPort;
-
- refNum = dce->dCtlRefNum;
- if (refNum < 0)
- refNum = -refNum;
- refNum = refNum - 1;
-
- if ((window = dce->dCtlWindow) == 0) /* already have a window? */
- {
- GetPort(&oldPort);/* no, make new one╔ */
- window = NewWindow(0, &windowRect, WINDOWTITLE, 0, WINDOWTYPE,INFRONT, 1, 0);
- SetPort(window);
- ((WindowPeek)window)->windowKind = dce->dCtlRefNum;
- dce->dCtlWindow = window;
-
- ourMenu = GetMenu(resolveid(refNum,THEMENUID));
- dce->dCtlMenu = resolveid(refNum,THEMENUID);
- InsertMenu(ourMenu,0);
-
- SetPort(oldPort);
- }
- return(0);
- }
-
- prime(iopb,dce)
- cntrlParam *iopb; /* pointer to parameter block */
- DCtlPtr dce; /* the device control entry */
- {
- /* Generally, only 'real' device drivers respond to prime calls */
- return(0);
- }
-
- control(iopb,dce)
- cntrlParam *iopb; /* pointer to parameter block */
- DCtlPtr dce; /* the device control entry */
- {
- GrafPtr ourPort;
- WindowPtr window;
-
- if (validWindow(window = dce->dCtlWindow))
- {
- GetPort(&ourPort);
- SetPort(window);
-
- switch (iopb->csCode)
- {
- case accEvent:
- doEvent(((EventRecord *) * (long *) &iopb->csParam),window);
- break;
- case accRun:
- /* If you are getting time from the system, here's where to
- * do your thing.
- */
- break;
- case accCursor:
- break;
- case accMenu:
- {
- int menuItem;
- menuItem = iopb->csParam[1];
- switch (menuItem)
- {
- /* Handle your menu items here╔ */
- case 1:
- doAboutBox(window);
- break;
- case 2:
- SysBeep(3);
- break;
- /* ╔ */
- default:
- SysBeep(3);
- break;
- }
- HiliteMenu(0);
- break;
- }
- case accUndo:
- SysBeep(2);
- break;
- case accCut:
- SysBeep(2);
- break;
- case accCopy:
- SysBeep(2);
- break;
- case accPaste:
- SysBeep(2);
- break;
- case accClear:
- SysBeep(2);
- break;
- }
- SetPort(ourPort);
- }
- return(0);
- }
-
- doEvent(event, window)
- EventRecord *event;
- WindowPtr window;
- {
- SetPort(window);
- switch (event->what)
- {
- case keyDown:
- case autoKey:
- if ((event->modifiers & cmdKey))
- {
- switch ((char) (event->message))
- {
- case 'c':
- case 'C':
- SysBeep(2);
- break;
- case 'v':
- case 'V':
- SysBeep(2);
- break;
- case 'x':
- case 'X':
- SysBeep(2);
- break;
- default:
- SysBeep(2);
- }
- break;
- }
- return;
-
- case mouseDown:
- GlobalToLocal(&event->where);
- return;
-
- case updateEvt:
- SetPort(window);
- BeginUpdate(window);
- /* Do update stuff here */
- EndUpdate(window);
- return;
-
- case activateEvt:
- if ((event->modifiers & activeFlag)) {
- InsertMenu(ourMenu,0); /* put menu up */
- DrawMenuBar();
- }
- else {
- DeleteMenu(resolveid(refNum,THEMENUID));
- DrawMenuBar();
- }
- return;
- }
- }
-
-
- status(iopb,dce)
- cntrlParam *iopb; /* pointer to parameter block */
- DCtlPtr dce; /* the device control entry */
- {
- /* Generally, only 'real' device drivers respond to status calls */
- return(0);
- }
-
- close(iopb,dce)
- cntrlParam *iopb; /* pointer to parameter block */
- DCtlPtr dce; /* the device control entry */
- {
- WindowPtr window;
-
- if (validWindow(window = dce->dCtlWindow))
- {
- DeleteMenu(resolveid(refNum,THEMENUID));
- DrawMenuBar();
- dce->dCtlMenu = NIL;
- DisposeWindow(window);
- dce->dCtlWindow = NIL;
- }
- return(0);
- }
-
-
- main(iopb, dce, n)
- cntrlParam *iopb; /* pointer to parameter block */
- DCtlPtr dce; /* the device control entry */
- int n; /* routine selector */
- {
-
- /* Make sure that our 'globals' we actually allocated for us.
- * give up if they weren't.
- */
- if (dce->dCtlStorage == 0) {
- if (n == 0) { /* open, but no data */
- SysBeep(3);
- CloseDriver(dce->dCtlRefNum);
- }
- return(0);
- }
- /* Since we're here, we have our globals, now set the flags╔ */
- dce->dCtlFlags |= dNeedLock | dNeedTime;
- dce->dCtlDelay = 60; /* 1 second - 60 ticks */
-
- switch (n) {
- case drvrOpen:
- open(iopb,dce);
- break;
- case drvrPrime:
- prime(iopb,dce);
- break;
- case drvrControl:
- control(iopb,dce);
- break;
- case drvrStatus:
- status(iopb,dce);
- break;
- case drvrClose:
- close(iopb,dce);
- break;
- }
-
- }