[net.sources] Macintosh Desk Installer/Launcher

fjh@bentley.UUCP (FJ Hirsch) (08/27/84)

#
# Here is Michael Schuster's desk accessory launcher/installer for
#	non-ARPA people.  
# Fred.
#
#Date: Wed, 22 Aug 84 19:12:23 pdt
#----------------------------------------------------------------------------
#! /bin/sh
echo x - desk.c
cat > desk.c << '{~}{~}'
/*
 * Desk accessory launcher/installer.
 *
 * (C) Copyright 1984 Michael Schuster
 * All Rights Reserved
 */

/*
 * 08/10/84	Schuster	Created
 * 08/21/84	Schuster	Search for unused resource id
 */

#include "quickdraw.h"
#include "osintf.h"
#include "toolintf.h"

#define NIL 0
#define FALSE 0
#define TRUE 1

#define minID 12
#define maxID 31

#define appleMenu 1
#define fileMenu 2
#define editMenu 3

#define closeItem 1
#define installItem 2
#define quitItem 3
#define undoItem 1
#define cutItem 3
#define copyItem 4
#define pasteItem 5
#define clearItem 6

MenuHandle menus[editMenu + 1];

main()
   {
   struct QDVar QDVar;
   EventRecord event;
   WindowPtr window;
   Rect dragRect;

   QD = &QDVar;
   InitGraf(&thePort);
   InitFonts();
   InitWindows();
   InitMenus();
   TEInit();

   dragRect = QD->screenBits.bounds; 

   menus[appleMenu] = NewMenu(appleMenu, "\24");
   AddResMenu(menus[appleMenu], "DRVR");
   InsertMenu(menus[appleMenu], 0);
   menus[fileMenu] = NewMenu(fileMenu, "File");
   AppendMenu(menus[fileMenu], "Close");
   AppendMenu(menus[fileMenu], "Install");
   AppendMenu(menus[fileMenu], "Quit");
   InsertMenu(menus[fileMenu], 0);
   menus[editMenu] = NewMenu(editMenu, "Edit");
   AppendMenu(menus[editMenu], "Undo/Z");
   AppendMenu(menus[editMenu], "(-");
   AppendMenu(menus[editMenu], "Cut/X");
   AppendMenu(menus[editMenu], "Copy/C");
   AppendMenu(menus[editMenu], "Paste/V");
   AppendMenu(menus[editMenu], "Clear/B");
   InsertMenu(menus[editMenu], 0);
   DrawMenuBar();

   SetCursor(&QD->arrow);
   while (TRUE)
      {
      SystemTask();
      if (FrontWindow())
         DisableItem(menus[fileMenu], installItem);
      else
         EnableItem(menus[fileMenu], installItem);

      if (!GetNextEvent(everyEvent, &event))
         continue;

      switch (event.what)
         {
         case mouseDown:
            switch (FindWindow(&event.where, &window))
               {
               case inMenuBar:
                  SetCursor(&QD->arrow);
                  commandEvent(MenuSelect(&event.where));
                  HiliteMenu(0);
                  break;

               case inSysWindow:
                  SystemClick(&event, window);
                  break;

               case inDrag:
                  DragWindow(window, &event.where, &dragRect);
                  break;

               case inGoAway:
                  if (TrackGoAway(window, &event.where))
                     commandEvent((fileMenu << 16) | closeItem);        
                  break;

               case inContent:
                  if (window != FrontWindow())
                     SelectWindow(window);
                  break;
               }
            break;

         case keyDown:
         case autoKey:
            if (event.modifiers & cmdKey)
               {
               commandEvent(MenuKey(event.message & 0xff));
               HiliteMenu(0);
               }
            break;
         }
      }
   }

commandEvent(menuItem)
   {
   WindowPtr window;
   int menu;
   int item;
   char name[64];
   char *c2pnstr();

   window = FrontWindow();
   SetPort(window);
   menu = HiWord(menuItem);
   item = LoWord(menuItem);

   switch (menu)
      {
      case appleMenu:
         GetItem(menus[appleMenu], item, name);
         OpenDeskAcc(c2pnstr(name));
         break;

      case fileMenu:
         switch (item)
            {
            case closeItem:
               CloseDeskAcc(((WindowPeek) window)->windowKind);
               break;

            case installItem:
               install();
               break;

            case quitItem:
               ExitToShell();
               break;    
            }
         break;

      case editMenu:
         switch (item)
            {
            case undoItem:
               SystemEdit(undoCmd);
               break;

            case cutItem:
               SystemEdit(cutCmd);
               break;

            case copyItem:
               SystemEdit(copyCmd);
               break;

            case pasteItem:
               SystemEdit(pasteCmd);
               break;

            case clearItem:
               SystemEdit(clearCmd);
               break;      
            }
         break;
      }
   }

