wade blomgren
unread,Sep 2, 1986, 6:04:35 PM9/2/86You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# ascii_chart.c
sed 's/^X//' << 'SHAR_EOF' > ascii_chart.c
X/*************************************************************************/
X/* Ascii Chart - a Desk Accessory for the Macintosh written by: */
X/* Wade S. Blomgren (c) 1986 version 1.0 */
X/* UC San Diego */
X/* */
X/* Both source and executable files may be freely distributed for */
X/* NON-COMMERCIAL USE ONLY provided this copyright notice is left */
X/* intact. */
X/* */
X/* This program is intended as an example for persons beginning to */
X/* learn about programming the Macintosh. It is NOT meant to be an */
X/* example of excellent programming or a particularly fabulous */
X/* idea for a program. It IS supposed to be chock full of comments */
X/* and to have some examples of common uses for the toolbox. */
X/* */
X/* This program was written using LightspeedC (c) from Think */
X/* Technologies, INC. and therefore includes material that is */
X/* copyright Think Technologies INC. */
X/* */
X/* Some techniques were gleaned from a PD desk accessory called */
X/* ZoomIdle by Paul DuBois, University of Wisconsin */
X/* */
X/* Wade S. Blomgren UCSD-ACS mailcode B-028 La Jolla, CA 92093 */
X/* */
X/*************************************************************************/
X
X#include "devicemgr.h"
X#include "quickdraw.h"
X#include "windowmgr.h"
X#include "dialogmgr.h"
X#include "eventmgr.h"
X#include "controlmgr.h"
X
X/* since this is a DA and not a standalone application we do not have to */
X/* initialize the various managers */
X
X/* Global Variables for the DA */
X
X/* the chart data is stored in two dimensional arrays so we can use the */
X/* drawtext routine (faster than repeated calls to drawchar) (IM I-172) */
X
X char octdata[23][47] = {
X "000 NUL 026 SYC 054 , 102 B 130 X 156 n ",
X "001 SOH 027 ETB 055 - 103 C 131 Y 157 o ",
X "002 STX 030 CAN 056 . 104 D 132 Z 160 p ",
X "003 ETX 031 EM 057 / 105 E 133 [ 161 q ",
X "004 EOT 032 SUB 060 0 106 F 134 \\ 162 r ",
X "005 ENQ 033 ESC 061 1 107 G 135 ] 163 s ",
X "006 ACK 034 FS 062 2 110 H 136 ^ 164 t ",
X "007 BEL 035 GS 063 3 111 I 137 _ 165 u ",
X "010 BS 036 RS 064 4 112 J 140 ` 166 v ",
X "011 HT 037 US 065 5 113 K 141 a 167 w ",
X "012 LF 040 SPA 066 6 114 L 142 b 170 x ",
X "013 VT 041 ! 067 7 115 M 143 c 171 y ",
X "014 FF 042 '' 070 8 116 N 144 d 172 z ",
X "015 CR 043 # 071 9 117 O 145 e 173 { ",
X "016 SO 044 $ 072 : 120 P 146 f 174 | ",
X "017 SI 045 % 073 ; 121 Q 147 g 175 } ",
X "020 DLE 046 & 074 < 122 R 150 h 176 ~ ",
X "021 DC1 047 ' 075 = 123 S 151 i 177 DEL",
X "022 DC2 050 ( 076 > 124 T 152 j ",
X "023 DC3 051 ) 077 ? 125 U 153 k ",
X "024 DC4 052 * 100 @ 126 V 154 l ",
X "025 NAK 053 + 101 A 127 W 155 m "};
X
X char decdata[23][47] = {
X "000 NUL 022 SYC 044 , 066 B 088 X 110 n ",
X "001 SOH 023 ETB 045 - 067 C 089 Y 111 o ",
X "002 STX 024 CAN 046 . 068 D 090 Z 112 p ",
X "003 ETX 025 EM 047 / 069 E 091 [ 113 q ",
X "004 EOT 026 SUB 048 0 070 F 092 \\ 114 r ",
X "005 ENQ 027 ESC 049 1 071 G 093 ] 115 s ",
X "006 ACK 028 FS 050 2 072 H 094 ^ 116 t ",
X "007 BEL 029 GS 051 3 073 I 095 _ 117 u ",
X "008 BS 030 RS 052 4 074 J 096 ` 118 v ",
X "009 HT 031 US 053 5 075 K 097 a 119 w ",
X "010 LF 032 SPA 054 6 076 L 098 b 120 x ",
X "011 VT 033 ! 055 7 077 M 099 c 121 y ",
X "012 FF 034 '' 056 8 078 N 100 d 122 z ",
X "013 CR 035 # 057 9 079 O 101 e 123 { ",
X "014 SO 036 $ 058 : 080 P 102 f 124 | ",
X "015 SI 037 % 059 ; 081 Q 103 g 125 } ",
X "016 DLE 038 & 060 < 082 R 104 h 126 ~ ",
X "017 DC1 039 ' 061 = 083 S 105 i 127 DEL",
X "018 DC2 040 ( 062 > 084 T 106 j ",
X "019 DC3 041 ) 063 ? 085 U 107 k ",
X "020 DC4 042 * 064 @ 086 V 108 l ",
X "021 NAK 043 + 065 A 087 W 109 m " };
X
X char hexdata[23][47] = {
X
X "000 NUL 016 SYC 02C , 042 B 058 X 06E n ",
X "001 SOH 017 ETB 02D - 043 C 059 Y 06F o ",
X "002 STX 018 CAN 02E . 044 D 05A Z 070 p ",
X "003 ETX 019 EM 02F / 045 E 05B [ 071 q ",
X "004 EOT 01A SUB 030 0 046 F 05C \\ 072 r ", /* escape the \
Xcharacter */
X "005 ENQ 01B ESC 031 1 047 G 05D ] 073 s ",
X "006 ACK 01C FS 032 2 048 H 05E ^ 074 t ",
X "007 BEL 01D GS 033 3 049 I 05F _ 075 u ",
X "008 BS 01E RS 034 4 04A J 060 ` 076 v ",
X "009 HT 01F US 035 5 04B K 061 a 077 w ",
X "00A LF 020 SPA 036 6 04C L 062 b 078 x ",
X "00B VT 021 ! 037 7 04D M 063 c 079 y ",
X "00C FF 022 '' 038 8 04E N 064 d 07A z ",
X "00D CR 023 # 039 9 05F O 065 e 07B { ",
X "00E SO 024 $ 03A : 050 P 066 f 07C | ",
X "00F SI 025 % 03B ; 051 Q 067 g 07D } ",
X "010 DLE 026 & 03C < 052 R 068 h 07E ~ ",
X "011 DC1 027 ' 03D = 053 S 069 i 07F DEL",
X "012 DC2 028 ( 03E > 054 T 06A j ",
X "013 DC3 029 ) 03F ? 055 U 06B k ",
X "014 DC4 02A * 040 @ 056 V 06C l ",
X "015 NAK 02B + 041 A 057 W 06D m " };
X
X DCtlPtr dce; /* pointer to the device control entry struct */
X int DAisOpen = 0; /* flag so we know if the DA is already open */
X
X#define rALRT 0 /* the About box's resource ID # */
X
X/* allocate control handles to the various control buttons */
X
X ControlHandle OctPtr,HexPtr,DecPtr,curControl,whichControl,AbPtr;
X
X
X int line; /* counter for the text drawing loop */
X int y; /* coordinate variable for positioning the text */
X
X/* define rectangles for the DA's window and the control buttons */
X/* BlankRect is the entire data area & is used to erase the data */
X static Rect bounds = { 60,60, 335, 350 };
X static Rect OctRect = { 225,12,242,80 };
X static Rect HexRect = { 225,115, 242, 185 };
X static Rect DecRect = { 225,200, 242, 268 };
X static Rect AbRect = { 250,85, 270, 205 };
X static Rect BlankRect = { 3,12,220,280 };
X
X/* various functions begin here - see 'main' for calling sequence */
X
X
XaboutDA() /* creates an alert dialog message about */
X /* the DA and gives an OK button to exit */
X{
X /* the alert resource and accompanying item list are stored in a */
X /* file called "ascii_chart.rsrc" which was created with ResEdit */
X /* ..since the OK button is the default (highlighted) choice, we */
X /* do not have to have a filterProc (IM I-419) */
X /* If you examine the DA file with ResEdit, you will see that the */
X /* resource ID for the ALRT is -16000, which translates into an */
X /* 'owned' resource ID of '0' (zero) for a DRVR (our program) */
X /* with an ID of '12'. This is the ID number that LightspeedC */
X /* assigns to a Desk Accesory that it creates. When you install */
X /* a DA with the Font/DA mover, it checks to see that the ID# does */
X /* not conflict with that of an existing DA. If it does, the F/DA */
X /* will change our DA's ID to an unused #, and all of the 'owned' */
X /* resource ID's will be shifted accordingly. Read IM I-108,109. */
X
X Alert(rsrcID(rALRT),0L); /* invoke the alert (IM I-418) */
X
X}
X
X/* this routine from the LightspeedC demo DA by Michael Kahl... */
X/* returns the correct resource ID number "no matter what driver # */
X/* the Font/DA Mover has assigned us... " (IM I-109) */
X
XrsrcID(id)
X{
X return(0xc000 + (~dce->dCtlRefNum << 5 ) + id);
X}
X
X
X/* window update routine - if it's a result of a radix change, scope */
X/* is 0 (update everything) - if it is a system update event, update */
X/* only the area that needs it, by using BeginUpdate & EndUpdate */
X/* (see calls to 'updateDisplay()' in 'main' and 'DAEvent' */
X
XupdateDisplay(scope)
Xint scope;
X{
X
XGrafPtr currentPort;
XPtr dataAddr; /* a generic 'pointer' data type */
X
XGetPort(¤tPort); /* save the current grafport (IM I-447) */
XSetPort(dce->dCtlWindow); /* set the grafport to our window */
X
X if (scope)
X BeginUpdate(dce->dCtlWindow); /* set the visRgn to only the part */
X /* that needs updating (IM I-292) */
X /* otherwise, redraw the whole window */
X
X DrawControls(dce->dCtlWindow); /* draw the controls in our window */
X EraseRect(&BlankRect); /* blank out the old data (IM I-177) */
X y = 10;
X
X if (curControl == OctPtr) /* determine which control was pressed */
X dataAddr = (Ptr) octdata; /* & cast the address of the 2D array */
X else if (curControl == DecPtr) /* into our generic data pointer */
X dataAddr = (Ptr) decdata;
X else if (curControl == HexPtr)
X dataAddr = (Ptr) hexdata;
X
X TextFont(4); /* Monaco font for evenly spaced columns (IM I-219) */
X TextSize(9); /* these are quickdraw functions */
X
X for (line = 0; line < 22; line++) {
X
X /* we have 23 lines per 'page' - use quickdraw to output the data */
X /* the starting address for DrawText is (line# * 47) to get to the */
X /* proper position in the 2D array */
X
X MoveTo(12,y);
X DrawText(dataAddr + (line * 47),0,46); /* (IM I-172) */
X y = y +10;
X }
X
X if (scope) EndUpdate(dce->dCtlWindow);
X
XSetPort(currentPort); /* restore the current grafport (IM I-447) */
X
X} /* end of updateDisplay */
X
X
X
XopenDA() /* open the desk accessory */
X{
X
X GrafPtr currentPort;
X
X if (DAisOpen) return; /* if it is already open, just ignore */
X GetPort(¤tPort); /* save the current grafport */
X
X/* create our window, set the device control entry (dce) window field */
X/* to our window, set the window's windowKind field to the reference # */
X/* for the driver (IM I-445) */
X
X dce->dCtlWindow = NewWindow(0,&bounds,"\pAscii Chart",0,16,-1,1,0);
X ((WindowPeek) (dce->dCtlWindow))->windowKind = dce->dCtlRefNum;
X
X SetPort(dce->dCtlWindow); /* set the grafport to our window */
X ShowWindow(dce->dCtlWindow); /* display the window */
X
X
X /* create new controls for the various radixes and the about box */
X /* set the octal radix control to be 'on'... (IM I-319) */
X OctPtr = NewControl(dce->dCtlWindow,&OctRect,"\poctal",1,1,0,1,2,0);
X HexPtr = NewControl(dce->dCtlWindow,&HexRect,"\phex",1,0,0,1,2,0);
X DecPtr = NewControl(dce->dCtlWindow,&DecRect,"\pdecimal",1,0,0,1,2,0);
X AbPtr = NewControl(dce->dCtlWindow,&AbRect,"\pabout ascii
Xchart",1,1,0,0,0,0);
X
X curControl = OctPtr; /* set default for current control button */
X
X/* we do not need to explicitly call "updateDisplay" because the open */
X/* routine will cause an update event to be sent to the Desk Manager */
X
X DAisOpen = 1; /* set the DA 'on' (our own flag) */
X SetPort(currentPort); /* restore original grafport */
X
Xreturn(0);
X
X} /* end of the openDA routine */
X
X
XDAevent(theEvent)
XEventRecord *theEvent; /* argument is a pointer to an event record */
X{
X
XGrafPtr currentPort;
X
XGetPort(¤tPort); /* save the system's current grafport */
X
X/* at this point we know there has been an event in the DA window */
X/* content region, so we must process the event */
X
XSetPort(dce->dCtlWindow); /* set the port to our window */
X
Xswitch (theEvent->what) { /* examine the 'what' field of event */
X /* (IM I-263,264) */
X case activateEvt: /* the DA window has become active */
X updateDisplay(1);
X return(0);
X
X case updateEvt: /* we need to update (result of drag, etc) */
X updateDisplay(1);
X return(0);
X
X case mouseDown:
X /* convert the location to local coordinates (IM I-193,323) */
X GlobalToLocal(&(theEvent->where));
X
X /* find where mouse was pressed - (the part code) (IM I-334) */
X
X switch (FindControl(theEvent->where,dce->dCtlWindow,&whichControl)) {
X
X case (11): /* a RADIO button has been hit - track it */
X
X /* track control routine makes sure mouse is released in button
X*/
X if (TrackControl(whichControl,theEvent->where,0)) {
X
X if (whichControl != curControl) { /* a new radix */
X SetCtlValue(curControl,0);
X curControl = whichControl; /* set new 'current' ctl */
X SetCtlValue(curControl,1);
X updateDisplay(0); /* update whole window */
X } /* end new radix */
X } /* end if track control */
X break;
X case (10): /* SIMPLE button (must be the about box) */
X
X /* create an alert dialog with an OK button to terminate */
X
X aboutDA();
X break;
X
X } /* end possible control mousedown */
X
X LocalToGlobal(&theEvent->where); /* put the coordinates back to global
X*/
X
X } /* end of the event switch */
X
X SetPort(currentPort); /* restore the grafport */
X
X} /* end of DAevent */
X
X
X
X/* close DA function */
X
XcloseDA()
X{
X GrafPtr currentPort;
X
X GetPort(¤tPort); /* save the system's grafport */
X DisposeWindow(dce->dCtlWindow);/* dispose our window */
X dce->dCtlWindow = 0L; /* set the driver's window ptr to null */
X /* (IM I-446) */
X SetPort(currentPort); /* restore the system's grafport */
X return(0);
X
X}
X/* main driver routine - three parameters are passed to us through the */
X/* device manager. 1. the control parameter pointer */
X/* 2. the pointer to the dce record */
X/* 3. the driver routine (open, control, or close) */
X/* (IM II-201, I-445 ) */
X
X
Xmain (p,d,n)
XcntrlParam *p;
XDCtlPtr d;
Xint n;
X
X
X{
X
Xif (d->dCtlStorage == 0 ) {
X if (n == 0) { /* open but no data */
X SysBeep(3);
X CloseDriver(d->dCtlRefNum);
X }
X return(0);
X }
X
X dce = d;
X
X/* find the appropriate driver routine */
X
X switch(n) { /* 0 = open, 2 = control event, 4 = close */
X
X case 0: /* open the DA */
X openDA();
X break;
X
X case 2: /* action in the DA */
X switch(p->csCode) {
X
X case accEvent:
X DAevent(((EventRecord *) * (long *) &p->csParam));
X
X /* casting the *address of* p->csParam as an pointer to a long, and the */
X /* long is cast as a pointer to a pointer to an Event Record (I think?) */
X /* (from ZoomIdle 1.1 by Paul DuBois) */
X /* the pointer is passed as the parameter to DAevent */
X
X
X } /* end of case 2 switch */
X break;
X
X case 4: /* close box has been clicked */
X closeDA();
X break;
X
X } /* end of the main switch */
X
X return(0);
X
X
X} /* end of main */
SHAR_EOF
exit