/* install local drivers as system drivers */
install()
   {
   int i;
   int j;
   int k;
   int rsrc;
   Handle oldHandle;
   Handle handle;
   Handle drivers[16];
   ResType type;
   int id;
   int newId;
   int oldId;
   int attrs;
   char name[256];

   j = CountResources("DRVR");
   k = 0;
   rsrc = CurResFile();
   SetResLoad(FALSE);
   for (i = 1; i <= j; i++)
      {
      handle = GetIndResource("DRVR", i);
      if (handle)
         {
         ReleaseResource(handle);
         handle = GetIndResource("DRVR", i);
         }
      if (handle && HomeResFile(handle) == rsrc)
         drivers[++k] = handle;
      }
   SetResLoad(TRUE);

   for (i = 1; i <= k; i++)
      {
      UseResFile(rsrc);
      LoadResource(drivers[i]);
      handle = NewHandle(GetHandleSize(drivers[i]));
      if (!MemError())
         {
         BlockMove(*drivers[i], *handle, GetHandleSize(handle));
         GetResInfo(drivers[i], &id, type.s, name);
         attrs = GetResAttrs(drivers[i]);
         ReleaseResource(drivers[i]);
         UseResFile(0);

         if (oldHandle = GetNamedResource("DRVR", name))
            {
            GetResInfo(oldHandle, &oldId, type.s, name);
            UseResFile(rsrc);
            if (installAlert(name, "DRVR", oldId) == 2)
               continue;
            UseResFile(0);
            RmveResource(oldHandle);
            DisposHandle(oldHandle);
            id = oldId;
            }
         else
            {
	    SetResLoad(FALSE);
	    newId = minID;
	    while (newId <= maxID && (oldHandle = GetResource("DRVR", newId)))
	       {
	       ReleaseResource(oldHandle);
	       newId++;
	       }
	    SetResLoad(TRUE);
	    id = (newId <= maxID) ? newId : id;

	    if (oldHandle = GetResource("DRVR", id))
	       {
	       UseResFile(rsrc);
	       if (installAlert(name, "DRVR", id) == 2)
		  continue;
	       UseResFile(0);
	       RmveResource(oldHandle);
	       DisposHandle(oldHandle);
	       }
            }

         AddResource(handle, "DRVR", id, name);
         if (!ResError())
            {
            WriteResource(handle);
            SetResAttrs(handle, attrs);
            }
         }
      else
         ReleaseResource(drivers[i]);
      }
   UpdateResFile(0);
   UseResFile(rsrc);
   }

/* install alert */
installAlert(name, type, id)
   char *name;
   char *type;
   int id;
   {
   char idstring[16];

   NumToString(id, idstring);
   ParamText(name, type, idstring, "");
   return CautionAlert(256, (ProcPtr) NIL);
   }

/* convert a C string to a Pascal string with a leading NUL character */
char *c2pnstr(s)
   char *s;
   {
   extern char *isapstr();
   char *t;
   int i;
   int j;

   i = 0;
   while (*s++)
     i++;
   j = i;
   t = s - 2;
   while (j--)
      *s-- = *t--;
   *s-- = 0;
   *s = (char) i + 1;
   return(isapstr(s));
   }

{~}{~}
echo x - print.c
cat > print.c << '{~}{~}'
/*
 * Print desk accessory
 *
 * (C) Copyright 1984 Michael Schuster
 * All Rights Reserved
 *
 */

/*
 * 08/21/84	Schuster	Created
 */

#include "quickdraw.h"
#include "osintf.h"
#include "toolintf.h"
#include "packintf.h"
#include "device.h"

#define NIL 0
#define FALSE 0
#define TRUE 1

#define pageLen 62
#define topOfForm pChar('\014')
#define topSpace pChar('\n'); pChar('\n')

typedef struct
   {
   int volumn;			/* file volumn */
   char name[64];		/* file name */
   } File;

#define queueLen 8
File queue[queueLen];		/* file queue */

int indent;			/* indentation counter for tab handler */
int lines;			/* line counter for top of form handler */
#define bufferLen 64
char buffer[bufferLen];		/* io buffer */

int port;			/* printer port ID */
int file;			/* file ID */
int open;			/* TRUE if file open */

int inSFGetFile;		/* TRUE if SFGetFile dialog active */
   
/*
 * file routines
 */

/*
 * put a file into the queue
 */
putFile(name, length, volumn)
   char *name;
   {
   register int i;

   for (i = 0; i < queueLen; i++)
      {
      if (!*queue[i].name)
         {
	 BlockMove(name, queue[i].name, length);
         queue[i].name[length] = '\0';
	 queue[i].volumn = volumn;
	 return;
	 }
      }
   }

/*
 * get a file from the queue, if any
 */
getFile()
   {
   register int i;

   if (open)
      return TRUE;
   else
      {
      for (i = 0; i < queueLen; i++)
	 {
	 if (*queue[i].name)
	    {
	    open = 
               (FSOpen(queue[i].name, queue[i].volumn, &file)) ? FALSE : TRUE;
	    if (open)
	       {
	       pChar('\033');		/* software reset */
	       pChar('c');
	       topSpace;
	       }
            *queue[i].name = 0;
	    lines = indent = 0;
	    return open;
	    }
	 }
      return FALSE;
      }
   }

/*
 * close the open file and optionally purge all files from the queue
 */
closeFile(purge)
   {
   register int i;

   if (open)
      {
      topOfForm;
      FSClose(file);
      }
   open = FALSE;

   if (purge)
      for (i = 0; i < queueLen; i++)
	 *queue[i].name = 0;
   }

/*
 * driver routines
 */

/*
 * driver open routine
 */
drvrOpen(pb, dce)
   CntrlParam *pb;
   struct dce *dce;
   {
   Point point;
   SFReply sfReply;
   SFTypeList sfTypeList;

   FSOpen(".BOut", 0, &port);
   SetPt(&point, 50, 50);
   inSFGetFile = TRUE;
   BlockMove("TEXT", sfTypeList.ftype[0].s, 4);
   SFGetFile(&point,"",(ProcPtr)NIL,1,(Ptr)&sfTypeList,(ProcPtr)NIL,&sfReply);
   inSFGetFile = FALSE;
   if (sfReply.good)
      putFile(&sfReply.fName[1], sfReply.fName[0], sfReply.vRefNum);
   return(IOrts);
   }

/*
 * driver close routine
 */
drvrClose(pb, dce)
   CntrlParam *pb;
   struct dce *dce;
   {
   closeFile(FALSE);
   return(IOrts);
   }

/*
 * driver control routine
 */
drvrCtl(pb, dce)
   CntrlParam *pb;
   struct dce *dce;
   {
   int chars;

   switch (pb->CSCode)
      {
      case accRun:
         if (inSFGetFile)
            ;
	 else if (getFile() && !portHeldUp())
            {
            chars = bufferLen;
	    FSRead(file, &chars, buffer);
	    if (chars)
	       pText(chars, buffer);
	    else
	       closeFile(FALSE);
	    }
         else
            ; /* CloseDeskAcc(dce->dCtlRefNum); */
         break;
      }
   return(IOrts);
   }

/*
 * return TRUE if port held up
 */
portHeldUp()
   {
   OpParamType param;

   Status(port, 8, &param);
   return param.ASStaRec.CTSHold;
   }

/*
 * write char to port
 */
pChar(c)
   char c;
   {
   int chars;

   chars = 1;
   FSWrite(port, &chars, &c);
   }

/*
 * write text to port
 */
pText(chars, buffer)
   char *buffer;
   {
   register char *b;
   register char *p;
   register char *e;

   b = p = e = buffer;
   e += chars;
   while (p < e)
      {
      if (*p == '\r')
         {
	 *p++ = '\n';
         indent = 0;
	 lines++;
	 if (!(lines % pageLen))
	    {
	    chars = p - b;
	    FSWrite(port, &chars, b);
	    b = p;
	    topOfForm;
	    topSpace;
	    }
         }
      else if (*p == '\t')
         {
         chars = p - b;
	 FSWrite(port, &chars, b);
	 b = ++p;
	 chars = 8 - (indent % 8);
	 FSWrite(port, &chars, "        ");
	 indent += chars;
         }
      else if (*p < '\040' || *p > '\176')
         {
	 *p++ = ' ';
	 indent++;
	 }
      else
	 {
         p++;
	 indent++;
	 }
      }
   chars = p - b;
   FSWrite(port, &chars, b);
   }

/*
 * driver status routine
 */
drvrStatus(pb, dce)
   CntrlParam *pb;
   struct dce *dce;
   {
   return(IOrts);
   }

/*
 * driver prime routine
 */
drvrPrime(pb, dce)
   CntrlParam *pb;
   struct dce *dce;
   {
   return(IOrts);
   }
{~}{~}
echo x - crtprint.s
cat > crtprint.s << '{~}{~}'
|
| crtterm.s - self relocating C runtime startoff for Mac desk accessory
|
| Copyright (C) 1984, Stanford Univ. SUMEX project
| May be used but not sold without permission.
|
| history
| 07/20/84	Croft	Created.
| 08/21/84	Schuster	Customize for Print.
|
	.data
	.text
	.globl	_savea5
	.globl	drvr
	.globl	drvrOpen,drvrPrime,drvrCtl,drvrStatus,drvrClose

| driver header

drvr:
	.word	0x2400		| enable control, need time
	.word	60		| every second
	.word	0		| no events
	.word	0		| no menu
doffset:
	.word	reloc-drvr	| replaced by "dopen-drvr" after initialization
	.word	dprime-drvr
	.word	dctl-drvr
	.word	dstatus-drvr
	.word	dclose-drvr
	.byte	6
	.byte	0
	.ascii	"Print"
	.blkb	25		| 32 bytes total for name

reloc:	jra	.L21
	.long	0,0,0,0,0,0,0,0,0,0		| longruns from rmaker
_savea5:.long	0
|
| a1 = next longrun address
| a2 = current reloc address
| d1 = relocation factor
|
.L21:
	moveml	#0xffff,sp@-
	lea	pc@([drvr-.-2]),a1	| reloc factor
	movl	a1,d1
	lea	pc@([reloc+2-.-2]),a1
	movl	a1@+,a2		| pickup 1st relocation
	addl	d1,a2
.L16:
|	for(;;) {
|		i = *a2;
|		*a2 = 0;
|		*(u_long *)a2 += (u_long)d1;
|		if (i == 0377)
|			goto start;
|		if (i == 0) {
|			a2 = *a1++;
|			a2 += d1;
|			continue;
|		}
|		a2 += (i << 1);
|	}
	movb	a2@,d7
	andl	#255,d7
	clrb	a2@
	addl	d1,a2@
	cmpl	#255,d7
	beqs	.L18
	tstl	d7
	bnes	.L19
	movl	a1@+,a2
	addl	d1,a2
	bras	.L16
.L19:
	roll	#1,d7
	addl	d7,a2
	bras	.L16
|
| if shift button is pressed on entry, beep and hang around for an NMI.
|
.L18:
	btst	#0,0x17b
	beqs	.L31		| if not pressed
	movw	#1,sp@-		| sysbeep, duration 1
	.word	/A9C8
	moveq	#1,d0
.L22:
	tstl	d0
	bnes	.L22		| hang, waiting for NMI
.L31:
	movl	a5,_savea5
 	movw	doff2,doffset	| above code is once-only
	moveml	sp@+,#0xffff
|
| driver entry points
|
dopen:
	movl	#drvrOpen,d0
	bras	call
dclose:
	movl	#drvrClose,d0
	bras	call
dctl:
	movl	#drvrCtl,d0
	bras	call
dstatus:
	movl	#drvrStatus,d0
	bras	call
dprime:
	movl	#drvrPrime,d0
call:
	moveml	#0x3ffc,sp@-
	movl	a1,sp@-
	movl	a0,sp@-
	movl	d0,a0
	jsr	a0@
	addql	#8,sp
	moveml	sp@+,#0x3ffc
	cmpl	#0x40000000,d0
	bnes	done
	clrl	d0
	rts
jiodone = 0x8fc
done:
	movl	jiodone,sp@-
	rts
doff2:	.word	dopen-drvr
{~}{~}
echo x - desk.rc
cat > desk.rc << '{~}{~}'
desk.rsrc

Type ALRT
  ,256(32)
  60 81 180 431
  256
  5555

Type DITL
  ,256(32)
  3
   BtnItem Enabled
   90 10 110 80
OK

   BtnItem Enabled
   90 270 110 340
Cancel

   StatText Disabled
   10 60 70 350
Replace system resource ^0 type=^1 id=^2?

Type DRVR
   print|Print,30(48)

Type CODE
   desk,0
{~}{~}
echo x - Makefile
cat > Makefile << '{~}{~}'
.SUFFIXES: .rsrc .b .ln .s .c
BIN=/usr1/mac/bin/
INCLUDE=/usr1/mac/include

CFILES = desk.c print.c
SFILES = crtprint.s

.c.b:
	$(BIN)cc68 -I$(INCLUDE) -c $<

.c.s:
	$(BIN)cc68 -I$(INCLUDE) -S $<

.s.b:
	$(BIN)cc68 -c $<

.c.ln:
	$(BIN)lint -I$(INCLUDE) -lmac $< > $*.ln

print: print.b crtprint.b 
	$(BIN)ld68 -X -r -d -e drvr -T 0 crtprint.b print.b -lmac -lc -x -o print

desk: desk.b
	$(BIN)cc68 -m desk.b -o desk

desk.rsrc: print desk desk.rc
	$(BIN)rmaker desk.rc

all: desk.rsrc

put: desk.rsrc
	$(BIN)macput -o -r desk

lint: print.ln desk.ln

desk.shar: $(CFILES) $(SFILES) desk.rc Makefile
	csh shar desk.shar $(CFILES) $(SFILES) desk.rc Makefile

clean:
	rm -f *.b *.rsrc print desk

{~}{~}

-- 

<*> Fred Hirsch <*> AT&T Bell Laboratories <*> ihnp4!bentley!fjh <*>