home *** CD-ROM | disk | FTP | other *** search
/ Carousel / CAROUSEL.cdr / mactosh / code / c_smplet.sit < prev    next >
Text File  |  1988-06-20  |  69KB  |  2,331 lines

  1. 18-Jun-88 14:44:01-MDT,71786;000000000000
  2. Return-Path: <u-lchoqu%sunset@cs.utah.edu>
  3. Received: from cs.utah.edu by SIMTEL20.ARPA with TCP; Sat, 18 Jun 88 14:42:14 MDT
  4. Received: by cs.utah.edu (5.54/utah-2.0-cs)
  5.     id AA22611; Sat, 18 Jun 88 14:42:05 MDT
  6. Received: by sunset.utah.edu (5.54/utah-2.0-leaf)
  7.     id AA24770; Sat, 18 Jun 88 14:41:57 MDT
  8. Date: Sat, 18 Jun 88 14:41:57 MDT
  9. From: u-lchoqu%sunset@cs.utah.edu (Lee Choquette)
  10. Message-Id: <8806182041.AA24770@sunset.utah.edu>
  11. To: rthum@simtel20.arpa
  12. Subject: SimpleTools.c.shar
  13.  
  14. #! /bin/sh
  15. #
  16. # This is a shell archive.  Save this into a file, edit it
  17. # and delete all lines above this comment.  Then give this
  18. # file to sh by executing the command "sh file".  The files
  19. # will be extracted into the current directory owned by
  20. # you with default permissions.
  21. #
  22. # The files contained herein are:
  23. #
  24. #    3 STools.info
  25. #   12 SimpleDemo.c
  26. #   31 SimpleTools.c
  27. #   19 SimpleTools.doc
  28. #
  29. echo 'Extracting STools.info'
  30. if test -f STools.info; then echo 'shar: will not overwrite STools.info'; else
  31. sed 's/^X//' << '________This_Is_The_END________' > STools.info
  32. XFrom: erik@ucbssl.CC.Berkeley.EDU (Erik Kilk)
  33. X
  34. X!rSimpleTalk.text
  35. X
  36. XHere is an updated version of SimpleTools.  Included are the SimpleTools
  37. Xsources, a MacWrite document, and an example using some of the easy and
  38. Xadvanced features in the SimpleTools library.
  39. X
  40. XSimpleTools is a set of subroutines which greatly ease the use of the
  41. XMacintosh toolbox.  It is mainly intended to be used for your smaller
  42. Xapplications where you would rather not be too concerned with reading
  43. XInside Macintosh over again.  The subroutines are currently written in C
  44. Xand were done so using the Megamax compiler.  They are designed to be
  45. Xcompiled into an object file.  Your program will then link in this object
  46. Xfile at the same time it links in the toolbox interface.  When you receive
  47. Xthe SimpleTools source, you should compile it into SimpleTools.o.  You can
  48. Xthen compile the demo, SimpleDemo, and link it to SimpleTools.o.
  49. X
  50. XFor example, lets say you want the menu items named "Zoom" and "Widen"
  51. Xunder the menu "View".  You would like the procedure:
  52. X
  53. X    zoom()
  54. X    {
  55. X     zoomfactor++;
  56. X    }
  57. X
  58. Xto be executed when the user selects Zoom and:
  59. X
  60. X    widen()
  61. X    {
  62. X     zoomfactor--;
  63. X    }
  64. X
  65. Xto execute when Widen is selected.  You would both create the menus on the
  66. Xmenu bar AND inform SimpleTools what to do with the calls:
  67. X
  68. X    menu ("View", "Zoom", zoom);
  69. X    menu ("View", "Widen", widen);
  70. X
  71. XThen, your program would run by repeatedly calling SimpleEvents, like:
  72. X
  73. X    main()
  74. X    {
  75. X     setup();
  76. X     for (;;) SimpleEvents();
  77. X    }
  78. X
  79. XSeveral other features are included in SimpleTools:
  80. X
  81. X1.  Window creation with assignment of procedures to be executed on window
  82. Xactivation, deactivation, when the mouse is clicked in it, and when an
  83. Xupdate occurs.
  84. X
  85. X2.  Assignment of procedures to be "run" each time SimpleEvents() is
  86. Xcalled.  This can easily make it look like multi-subroutines are running
  87. Xconcurrently.
  88. X
  89. X3.  Generic prompt() and message() routines which pop up a small dialog box
  90. Xfor you.  For example:
  91. X
  92. X    prompt("What is your name?", answer)
  93. X
  94. Xis all yo have to do to get a dialog box up requesting the user's name.
  95. XThe answer goes into the string answer.
  96. X
  97. X4.  Automatic setup of the Apple, File, and Edit menu so even your simplest
  98. Xof programs will still have Desk Accessories.
  99. X
  100. X5.  Many, many, hidden options that you will never know about unless you
  101. Xcare to know about them.  (This was a major design goal of SimpleTools--
  102. Xhide options and use the most common default.)
  103. X
  104. XThis has just been a summary of the SimpleTools routines.  I'm sure you
  105. Xcould find them very useful.  Many users of SimpleTools have been very
  106. Xpleased with this idea and have saved many hours of studying and
  107. Xprogramming.  To those people, thanks for your letters, they are very
  108. Xhighly appreciated.
  109. X
  110. X                                    Erik
  111. X
  112. XP.S.  If you don't have access to the network library, feel free to send a
  113. Xself-addressed, stamped envelope and a disk (full of any goodies you have)
  114. Xto Erik Kilk, 1325 Nord Ave #155, Chico, CA 95926, and I'll copy my master
  115. Xdisk for you.
  116. ________This_Is_The_END________
  117. if test `wc -l < STools.info` -ne 84; then
  118.     echo 'shar: STools.info was damaged during transit'
  119.   echo '      (should have been 84 bytes)'
  120. fi
  121. fi        ; : end of overwriting check
  122. echo 'Extracting SimpleDemo.c'
  123. if test -f SimpleDemo.c; then echo 'shar: will not overwrite SimpleDemo.c'; else
  124. sed 's/^X//' << '________This_Is_The_END________' > SimpleDemo.c
  125. X
  126. X/*
  127. X    Title    : SimpleDemo.c
  128. X    Author    : Erik Kilk
  129. X    Date    : June 9, 1985
  130. X    Revised    : July 17, 1985
  131. X    
  132. X    Synopsis: A demonstration of the use of SimpleTools with 
  133. X        other toolbox calls.  This demonstrates a very 
  134. X        advanced use of SimpleTools.  I've always disliked
  135. X        being given simple examples.  So, this example 
  136. X        uses many, many optional features of SimpleTools.
  137. X        
  138. X    The SimpleTools routines are being freely distributed.
  139. X    You may use them, distribute your applications which use them,
  140. X    and copy them if you send $10 or more to:
  141. X    
  142. X            Erik Kilk
  143. X            325 San Leandro Way
  144. X            San Francisco,  CA  94127
  145. X            
  146. X    Link this demonstration program with SimpleTools.o.
  147. X        
  148. X*/
  149. X
  150. X#define TRUE -1            /* Common boolean constants */
  151. X#define FALSE 0
  152. X
  153. X/*******************************/
  154. X/*  INCLUDE FILES FOR TOOLBOX  */
  155. X/*******************************/
  156. X
  157. X#include <qd.h>
  158. X#include <event.h>
  159. X#include <mem.h>
  160. X#include <font.h>
  161. X#include <qdvars.h>
  162. X#include <misc.h>
  163. X#include <win.h>
  164. X#include <string.h>
  165. X#include <stdio.h>
  166. X
  167. X/***********************************************/
  168. X/*  DEFINITIONS FOR THE SIMPLETOOLS MENU CALL  */
  169. X/***********************************************/
  170. X
  171. X#define itemdisable 0L
  172. X#define itemenable 1L
  173. X#define itemcheck 2L
  174. X#define itemuncheck 3L
  175. X
  176. X/**************************************/
  177. X/*  GLOBAL VARIABLES  AND  FUNCTIONS  */
  178. X/**************************************/
  179. X
  180. Xint circspeed = 50;        /* rate of drawing new circles */
  181. Xint ourpensize = 1;        /* global pen size instead of windows */
  182. Xrect drag;            /* for moving our free mem manually */
  183. X
  184. Xextern windowptr windowpoint();    /* defined in SimpleTools */
  185. Xextern char applestring[];    /* defined in SimpleTools */
  186. Xextern int windmenu;        /* defined in SimpleTools */
  187. Xextern int dogoaway;        /* defined in SimpleTools */
  188. Xextern int wprocid;        /* defined in SimpleTools */
  189. X
  190. X/*********************/
  191. X/*   Odds and Ends   */
  192. X/*********************/
  193. X
  194. Xleave()             /* Attached to the Quit menu */
  195. X{ 
  196. X    exit(0); 
  197. X}        
  198. X
  199. Xnop()                 /* Attached as a null pointer */
  200. X{
  201. X}            
  202. X
  203. X/******************************/
  204. X/*   Clear the front window   */
  205. X/******************************/
  206. X
  207. Xourclear()            /* attatched to Clear during sketching */
  208. X{
  209. X  rect therect;            /* rectangle to clear */
  210. X  if ((long)frontwindow() != 0L) {    /* if there is a front window */
  211. X    setport (frontwindow());        /* set it for output */
  212. X    setrect ( &therect, 0, 0, 512, 400);/* make a rectangle */
  213. X    fillrect ( &therect, qdvars.qdwhite);    /* erase the rectangle in window */
  214. X  }
  215. X}
  216. X
  217. X/***********************/
  218. X/*  Sketch Window      */
  219. X/***********************/
  220. X
  221. Xsketactivate()            /* Attached to sketch's activate */
  222. X{                /* Disable the whole sketch menu */
  223. X  menu ("Sketch", "", itemenable);
  224. X  menu ("Edit", "Clear", ourclear);  /* put our clear routine into place */
  225. X}
  226. X    
  227. Xsketdeactivate()        /* Attached to sketch's deactivate */
  228. X{                /* Enable the whole sketch menu */
  229. X  menu ("Sketch", "", itemdisable);
  230. X  menu ("Edit", "Clear", nop);    /* take off our clear routine */
  231. X}
  232. X
  233. Xsketch(x,y)            /* follow mouse while it's down */
  234. Xint x,y;            /* we will get passed the mouse point */
  235. X{
  236. X  point xy, lastxy;        /* points of interest */
  237. X  windowptr ourport;
  238. X  
  239. X  getport (&ourport);
  240. X  pensize (ourpensize, ourpensize);
  241. X  moveto (x, y);        /* position pen at mouse down point */
  242. X  while ( stilldown() ) {    /* while the button is pressed */
  243. X    getmouse (&xy);        /* read the mouse position */
  244. X    if ( (xy.a.v != lastxy.a.v) || (xy.a.h != lastxy.a.h) ) {
  245. X      lineto (xy.a.h, xy.a.v);    /* if mouse moved, draw a line to it */
  246. X      lastxy.a.v = xy.a.v;    /* record position so we can detect */
  247. X      lastxy.a.h = xy.a.h;    /*   a move. */
  248. X    }                /* could runruns here to have circles */
  249. X    runruns(0L);
  250. X    setport (ourport);
  251. X  }
  252. X}
  253. X    
  254. Xsetpensize(size)        /* Attached to pen size menus */
  255. Xchar *size;            /* menu item name given to us */
  256. X{
  257. X  static char lastsize[5]={'1','\0'};    /* keep last setting */
  258. X  menu ("Sketch", lastsize, itemuncheck);    /* remove old check mark */
  259. X  menu ("Sketch", size, itemcheck);    /* install a new check mark */
  260. X  strcpy (lastsize, size);    /* save size for the next setpensize */
  261. X  ourpensize = atoi (size);        /* convert to a number */
  262. X}
  263. X
  264. X/**************************/
  265. X/*   The Circles Window   */
  266. X/**************************/
  267. X
  268. Xint newabs(x)            /* an absolute value funtion */
  269. Xint x;
  270. X{
  271. X  if (x < 0)
  272. X    x = -x;
  273. X  return (x);
  274. X}
  275. X
  276. Xcircles()            /* draw a random sized circle */
  277. X{
  278. X  static windowptr wind = (windowptr) 0; /* keep "circle" windowptr */
  279. X  static int speed = 1;        /* current count between new circles */
  280. X  register int cx, cy;        /* center of the circle */
  281. X  int r, b, rd;            /* right and bottom edges */
  282. X  register pattern *color;    /* color for the circle */
  283. X  rect therect;            /* rectangle to draw circle in */
  284. X  if ( --speed == 0) {        /* count, and if it reaches zero... */
  285. X    speed = circspeed;        /* reset the count */
  286. X    if ((long)wind == 0L)     /* get window pointer if we need */
  287. X      wind = windowpoint ("Circles");  /* save window for next time */
  288. X    setport (wind);        /* set output to the circle window */
  289. X    r = wind->portrect.a.right;    /* get current size of window */
  290. X    b = wind->portrect.a.bottom;
  291. X    cx = newabs(random()) % (r-30) + 1;    /* pick a random location */
  292. X    cy = newabs(random()) % (b-30) + 1;
  293. X    rd = newabs(random()) % 25 + 5;        /* and size */
  294. X    setrect ( &therect, cx, cy, cx+rd, cy+rd);    /* make a rectangle */
  295. X    switch ( newabs(random()) % 4) {        /* pick a color */
  296. X      case 0: color = (pattern *)(&dkgray); break;
  297. X      case 1: color = (pattern *)(<gray); break;
  298. X      case 2: color = (pattern *)(&gray); break;
  299. X      case 3: color = (pattern *)(&black); break;
  300. X    }
  301. X    filloval ( &therect, color);    /* make the circle */
  302. X  }
  303. X}
  304. X
  305. Xsetspeed(name)                /* attached to circle's menu */
  306. Xchar *name;
  307. X{
  308. X  menu ("Circles","Slow/S", itemuncheck);    /* another way to uncheck last */
  309. X  menu ("Circles","Medium/M", itemuncheck); /* just uncheck everything */
  310. X  menu ("Circles","Fast/F", itemuncheck);
  311. X  menu ("Circles", name, itemcheck);    /* then check the current  */
  312. X  if (strcmp("Slow/S", name) ==0) circspeed = 100;  /* set the reset count */
  313. X  else if (strcmp("Medium/M", name) ==0) circspeed = 50;
  314. X  else if (strcmp("Fast/F", name) ==0) circspeed = 1;
  315. X}
  316. X
  317. X/***********************************************/
  318. X/*   Generate a new sketch window by command   */
  319. X/***********************************************/
  320. X
  321. Xnwindow()            /* command to attatch to new window menu */
  322. X{
  323. X  static topplace = 100;    /* remember where to put next window */
  324. X  char newname[255];        /* string storage for window's name */
  325. X  strcpy (newname, "New Window");    /* default window name */
  326. Xretry:                /* prompt for the name from user */
  327. X  if (prompt ("Give me a unique name for the new window:", newname)) {
  328. X    if ( (long)windowpoint(newname) != 0L ) {
  329. X      if (message ("Sorry, a window by that name already exists.")) 
  330. X        goto retry;        /* if exists, ask for another name */
  331. X    } else {
  332. X      if ( strlen(newname) > 0)  {  /* if ok, make the new window */
  333. X        /* then it is new */
  334. X        window (newname, 20,topplace, 200,topplace+60, 
  335. X      sketactivate, sketdeactivate, nop, sketch);
  336. X        topplace += 5;        /* adjust top for next new window */
  337. X        if (topplace > 300) topplace = 100;  /* reset top if too low */
  338. X      }
  339. X    }
  340. X  }
  341. X}
  342. X
  343. X/**********************/
  344. X/*  About SimpleDemo  */
  345. X/**********************/
  346. X
  347. Xusageinfo()        /* messages for Usage Info menu choice */
  348. X{
  349. X  char mess[255];    /* string to form a message */
  350. X  strcpy (mess,"You may use, distribute your programs which use, ");
  351. X  strcat (mess,"and copy SimpleTools if you send ");
  352. X  strcat (mess,"$10 or more to ...");
  353. X  if (message (mess)) {  /* if OK pressed for first message */
  354. X    strcpy (mess, "Erik Kilk\r325 San Leandro Way\r");
  355. X    strcat (mess, "San Francisco, CA  94127");
  356. X    if (message (mess))  /* if OK pressed for 2nd message */
  357. X      message ("Thank you for your support.");  /* show final message */
  358. X  }
  359. X}
  360. X
  361. Xtellabout()        /* for the About SimpleDemo menu choice */
  362. X{
  363. X  char mess[255];    /* string to form a message */
  364. X  strcpy (mess,"SimpleDemo -- Copyright 1985 Erik Kilk\r");
  365. X  strcat (mess,"A demonstration of the use of SimpleTools");
  366. X  strcat (mess," as a Macintosh toolbox aid.");
  367. X  if (message (mess))    /* display the string in a dialog */
  368. X    usageinfo();
  369. X}
  370. X  
  371. X/**************************/
  372. X/* The free memory window */
  373. X/**************************/
  374. X
  375. Xwritemem(forsure)            /* write the freemem value */
  376. Xint forsure;                /* true if force write */
  377. X{                    /* false if only on change */
  378. X  static long lastmem;
  379. X  long mem;
  380. X  int foo;
  381. X  char thestring[10], outstr[10];
  382. X  rect erasearea;
  383. X  mem = freemem();            /* get new free memory */
  384. X  foo = mem != lastmem;            /* compare it to last reading */
  385. X  if ( forsure | foo ) {        /* if forsure or different */
  386. X    withwindow ("FreeMem");        /* set window for output */
  387. X    setrect (&erasearea, 0, 0, 100, 20);
  388. X    eraserect (&erasearea);        /* erase old value */
  389. X    moveto (0, 12);            /* write new value */
  390. X    numtostring (mem, thestring);
  391. X    strcpy (outstr, " Free ");
  392. X    strcat (outstr, thestring);
  393. X    drawstring (outstr);
  394. X    lastmem = mem;            /* record this for next time */
  395. X  }
  396. X}
  397. X
  398. Xshowmem(windp)                /* write freemem on an update */
  399. Xwindowptr windp;
  400. X{
  401. X  endupdate (windp);            /* allow use of entire window */
  402. X  writemem(TRUE);            /* clear and write new value */
  403. X  beginupdate (windp);
  404. X}
  405. X
  406. Xnewmemvalue()                /* write freemem occasionally */
  407. X{
  408. X  writemem(FALSE);            /* write only if value changed */
  409. X}
  410. X
  411. X/* This is a special, non-standard, method of moving a window.  Our
  412. X   free memory window does not have a title bar.  So, I have decided
  413. X   to allow it to be moved if the mouse is clicked in its content
  414. X   region.  This routine is attached to the free memory in content
  415. X   procedure with SimpleTools.  SimpleTools convenienly gives us
  416. X   various parameters, here we need the window pointer and the event
  417. X   record.  The event record has the coordinates of the mouse in
  418. X   globals */
  419. X   
  420. Xmovemem(x,y,windp,event)    /* free mem's incontent procedure */
  421. Xint x,y;            /* SimpleTools gives us these for */
  422. Xwindowptr windp;        /* an in-content procedure */
  423. Xeventrecord *event;
  424. X{
  425. X  dragwindow (windp, &(event->where), &drag);
  426. X}
  427. X
  428. X/**********************/
  429. X/*   Initialization   */
  430. X/**********************/
  431. X
  432. Xsetup()        /* to be called with Start Demo menu choice */
  433. X{
  434. X  int temp;
  435. X  setrect (&drag, 4, 24, 508, 338);  /* drag area for free mem window */
  436. X  windmenu = FALSE;    /* modify default values, optional */
  437. X  dogoaway = FALSE;    /* optional change */
  438. X  window("Circles", 20, 55, 245, 315,nop, nop, nop, nop); /* circles */
  439. X  temp = wprocid;    /* save value for an optional change */
  440. X  wprocid = 3;         /* optional change to set to altDBoxProc */
  441. X  window ("FreeMem", 407, 322, 497, 337, nop, nop, showmem, movemem);
  442. X  wprocid = temp;    /* return to defaults */
  443. X  windmenu = TRUE;    
  444. X  dogoaway = TRUE;
  445. X  window ("Sketch", 265, 55, 490, 315,sketactivate,sketdeactivate, 
  446. X      nop, sketch);    /* display the sketch pad window */
  447. X  menu ( applestring, "About SimpleDemo", tellabout);
  448. X  menu ( applestring, "About SimpleDemo", itemenable);
  449. X  menu ( "File", "New", nwindow);        /* setup File menu */
  450. X  menu ( "File", "New", itemenable);
  451. X  menu ( "File", "Quit", leave);    
  452. X  menu ("Circles", "Speed", itemdisable);    /* install circles menu */
  453. X  menu ("Circles", "Slow/S", setspeed);        /* optional key equivs */
  454. X  menu ("Circles", "Medium/M", setspeed);
  455. X  menu ("Circles", "Fast/F", setspeed);
  456. X  menu ("Circles", "Medium/M", itemcheck);
  457. X  menu ("Sketch", "Pen Size", itemdisable);  /* install sketches menu */
  458. X  menu ("Sketch", "", itemdisable);
  459. X  menu ("Sketch", "1", setpensize);
  460. X  menu ("Sketch", "1", itemcheck);
  461. X  menu ("Sketch", "2", setpensize);
  462. X  menu ("Sketch", "3", setpensize);
  463. X  menu ("Sketch", "4", setpensize);
  464. X  menu ("Sketch", "5", setpensize);
  465. X  menu ("Sketch", "6", setpensize);
  466. X  run (circles);        /* keep drawing circles */
  467. X  run (newmemvalue);        /* check if mem changed occasionally */
  468. X}
  469. X
  470. Xmain()
  471. X{
  472. X  simpletools("About SimpleDemo");    /* setup Apple and Edit menus */
  473. X  setup();                /* setup our program */
  474. X  for (;;) simpleevents();        /* process events */
  475. X}
  476. ________This_Is_The_END________
  477. if test `wc -l < SimpleDemo.c` -ne 351; then
  478.     echo 'shar: SimpleDemo.c was damaged during transit'
  479.   echo '      (should have been 351 bytes)'
  480. fi
  481. fi        ; : end of overwriting check
  482. echo 'Extracting SimpleTools.c'
  483. if test -f SimpleTools.c; then echo 'shar: will not overwrite SimpleTools.c'; else
  484. sed 's/^X//' << '________This_Is_The_END________' > SimpleTools.c
  485. X
  486. X/*
  487. X    Title    : SimpleTools.c
  488. X    Author    : Erik Kilk  Copyright 1985
  489. X    Date    : June 7, 1985
  490. X    
  491. X    Version    : 1.2
  492. X    Revisions: 
  493. X    09/05/85 EK Removed fix needed for a old compiler bug
  494. X    07/13/85 EK Fixed menu unhilighting with D.A.'s menus.
  495. X    07/16/85 EK Resettable default for new window type and has goaway.
  496. X                Included menu command key usage.
  497. X     07/17/85 EK Removed menu changes to avoid flicker. 
  498. X             Added return codes to most functions.
  499. X            Fixed in-content call from changing event record.
  500. X    
  501. X    Synopsis: A collection of subroutines to simplify programming
  502. X        the Macintosh in C.  These are for those little programs
  503. X        you are tempted not to write because of all the hassles
  504. X        you have to go through writing programs for the Macintosh
  505. X        environment.
  506. X        
  507. X    Copyright:  These routines are copyrighted by Erik Kilk.  You
  508. X        may use them for your programming, as examples for your
  509. X        own programming, in your programs, in programs you
  510. X        distribute, copy them, and give copies to others who will
  511. X        abide by these rules if you send $10 or more to:
  512. X                Erik Kilk
  513. X                325 San Leandro Way
  514. X                San Francisco, CA  94127
  515. X        You use this software "as is".  The author make no
  516. X        promises and is not responsible nor liable for anything 
  517. X        due to your use of these subroutines. 
  518. X        
  519. X        Thank you for your support.
  520. X                
  521. X                
  522. X    Summary of User Routines:
  523. X    
  524. X    simpletools ("About SimpleTools");        Initialize 
  525. X    simpleevents ();                        Process next event
  526. X    menu ("Search", "Find", findroutine);    Add a menu
  527. X    window ("Sketch", 50,50,200,200, 
  528. X      activate,deactivate,update,content);    Add a window
  529. X    withwindow ("Sketch");                    Set output to window
  530. X    run (routine);                            Periodically call a routine
  531. X    stop (routine);                            Stop periodic call
  532. X    message ("Welcome to SimpleTools");        Display dialog message
  533. X    prompt ("What is your name?", answer);    Ask a question
  534. X        
  535. X    simpletools("Name");
  536. X        Call this once at the very beginning of your program. Pass
  537. X    it the name of your program if you want an "About Name" menu
  538. X    entry, otherwise pass it just "" as the name. It initializes
  539. X     the data structures used by SimpleTools.  It also does all of
  540. X    the toolbox initializing and
  541. X    installs the Apple, File, and Edit menus.  Only base pointers
  542. X    to linked structures and a few flags and scratch variables are
  543. X    set.  All other data is dynamically allocated with relocatable
  544. X    blocks through the Macintosh memory manager for each new menu
  545. X    and window created with these SimpleTools routines.
  546. X    
  547. X    simpleevents();
  548. X        Repeatedly call this routine as fast as you can.  Often this
  549. X    routine is in a for(;;) loop in the main procedure.  This routine
  550. X    handles menu selection, desk accessory startups, window moves,
  551. X    window resizes, close-box clicks, all window events, and the
  552. X    periodic calling of routines.  It will only handle menus, windows,
  553. X    and periodic routines installed with simpletools(), menu(), 
  554. X    window(), and run().
  555. X        This routine does the systemtask() and getnextevent() calls
  556. X    so you don't have to process them yourself.
  557. X        At times simpleevents() will be looking up assigned procedures
  558. X    to be executed. These procedures are passed some of information
  559. X    particular to its situation.  With Magamax C (and possibly others)
  560. X    the called procedure need not declare or use this passed data if
  561. X    it has no need for it.  The kind of data passed is described below.
  562. X        For key down and autokey events, the procedures set in 
  563. X    keydownproc and autokeyproc are passed the address to the event 
  564. X    record. By default, keydownproc and autokeyproc are set to 
  565. X    a no op procedure.
  566. X    
  567. X    menu ("Settings", "Trace Execution", hideproc );
  568. X        Call this routine for each menu to install or modify.  The 
  569. X    first argument is the menu bar title, the second is the item name,
  570. X    and the third is either the procedure to be executed when that
  571. X    item is selected or a modifier ( 0L, itemdisable; 1L, itemenable;
  572. X    2L, itemcheck, 3L, itemuncheck).  The first call with a particular
  573. X    menu/item pair will install the menu/item with either a procedure
  574. X    or modifier (in which case it is assigned a no op procedure.)  
  575. X    Subseqent calls are used to change either the assigned procedure or
  576. X    the current active modifiers.  Calling it with a null item name
  577. X    will disable or enable the entire menu if the menu already exists
  578. X    and the third parameter is either a 0L or 1L as listed above.
  579. X        Assigned procedures will be called with a (char *) pointing to
  580. X    the item name chosen.
  581. X    
  582. X    menuhandle mhand ("Settings");
  583. X        This function returns the handle to a given menu bar selection
  584. X    so that you can call the Menu manager routines yourself.
  585. X    
  586. X    window ("Trace Output", 256, 50, 500, 300, activateproc, 
  587. X          deactivateproc, updateproc, incontentproc);
  588. X        Call this routine for each window to install or modify.  The
  589. X    first argument is the window's name.  Then the (x,y) of the top
  590. X    left corner and the (x,y) of the bottom right corner.  These
  591. X    coordinates are only used for installing a window and will be
  592. X    ignored for subsequent calls.  Then comes four procedure names.
  593. X    Activateproc is called when the window becomes the active window.
  594. X    Deactivate when another window is activated.  Updateproc when 
  595. X    windows have moved and the window needs redrawn.  And incontentproc
  596. X    when the mouse is clicked inside the window.  
  597. X         New windows are given a menu selection of their name under
  598. X    a menu bar title of "Windows."  Menu() is used to install these.
  599. X    The procedure called for each window name is a procedure to
  600. X    bring back the window if it was closed by clicking its closebox or
  601. X    activate it (in case it is hidden and can't be clicked on.  
  602. X    When the close-box of a window is clicked, the window is just
  603. X    hidden, it isn't really closed.
  604. X         The assigned "in content" procedure will be called with two
  605. X    (int)s.  The x and y of the mouse position in that window's
  606. X    local coordinates.  Each assigned window procedure is also called
  607. X    with a (windowptr) to the target window and an address to
  608. X    the event record which just occured.  Before each is called,
  609. X    the current port is set to the target window.
  610. X    
  611. X    withwindow ("Trace Output");
  612. X         Call this routine to set the current output port to the
  613. X    asked for window.  Remember that proper scrolling of text in the
  614. X    window is only taken care of for the active window though output
  615. X    can be to any window.
  616. X    
  617. X    windowptr windowpoint ("Trace Output");
  618. X        This function returns a pointer to the given window name in
  619. X    case you want to use one of the Window manager routines your
  620. X    self.  
  621. X    
  622. X    run (flashsquareproc);
  623. X        Call this routine to install a procedure to be periodically
  624. X    executed.  Up do 100 procedures may be installed at once.  These
  625. X    procedure are called just after each i/o event is read.  They are
  626. X    called with the address of the current unprocessed eventrecord.
  627. X    
  628. X    stop (flashsquaresproc);
  629. X        Call this to remove a procedure from the list of procedures
  630. X    running periodically as installed with run().  
  631. X        
  632. X    message ("Are you sure you want to quit?");
  633. X        Puts up a dialog with your message and an OK and Cancel
  634. X    button.  Returns true if OK is clicked, false if Cancel hit.
  635. X    Memory for the dialog is allocated when it is put up and
  636. X    returned to the heap when a button is clicked.
  637. X    
  638. X    prompt ("What is your name?", answer);
  639. X        Where answer is a string set to a default value.  Puts up 
  640. X    a dialog with your question, an editable answer field with you
  641. X    default answer, the OK and Cancel buttons.  Returns true when
  642. X    OK or RETURN is entered, false if Cancel is clicked.
  643. X*/
  644. X
  645. Xoverlay "simpletools"        /* remove or change this if needed */
  646. X
  647. X#include <mem.h>        /* include type defs and constants */
  648. X#include <qd.h>            /* for the Macintosh tool box */
  649. X#include <qdvars.h>
  650. X#include <misc.h>
  651. X#include <event.h>
  652. X#include <res.h>
  653. X#include <win.h>
  654. X#include <te.h>
  655. X#include <dialog.h>
  656. X#include <menu.h>
  657. X#include <string.h>
  658. X#include <stdio.h>
  659. X
  660. X#define TRUE (-1)        /* local definitions */
  661. X#define FALSE 0
  662. X#define itemdisable 0        /* constants for menu modifiers */
  663. X#define itemenable 1
  664. X#define itemcheck 2
  665. X#define itemuncheck 3
  666. X#define maxsruns 50        /* procedure table size */
  667. X#define MESSN 30        /* array size for message dialog items */
  668. X#define QUESN 40        /* array size for prompt dialog items */
  669. X
  670. Xtypedef struct {        /* structure for an item */
  671. X    char itemname[40];    /* to allow reference by name */
  672. X    int itemno;        /* item number within menu */
  673. X    int menuid;        /* menu id in case menu info is needed */
  674. X    menuhandle menuhand;    /* item's menu's handle */
  675. X    procptr menurun;    /* procedure to run */
  676. X    ptr next;        /* pointer to the next item */
  677. X} itemdatum;
  678. X
  679. Xtypedef struct {        /* structure for a menu */
  680. X    char menuname[20];    /* to allow reference by name */
  681. X    int menuid;        /* menu id used to create the menu */
  682. X    menuhandle menuhand;    /* menu handle used to reference menu */
  683. X    itemdatum **itemlist;    /* pointer to the list of items */
  684. X    ptr next;        /* pointer to the next menu */
  685. X} menudatum;
  686. X
  687. Xtypedef struct {        /* structure for a window */
  688. X    char windname[80];    /* the window's name and reference */
  689. X    windowptr wptr;        /* the window's pointer reference */
  690. X    procptr wact;        /* the activate procedure */
  691. X    procptr wdeact;        /* the deactivate procedure */
  692. X    procptr wupdate;    /* the update procedure */
  693. X    procptr wcontent;    /* the content procedure */
  694. X    ptr next;        /* pointer to the next window */
  695. X} winddatum;
  696. X
  697. Xmenudatum **simplemenus;    /* handle to menu data */
  698. Xchar accname[80];        /* desk accessory name to open */
  699. Xrect dragrect, sizerect;    /* limits for moving windows */
  700. Xint wprocid = documentprod;    /* window procedure id */
  701. Xint dogoaway = TRUE;        /* if window has go away box */
  702. Xwinddatum **simplewinds;    /* handle to window data */
  703. Xint firstwind;            /* true if no windows have been made */
  704. Xprocptr keydownproc,
  705. X  autokeyproc;             /* routines for key down events */
  706. Xprocptr simpleruns[maxsruns];    /* list of procedures to run */
  707. Xchar applestring[2] 
  708. X  = {'\024', '\0'};         /* name of apple menu */
  709. Xwindowptr debugw;        /* a window pointer for debugging */
  710. Xint windmenu = TRUE;        /* whether or not a window menu is made */
  711. X
  712. X/******************************************************************/
  713. X/* Dialog lists.  These were calculated by using the new resource */
  714. X/* editor to make a template for a dialog and then using fedit to */
  715. X/* list the hex listing of the item list for the dialog.      */
  716. X/******************************************************************/
  717. X
  718. Xint messd[MESSN] = {2,0,0,0x38,0xf1,0x4c,0x12d,0x402,0x4f4b,0,0,5,5,
  719. X        0x36,0x12d,0x800,0,0,0x38,0xac,0x4c,0xe8,0x406,
  720. X        0x4361,0x6e63,0x656c};
  721. Xint quesd[QUESN] = {3,0,0,0x21,0xf0,0x35,0x12c,0x402,0x4f4b,0,0,8,8,
  722. X        0x28,0xe8,0x800,0,0,0x2b,8,0x4b,0xe8,0x1000,0,0,
  723. X        8,0xf0,0x1c,0x12c,0x406,0x4361,0x6e63,0x656c};
  724. X
  725. Xstnop()                /* a no op procedure for defaults */
  726. X{
  727. X}
  728. X
  729. X/* Given a menu name, find our data structure for it.  Return a handle
  730. X   to this structure.
  731. X*/
  732. X
  733. Xmenudatum **getourmenuhandle (name)
  734. Xchar *name;            /* name of menu bar menu */
  735. X{
  736. X    menudatum **here;    /* a handle to our menu structure */
  737. X    here = simplemenus;
  738. X
  739. X    /* find the menu name or the end of out menu list */
  740. X    while ( (strcmp(name,(**here).menuname) != 0) & 
  741. X        ((**here).next != (ptr)0L) )   
  742. X        here = (menudatum **)(**here).next;
  743. X        
  744. X    /* see if we found it or just the end of the list */
  745. X    if (strcmp(name,(**here).menuname) == 0)
  746. X        return (here);
  747. X    else
  748. X        return ((menudatum **)0L);  /* return 0 if not found */
  749. X}
  750. X
  751. X/* Given a menu name, return the real menu handle as used by most
  752. X   of the Macintosh toolbox menu manager routines.
  753. X*/
  754. X
  755. Xmenuhandle mhand (name)            /* find menuhandle */
  756. Xchar *name;                /* given name of menu */
  757. X{
  758. X  menudatum **menu;            /* a handle to our data */
  759. X  menu = getourmenuhandle(name);
  760. X  if ( (long) menu != 0L )
  761. X    return ( (**menu).menuhand);    /* return menu handle */
  762. X  else
  763. X    return ( (menuhandle) 0 );        /* return 0 if not found */
  764. X}
  765. X
  766. X/* This takes a handle to our personal item record and either a 
  767. X   procedure name or a modifier code.  If it got a procedure name,
  768. X   it sets it to the item's procedure to run when the item is chosen.
  769. X   If it got a modifier code, it changes the state of the menu's item
  770. X   to checked, unchecked, enabled, or disabled.  It especially keeps 
  771. X   track of the standard Edit menu items so we can restore them after
  772. X   a desk accessory is finished.
  773. X*/
  774. X
  775. Xsetitem ( items, routine)    /* set a menu item's routine or display */
  776. Xitemdatum **items;        /* if items is neg, then whole menu */
  777. Xprocptr routine;
  778. X{
  779. X    int inumber;
  780. X    menuhandle mhand;
  781. X    
  782. X    /* check to see if a procedure pointer was given to us */
  783. X    if ( (((long)items)>0L) && (routine > (procptr)0x1000L)) {  
  784. X            /* a good procedure value */
  785. X        (**items).menurun = routine;
  786. X        return;
  787. X    }
  788. X    
  789. X    /* Calculate which item number we are going to modify */
  790. X    if ( (long)items < 0L) {    /* the whole menu */
  791. X      mhand = (menuhandle) (0L - (long)items);
  792. X      inumber = 0;
  793. X    }
  794. X    else {                /* just one item */
  795. X      mhand = (**items).menuhand;
  796. X      inumber = (**items).itemno;
  797. X    }
  798. X    
  799. X    /* If a NULL procedure pointer, then set to a no_op routine */
  800. X    if ( (inumber > 0) && ((**items).menurun == (procptr)0L) )
  801. X      (**items).menurun = stnop;
  802. X      
  803. X    /* Now change the state of a menu item */
  804. X    switch ((int)routine) {
  805. X        case itemdisable: 
  806. X            disableitem(mhand,inumber); break;
  807. X        case itemenable:
  808. X            enableitem(mhand, inumber); break;
  809. X        case itemcheck:
  810. X            checkitem(mhand, inumber, TRUE); break;
  811. X        case itemuncheck:
  812. X            checkitem(mhand, inumber, FALSE); break;
  813. X    }
  814. X    if (inumber == 0) drawmenubar();  /* if main menu was changed */
  815. X    
  816. X}
  817. X        
  818. X/* This routine is described above.  It takes care of our menu data
  819. X   structure by adding or modifying menu entries.  
  820. X*/
  821. X
  822. Xmenu (name, item, routine)        /* install or change a menu */
  823. Xchar *name;                /* the menu name */
  824. Xchar *item;                /* the item name */
  825. Xchar * routine;                /* a procedure or modifier */
  826. X{
  827. X    menudatum **here;        /* a roving handle to our data */
  828. X    menudatum **ourmhandle;        /* another handle to our data */
  829. X    itemdatum **items;        /* a handle to the item */
  830. X    menuhandle mhandle;        /* a handle to the real menu */
  831. X    int lastid, lastitem;
  832. X    
  833. X    /* get the handle to menu named 'name' */
  834. X    if ((ourmhandle = getourmenuhandle (name)) == 0L) {
  835. X    
  836. X        /* make a new menu entry by finding the end of the list */
  837. X        here = simplemenus;
  838. X        while ((**here).next != 0L)
  839. X            here = (menudatum **)(**here).next;
  840. X            
  841. X        /* make a structure for our new entry */
  842. X        lastid = (**here).menuid;
  843. X        (**here).next = (ptr)newhandle ( (long)sizeof(menudatum));
  844. X        here = (menudatum **)(**here).next;
  845. X        strcpy ( (**here).menuname, name);
  846. X        (**here).menuid = ++lastid;
  847. X        (**here).next = (ptr) 0L;
  848. X        
  849. X        /* make a new item structure */
  850. X        (**here).itemlist = (itemdatum **)newhandle ( 
  851. X            (long)sizeof(itemdatum));
  852. X            
  853. X        /* make a new menu entry for the Macintosh */
  854. X        (**here).menuhand = newmenu (lastid, name);
  855. X        mhandle = (**here).menuhand;
  856. X        items = (**here).itemlist;
  857. X        strcpy ((**items).itemname, item);
  858. X        (**items).itemno = 1;
  859. X        (**items).menuid = lastid;
  860. X        (**items).menuhand = (**here).menuhand;
  861. X        (**items).menurun = (procptr) 0L;
  862. X        (**items).next = 0L;
  863. X        
  864. X        /* install and display the menu */
  865. X        appendmenu ((**here).menuhand, item);
  866. X        insertmenu ((**here).menuhand,0);
  867. X        setitem (items, routine);
  868. X        drawmenubar();
  869. X        return(TRUE);
  870. X    }
  871. X    else {
  872. X        if (strlen(item) == 0) {
  873. X          /* then adjust main menu */
  874. X          setitem( 0L - (long) ((**ourmhandle).menuhand), routine);
  875. X          return(FALSE);
  876. X        }
  877. X        /* see if item is in list */
  878. X        items = (**ourmhandle).itemlist;
  879. X        while ( (strcmp(item,(**items).itemname) != 0) &
  880. X            ((**items).next != (ptr)0L)) {
  881. X            items = (itemdatum **)(**items).next;
  882. X        }
  883. X        if (strcmp(item,(**items).itemname) ==0) {
  884. X            setitem( items, routine);
  885. X            return(FALSE);
  886. X        }
  887. X        else {
  888. X            /* make new item entry */
  889. X            lastitem = (**items).itemno;
  890. X            (**items).next =(ptr)newhandle(
  891. X                (long)sizeof(itemdatum));
  892. X            items = (itemdatum **)(**items).next;
  893. X            strcpy ((**items).itemname, item);
  894. X            (**items).itemno = ++lastitem;
  895. X            (**items).menuid = (**ourmhandle).menuid;
  896. X            (**items).menuhand = (**ourmhandle).menuhand;
  897. X            (**items).menurun = (procptr) 0L;
  898. X            (**items).next = 0L;
  899. X            
  900. X            /* and install the item in the menu bar */
  901. X            appendmenu ((**ourmhandle).menuhand,item);
  902. X            setitem (items, routine);
  903. X            return(TRUE);
  904. X        }
  905. X    }
  906. X}
  907. X    
  908. X/* This routine is called by the simpletools() initial routine.  It gets
  909. X   the pointer list of menus started, loads the desk accessories into
  910. X   the Apple menu, and loads up some standard menu entries.  The reason
  911. X   menu File has a New entry, and none others, is because as this code
  912. X   currently stands, a menu must have at least one item.  And since we
  913. X   want File before Edit, I had to make an entry.  The most commonly used
  914. X   item under File is Quit.  But we like quit to be at the end of the list.
  915. X   So, since New is usually always first when it is used, that the one
  916. X   chosen to start File.  
  917. X*/
  918. X
  919. Xinitsmenus(about)            /* init simpletools' menus */
  920. Xchar *about;
  921. X{
  922. X    itemdatum **items;
  923. X    simplemenus = (menudatum **) newhandle ( (long)sizeof(menudatum));
  924. X    strcpy ( (**simplemenus).menuname, applestring);
  925. X    (**simplemenus).menuid = 1;
  926. X    (**simplemenus).next = (ptr) 0L;
  927. X    (**simplemenus).menuhand = newmenu (1, (**simplemenus).menuname);
  928. X    (**simplemenus).itemlist = (itemdatum **)newhandle ( 
  929. X            (long)sizeof(itemdatum));
  930. X    items = (itemdatum **) (**simplemenus).itemlist;
  931. X    strcpy ((**items).itemname, about);
  932. X    (**items).itemno = 1;
  933. X    (**items).menuid = 1;
  934. X    (**items).menuhand = (**simplemenus).menuhand;
  935. X    (**items).menurun = stnop;
  936. X    (**items).next = 0L;
  937. X    appendmenu ((**simplemenus).menuhand, about);
  938. X    disableitem ((**simplemenus).menuhand, 1);
  939. X    menu (applestring, "-", (procptr) itemdisable);
  940. X    addresmenu ((**simplemenus).menuhand, "DRVR");
  941. X    insertmenu ((**simplemenus).menuhand, 0);
  942. X    menu ("File", "New", (procptr)itemdisable);
  943. X    menu ("Edit", "Undo", stnop);
  944. X    menu ("Edit", "-", (procptr)itemdisable);
  945. X    menu ("Edit", "Cut/X", stnop);
  946. X    menu ("Edit", "Copy/C", stnop);
  947. X    menu ("Edit", "Paste/V", stnop);
  948. X    menu ("Edit", "Clear", stnop);
  949. X}
  950. X
  951. X/* Given a window's name, return its window pointer so that other
  952. X   Macintosh Window Manager routines can be called for that window. */
  953. X   
  954. Xwindowptr windowpoint(name)        /* get window pointer */
  955. Xchar *name;                /* given window's name */
  956. X{
  957. X    winddatum **wind;            /* handle to our window data */
  958. X    if (firstwind) return ((windowptr)0); /* forget if there aren't any */
  959. X    wind = simplewinds;            /* look for the named window */
  960. X    while ( (strcmp ((**wind).windname, name) != 0) & 
  961. X      ((**wind).next != (ptr) 0)) {
  962. X        wind = (winddatum **) (**wind).next;
  963. X    }
  964. X    if ( strcmp ((**wind).windname, name) ==0) 
  965. X      return ( (**wind).wptr);        /* return pointer */
  966. X    else
  967. X      return ( (windowptr) 0);        /* or zero if it wasn't found */
  968. X}
  969. X
  970. X/* This routine is for the Windows menu item.  The Windows menu is
  971. X   set up when new windows are added.  It is used to bring forward and
  972. X   bring into view windows that may be under other windows or have been
  973. X   sent hiding by a click on their close box.
  974. X*/
  975. X
  976. Xshowawindow(name)            /* show the named window */
  977. Xchar *name;
  978. X{
  979. X  windowptr foo;
  980. X  foo = windowpoint(name);        /* get its window pointer */
  981. X  if ( (long)foo != 0L ) {
  982. X    showwindow(foo);            /* show it on the screen */
  983. X    setport (foo);            /* set further output to it */
  984. X    if ( foo != frontwindow())        /* if it isn't active, */
  985. X      selectwindow (foo);        /* activate it */
  986. X  }
  987. X}
  988. X
  989. X/* This routine installs a new window onto the screen.  It also gives
  990. X   that window an item in the Window menu.  This routine is also used
  991. X   to modify a window's associated routines.  The x,y positions are the
  992. X   top left and bottom right corners of where the window should originally
  993. X   be placed.  The coordinates are never used when this routine is called
  994. X   to update an already existing window.  But the spaces must be filled,
  995. X   so you can use zeros if you want.  Once the window has been displayed in
  996. X   its original position, the user has complete control of its size and
  997. X   placement with the mouse.
  998. X*/
  999. X
  1000. Xwindow(name, xtop, ytop, xbot, ybot, a, d, u, c)
  1001. Xchar *name;            /* window's name */
  1002. Xint xtop, ytop, xbot, ybot;    /* position if this is a new window */
  1003. Xprocptr a, d, u, c;        /* activate, deactivate, update, and */
  1004. X{                /*  content procedure names */
  1005. X  winddatum **wind;        /* handle to our window data */
  1006. X  winddatum **newentry;        /* another handle */
  1007. X  rect newplace;        /* a rectable for the window's placement */
  1008. X  if (a == (procptr) 0)
  1009. X    a = stnop;
  1010. X  if (d == (procptr) 0)
  1011. X    d = stnop;
  1012. X  if (u == (procptr) 0)
  1013. X    u = stnop;
  1014. X  if (c == (procptr) 0)
  1015. X    c = stnop;
  1016. X  if ( !firstwind ) {
  1017. X  
  1018. X    /* see if window is in the list */
  1019. X    wind = simplewinds;
  1020. X    while ( (strcmp ((**wind).windname, name) != 0) & 
  1021. X      ((**wind).next != (ptr) 0)) {
  1022. X        wind = (winddatum **) (**wind).next;
  1023. X    }
  1024. X    if ( strcmp ((**wind).windname, name) ==0) {
  1025. X    
  1026. X      /* reset the found window's parameters */
  1027. X      (**wind).wact = (procptr) a;
  1028. X      (**wind).wdeact = (procptr) d;
  1029. X      (**wind).wupdate = (procptr) u;
  1030. X      (**wind).wcontent = (procptr) c;
  1031. X      setport ( (**wind).wptr);        /* set output to window */
  1032. X      return(FALSE);
  1033. X    }
  1034. X  }
  1035. X  
  1036. X  /* make a new window entry */
  1037. X  newentry = (winddatum **)newhandle ( (long) sizeof (winddatum));
  1038. X  if (firstwind)
  1039. X    simplewinds = newentry;
  1040. X  else
  1041. X    (**wind).next = (ptr) newentry;
  1042. X  firstwind = 0;
  1043. X  strcpy ((**newentry).windname, name);
  1044. X  setrect (&newplace, xtop, ytop, xbot, ybot);
  1045. X  (**newentry).wptr = newwindow (0L, &newplace, name, -1, 
  1046. X    wprocid, -1L, dogoaway, newentry);
  1047. X  (**newentry).wact = (procptr) a;
  1048. X  (**newentry).wdeact = (procptr) d;
  1049. X  (**newentry).wupdate = (procptr) u;
  1050. X  (**newentry).wcontent = (procptr) c;
  1051. X  (**newentry).next = (ptr) 0;
  1052. X  if (windmenu)
  1053. X    menu ("Windows", name, showawindow);/* make a menu entry for it */ 
  1054. X  setport ( (**newentry).wptr);        /* set output to it */
  1055. X  return(TRUE);
  1056. X}
  1057. Xwinddatum **wdatum(windpt)        /* return handle to window data */
  1058. Xwindowptr windpt;
  1059. X{
  1060. X  winddatum **wind;
  1061. X  if (firstwind) return ((winddatum **) 0L);
  1062. X  wind = simplewinds;
  1063. X  while ( ((**wind).wptr != windpt) &    /* search for window's name */
  1064. X    ((**wind).next != (ptr) 0)) {
  1065. X      wind = (winddatum **) (**wind).next;
  1066. X  }
  1067. X  if ( (**wind).wptr == windpt)
  1068. X    return (wind);
  1069. X  else
  1070. X    return ((winddatum **) 0L);        /* zero if not found */
  1071. X}
  1072. X  
  1073. Xwithwindow(name)        /* set output to a window by name */
  1074. Xchar *name;            /* give it the window's name */
  1075. X{                /* returns boolean if window exists */
  1076. X    winddatum **wind;
  1077. X    wind = simplewinds;
  1078. X    if (firstwind) return(FALSE);    /* search for the window's name */
  1079. X    while ( (strcmp ((**wind).windname, name) != 0) & 
  1080. X      ((**wind).next != (ptr) 0)) {
  1081. X        wind = (winddatum **) (**wind).next;
  1082. X    }
  1083. X    if ( strcmp ((**wind).windname, name) ==0) {
  1084. X      setport ( (**wind).wptr);    /* set output to it */
  1085. X      return(TRUE);
  1086. X    }
  1087. X    else
  1088. X      return(FALSE);
  1089. X}
  1090. X  
  1091. X/* This run procedure is used to install routines to be occasionally
  1092. X   run.  The routine will be run once for each call to simpleevents()
  1093. X*/
  1094. X
  1095. Xrun(routine)            /* install a run procedure */
  1096. Xprocptr routine;        /* give it the procedure */
  1097. X{                /* return TRUE if successful */
  1098. X  int i;
  1099. X  i = 0;            /* add it to the end of the list */
  1100. X  while ( simpleruns[i] != (procptr) 0L) i++;
  1101. X  if (i < maxsruns) {
  1102. X    simpleruns[i] = routine;
  1103. X    simpleruns[i+1] = (procptr) 0L;
  1104. X    return(TRUE);
  1105. X  }
  1106. X  else
  1107. X    return(FALSE);
  1108. X}
  1109. X
  1110. X/* This routine removes a procedure from the list of run procedures */
  1111. Xstop(routine)            /* stop a procedure from running */
  1112. Xprocptr routine;        /* give the procedure */
  1113. X{                /* return TRUE if successful */
  1114. X  int i;
  1115. X  i = 0;
  1116. X  while ( (simpleruns[i] != routine) & (simpleruns[i] != (procptr) 0L))i++;
  1117. X  if (simpleruns[i] == (procptr) 0L)
  1118. X    return(FALSE);
  1119. X  else {
  1120. X    while ( simpleruns[i] != (procptr)0 ) {
  1121. X      simpleruns[i] = simpleruns[i+1];
  1122. X      i++;
  1123. X    }
  1124. X    return(TRUE);
  1125. X  }
  1126. X}
  1127. X
  1128. Xrunruns(event)            /* run all the installed run procedures */
  1129. Xeventrecord *event;        /* returns number of routines run */
  1130. X{
  1131. X  int i;
  1132. X  i = 0;
  1133. X  while ( simpleruns[i] != 0 )
  1134. X    (*(simpleruns[i++])) (event);
  1135. X  return(i);
  1136. X}
  1137. X
  1138. Xstdialog( question, answer, type)  /* a general dialog displayer */
  1139. Xchar *question;
  1140. Xchar *answer;
  1141. Xint  type;            /* type:  1=prompt, 2=message */
  1142. X{
  1143. X  dialogptr dialog;            /* dialog reference */
  1144. X  handle item, items;            /* handles for the dialog items */
  1145. X  rect screen, box;            /* rectangles for dialog/items */
  1146. X  int dtype, hit, canc;            /* item type and which was hit */
  1147. X  char tempanswer[255];            /* address where answer is */
  1148. X  
  1149. X  items = newhandle (512L);        /* get memory for items list */
  1150. X  hlock (items);            /* lock it down */
  1151. X  if (type == 1)
  1152. X    blockmove (quesd, *items, (long) QUESN * 2L); /* fill it with list */
  1153. X  else
  1154. X    blockmove (messd, *items, (long) MESSN * 2L);
  1155. X  setrect (&screen, 103, 50, 409, 137);        /* position window */
  1156. X  dialog = newdialog (0L, &screen, "", 0, dboxproc, -1L, 0, 0L, items);
  1157. X  getditem (dialog, 2, &dtype, &item, &box);    /* get item#2 handle */
  1158. X  setitext (item, question);            /* set item#2 text */
  1159. X  if (type == 1) {            /* set default answer */
  1160. X    getditem (dialog, 3, &dtype, &item, &box);
  1161. X    setitext (item, answer);
  1162. X    canc = 4;
  1163. X  }
  1164. X  else
  1165. X    canc = 3;
  1166. X  showwindow (dialog);                /* display the dialog */
  1167. X  do {
  1168. X    modaldialog (0L, &hit);            /* process the dialog */
  1169. X  } while ( (hit != 1) & (hit != canc) );
  1170. X  if (type == 1) {
  1171. X    getditem (dialog, 3, &dtype, &item, &box);    /* get item#3 handle */
  1172. X    hlock (item);
  1173. X    getitext (item, tempanswer);        /* get item#3 text */
  1174. X    strcpy (answer, tempanswer);        /* make a copy of it */
  1175. X    hunlock (item);
  1176. X  }
  1177. X  hunlock(items);                /* unlock items memory */
  1178. X  hpurge(items);                /* purge it */
  1179. X  disposdialog (dialog);            /* get rid of dialog */
  1180. X  return ( hit==1 );                /* return true if ok */
  1181. X}  
  1182. X  
  1183. Xprompt ( question, answer)        /* dialog box question/answer */
  1184. Xchar *question;
  1185. Xchar *answer;
  1186. X{
  1187. X  return (stdialog (question, answer, 1));
  1188. X}
  1189. X
  1190. Xmessage ( message )            /* dialog box message */
  1191. Xchar *message;
  1192. X{
  1193. X  return (stdialog (message, message, 2));
  1194. X}
  1195. X  
  1196. Xdocommand (which, thisevent)
  1197. Xlong which;
  1198. Xeventrecord *thisevent;
  1199. X{
  1200. X  int themenu, theitem;
  1201. X  long size;
  1202. X  char *cpoint;
  1203. X  grafptr tempport;
  1204. X  menudatum **here;
  1205. X  itemdatum **items;
  1206. X  char **myreshandle;
  1207. X  handle myhandle;
  1208. X  themenu = hiword (which);
  1209. X  theitem = loword (which);
  1210. X  if ((themenu == 1) && (theitem != 1)) {
  1211. X    /* start up a desk accessory */
  1212. X    getitem ((**simplemenus).menuhand,
  1213. X      theitem, accname);
  1214. X    setresload (FALSE);
  1215. X    myreshandle = getnamedresource ("DRVR", accname);
  1216. X    setresload (TRUE);
  1217. X    size = sizeresource (myreshandle);
  1218. X    myhandle = newhandle ( size + 3072L);
  1219. X    if (myhandle == 0L) 
  1220. X      message ("Not enough memory to do that.");
  1221. X    else {
  1222. X      disposhandle (myhandle);
  1223. X      getport (&tempport);
  1224. X      opendeskacc(accname);
  1225. X      setport (tempport);
  1226. X    }
  1227. X    return;
  1228. X  }
  1229. X  if (themenu ==3) {
  1230. X    /* do any system edits */
  1231. X    if (systemedit(theitem -1) != FALSE) 
  1232. X      return;
  1233. X  }
  1234. X  
  1235. X  /* now we run an installed menu procedure */
  1236. X  here = simplemenus;
  1237. X  
  1238. X  /* find out menu structure given the menu id */
  1239. X  while ( ((**here).menuid != themenu) &
  1240. X    ((**here).next != (ptr)0L) )
  1241. X  here = (menudatum **)(**here).next;
  1242. X  
  1243. X  if ((**here).menuid == themenu) {
  1244. X    /* now find the item structure */
  1245. X    items = (**here).itemlist;
  1246. X    while ( ((**items).itemno != theitem) &
  1247. X      ((**items).next != (ptr) 0L) )
  1248. X      items = (itemdatum **)(**items).next;
  1249. X  
  1250. X    /* prepare to give the item name to the procedure */
  1251. X    cpoint = (**items).itemname;
  1252. X    if ((**items).itemno == theitem) 
  1253. X      /* if we found the item, call its procedure */
  1254. X      (*((**items).menurun))(cpoint,thisevent) ;
  1255. X  }
  1256. X}
  1257. X      
  1258. Xdomousedown(thisevent)        /* respond to mouse down events */
  1259. Xeventrecord *thisevent;        /* passed the event record */
  1260. X{
  1261. X    windowptr whichwindow;
  1262. X    int code, x, y;
  1263. X    char *cpoint;
  1264. X    menudatum **omhand;
  1265. X    winddatum **thewdatum;
  1266. X    long newplace;
  1267. X    point temp;
  1268. X    code = findwindow(&(thisevent->where), &whichwindow);
  1269. X    switch (code) {
  1270. X        case inmenubar:
  1271. X          docommand(menuselect(&(thisevent->where)),thisevent);
  1272. X          break;
  1273. X        case insyswindow:
  1274. X            systemclick(thisevent, whichwindow); break;
  1275. X        case indrag:
  1276. X            dragwindow(whichwindow, &(thisevent->where),
  1277. X              &dragrect); break;
  1278. X        case ingrow:
  1279. X          newplace= growwindow(whichwindow, &(thisevent->where),
  1280. X            &sizerect);
  1281. X          sizewindow(whichwindow, loword(newplace), 
  1282. X            hiword(newplace), TRUE);
  1283. X          break;
  1284. X        case ingoaway:
  1285. X          if ( trackgoaway(whichwindow, &(thisevent->where))) {
  1286. X            hidewindow (whichwindow);
  1287. X          }
  1288. X          break;
  1289. X        case incontent:
  1290. X        
  1291. X          /* make the window active if it isn't yet */
  1292. X          if (whichwindow != frontwindow()) {
  1293. X            selectwindow(whichwindow);
  1294. X          }
  1295. X  
  1296. X          /* find our window data */
  1297. X          thewdatum = wdatum (whichwindow);
  1298. X          if ((long) thewdatum != 0L) {
  1299. X          
  1300. X            /* convert the point of click to the window's
  1301. X               own coordinates since this will be always
  1302. X               more useful than the global coordintates */
  1303. X            temp = thisevent->where;
  1304. X            setport (whichwindow);
  1305. X            globaltolocal (&temp);
  1306. X            x = temp.a.h;
  1307. X            y = temp.a.v;
  1308. X            
  1309. X            /* call the window's in content routine */
  1310. X            (*((**thewdatum).wcontent))(x, y, whichwindow,
  1311. X                thisevent);
  1312. X          }
  1313. X          break;
  1314. X    }
  1315. X}
  1316. X            
  1317. Xsimpletools(about)    /* to be called at the beginning of program */
  1318. Xchar *about;
  1319. X{
  1320. X    maxapplzone();        /* allow maximum heap expansion */
  1321. X    flushevents (everyevent,0);  /* ignore left over events */
  1322. X    initgraf (&theport);    /* initialize the screen */
  1323. X    initfonts();        
  1324. X    initwindows();
  1325. X    initmenus();
  1326. X    initcursor();        /* make the arrow cursor */
  1327. X    teinit();
  1328. X    initdialogs(0L);
  1329. X    setrect ( &sizerect, 20, 50, 250, 330);
  1330. X    /*
  1331. X    debugw = newwindow(0L,&sizerect,"Debug",-1,documentproc,-1L,-1L,0L);
  1332. X    */
  1333. X    simpleruns[0] = (procptr) 0;  /* empty the run list */
  1334. X    /* These are the bounds we are allowed to size a window or
  1335. X       move a window to.  
  1336. X    */
  1337. X    setrect ( &sizerect, 20, 20, 511, 341);
  1338. X    setrect ( &dragrect, 4, 24, 507, 337);
  1339. X    firstwind = 1;            /* empty window table */
  1340. X    keydownproc = stnop;        /* default key hit procedures */
  1341. X    autokeyproc = stnop;
  1342. X    initsmenus(about);        /* install the menus */
  1343. X}
  1344. X
  1345. Xsimpleevents()        /* to be called in the main loop */
  1346. X{
  1347. X    eventrecord newevent;
  1348. X    winddatum **thewdatum;
  1349. X    systemtask();        /* Do the system D.A. etc. stuff */
  1350. X    hilitemenu(0);
  1351. X    getnextevent(everyevent, &newevent);
  1352. X    runruns(&newevent);    /* Do our run procedures */
  1353. X    switch (newevent.what) {
  1354. X        case mousedown:
  1355. X          domousedown(&newevent); break;
  1356. X        case keydown: 
  1357. X          if ((newevent.modifiers & cmdkey) != 0)
  1358. X            docommand(menukey((char)(newevent.message & 0xffL)),
  1359. X              &newevent);
  1360. X          (*(keydownproc))(&newevent);
  1361. X          break;
  1362. X        case autokey: 
  1363. X          if ((newevent.modifiers & cmdkey) != 0)
  1364. X            docommand(menukey((char)(newevent.message & 0xffL)),
  1365. X                      &newevent);
  1366. X          (*(autokeyproc))(&newevent);
  1367. X          break;
  1368. X        case activateevt: 
  1369. X          thewdatum = wdatum(newevent.message);
  1370. X          if ((long)thewdatum != 0L) {
  1371. X            setport(newevent.message);
  1372. X            if ((newevent.modifiers & 1) == 1) {
  1373. X              (*((**thewdatum).wact))(newevent.message, 
  1374. X                &newevent);
  1375. X            }
  1376. X            else {
  1377. X              (*((**thewdatum).wdeact))(newevent.message,
  1378. X                &newevent);
  1379. X            }
  1380. X          }
  1381. X          break;
  1382. X        case updateevt:
  1383. X          thewdatum = wdatum(newevent.message);
  1384. X          if ((long)thewdatum != 0L) {
  1385. X            setport (newevent.message);
  1386. X            beginupdate (newevent.message);
  1387. X            (*((**thewdatum).wupdate))(newevent.message,
  1388. X              &newevent);
  1389. X            endupdate (newevent.message);
  1390. X          }
  1391. X        break;
  1392. X    }
  1393. X}
  1394. X
  1395. ________This_Is_The_END________
  1396. if test `wc -l < SimpleTools.c` -ne 911; then
  1397.     echo 'shar: SimpleTools.c was damaged during transit'
  1398.   echo '      (should have been 911 bytes)'
  1399. fi
  1400. fi        ; : end of overwriting check
  1401. echo 'Extracting SimpleTools.doc'
  1402. if test -f SimpleTools.doc; then echo 'shar: will not overwrite SimpleTools.doc'; else
  1403. sed 's/^X//' << '________This_Is_The_END________' > SimpleTools.doc
  1404. X
  1405. X
  1406. XSimpleTools
  1407. X
  1408. XCopyright (c) 1985 Erik Kilk
  1409. X
  1410. X
  1411. X
  1412. X
  1413. X
  1414. XWhat is SimpleTools?
  1415. X
  1416. XSimpleTools is a collection of subroutines (presently written for the C
  1417. Xlanguage) to aid the programmer in using the most common of the
  1418. XMacintosh user interfaces:  menus, windows, mouse control, and dialogs. 
  1419. XIts purpose is to allow the programmer to get on with programming
  1420. Xhis/her application without spending much effort on how to incorporate
  1421. Xthe standard Macintosh user interfaces into the application.  It was
  1422. Xdesigned mainly to allow you to program those simple little programs
  1423. Xwhich you are tempted not to write due to all the work needed to make a
  1424. Xprogram look like a Macintosh program.  It is not intended for use in large,
  1425. Xcomplicated programs which may need a larger variety of display
  1426. Xinterfaces.  
  1427. X
  1428. X
  1429. X
  1430. XDue to the slowness of a human user in selecting menus and manipulating
  1431. Xwindows, SimpleTools is not noticably slow.  It was not intended to be
  1432. Xefficient for the user, but rather easy for the programmer to use.  Aren't
  1433. Xyou tired of constantly looking up how to use so-and-so routine in Inside
  1434. XMacintosh?  Menus and windows are referenced by name, not by a number
  1435. Xor complex data structure.  One routine, simpleevents(), processes the next
  1436. XMacintosh event, including calling the appropriate routine when a menu or
  1437. Xwindow is selected.  Most of the other routines are used to "install" menus
  1438. Xand windows so that simpleevents() knows what to do.
  1439. X
  1440. X
  1441. X
  1442. XCopyright and Usage Info
  1443. X
  1444. XSimpleTools is supplied AS IS with absolutely no warrenties, promises, or
  1445. X
  1446. Xliability from or to the author.   You may use, copy, give others copies of,
  1447. Xand sell applications developed with SimpleTools after submitting  a $10
  1448. Xor more fee to:
  1449. X
  1450. X    Erik Kilk
  1451. X
  1452. X    325 San Leandro Way
  1453. X
  1454. X    San Francisco, CA  94127
  1455. X
  1456. X
  1457. X
  1458. XSummary of SimpleTools
  1459. X
  1460. XThe purpose of SimpleTools is to aid the use of the Macintosh user
  1461. Xinterface. The routines take care of most of the work needed to maintain
  1462. Xwindows and menus.  It is intended to be most effectively used in tandom
  1463. Xwith the Macintosh toolbox routines.
  1464. X
  1465. X
  1466. X
  1467. XSimpleTools works by maintaining several "lists of things to do" when
  1468. Xcertain events occure.  The programmer must supply the procedure to do
  1469. Xfor certain events.  To document this procedure, a step-by-step tutorial
  1470. Xtype discussion will be given.  Please note that NOT EVERYTHING useful to
  1471. Xknow about SimpleTools is contained here.  This is meant to get you
  1472. Xstarted.  Please take a look at the source code, SimpleTools.c, for more
  1473. Xadvanced usages.
  1474. X
  1475. X
  1476. X
  1477. XPlease report SimpleTools bugs to Erik Kilk, 325 San Leandro Way, San
  1478. XFrancisco, CA  94127. 
  1479. X
  1480. X
  1481. X
  1482. XThe Main SimpleTools' Routines
  1483. X
  1484. X    simpletools()    -- install the apple, file, and edit menus
  1485. X
  1486. X    menu()    -- install your own menu
  1487. X
  1488. X    window()    -- install your own window
  1489. X
  1490. X    withwindow()    -- send output to your window
  1491. X
  1492. X    run()    -- install a routine to run periodically
  1493. X
  1494. X    stop()    -- remove a routine from the "run" list
  1495. X
  1496. X    message()    -- display a message in a dialog box
  1497. X
  1498. X    prompt()    -- ask a question, get an answer in dialog
  1499. X
  1500. X    simpleevents()    -- handle all events
  1501. X
  1502. X
  1503. X
  1504. XReferences to all menus and windows are by a string containing the name
  1505. X
  1506. Xof the menu, item, or window.  There is no need to remember such things
  1507. X
  1508. Xas menu ids, item ids, menu handles, and window pointers.
  1509. X
  1510. X
  1511. X
  1512. XHow to Use SimpleTools
  1513. X
  1514. XFor the following discussion, assume the following main() routine is
  1515. Xcoded:
  1516. X
  1517. X    main()
  1518. X
  1519. X    {
  1520. X
  1521. X      simpletools("Documentation Tutorial");
  1522. X
  1523. X      mysetup();
  1524. X
  1525. X      for (;;) simpleevents();
  1526. X
  1527. X    }
  1528. X
  1529. XThis is a typical main() routine while using SimpleTools.  We will now 
  1530. X
  1531. Xdiscuss what is happening.
  1532. X
  1533. X
  1534. X
  1535. XAfter you have compiled your program, you must use your linker to link
  1536. XSimpleTools.o to your object file.
  1537. X
  1538. X
  1539. X
  1540. Xsimpletools("Documentation Tutorial");
  1541. X
  1542. XThis routine initializes the other SimpleTools routines.  It must be called
  1543. X
  1544. Xbefore any other SimpleTools routines are called.  It is called with the
  1545. X
  1546. Xname of the menu item to appear just under the apple menu (usually this
  1547. X
  1548. Xwill be something like "About MyProgram").  
  1549. X
  1550. X
  1551. X
  1552. XThe apple, file, and edit menus will be installed and displayed on the
  1553. X
  1554. Xmenu bar.  Under the apple menu will be the name you supplied (disabled),
  1555. X
  1556. Xa dashed line (disabled), and the available desk accessories.  Under the
  1557. X
  1558. Xfile menu will be the item "New" disabled.  Under the edit menu will be
  1559. X
  1560. Xundo, a dashed line (disabled), cut, copy, paste, and clear.
  1561. X
  1562. X  
  1563. X
  1564. X
  1565. X
  1566. XWhat Can Go In or Replace MySetup()
  1567. X
  1568. XBefore you start repeatedly calling simpleevents(), you'll probably want
  1569. X
  1570. Xto set up some windows and more menues than those installed by 
  1571. X
  1572. Xsimpletools().  BUT, YOU DON'T HAVE TO!  Your program will run with
  1573. X
  1574. Xjust the lines:
  1575. X
  1576. X    main()
  1577. X
  1578. X    {
  1579. X
  1580. X      simpletools("My Program Name");
  1581. X
  1582. X      for (;;) simpleevents();
  1583. X
  1584. X    }
  1585. X
  1586. XThis little program will just give you a skeleton application and about
  1587. X
  1588. Xall you will be able to do is run desk accessories.
  1589. X
  1590. X
  1591. X
  1592. XThe following routines can be used to setup your application before you
  1593. X
  1594. Xrun the simpleevents() loop.  
  1595. X
  1596. X
  1597. X
  1598. Xmenu ("File", "Quit", leave);
  1599. X
  1600. XLet us say you have previously defined the procedure:
  1601. X
  1602. X    leave()
  1603. X
  1604. X    {
  1605. X
  1606. X      exit(0);
  1607. X
  1608. X    }
  1609. X
  1610. XThen the statement:
  1611. X
  1612. X    menu ("File", "Quit", leave);
  1613. X
  1614. Xwill install under the File menu an item named Quit.  It will also store
  1615. X
  1616. Xthe procedure 'leave' as the routine to execute if the user picks Quit
  1617. X
  1618. Xfrom the File menu.  
  1619. X
  1620. X
  1621. X
  1622. XUsing this menu() statement, you can install or modify menu entries.  Each
  1623. X
  1624. Xcall to menu() must have three arguments.  The first is the menu name you
  1625. X
  1626. Xwish to reference, the second is the item name within the menu, and the
  1627. X
  1628. Xthird is either a procedure pointer or either 0L, 1L, 2L, or 3L (this will be
  1629. Xexplained).  
  1630. X
  1631. X
  1632. X
  1633. XIf you want to install a new menu/item pair, first define the procedure you
  1634. X
  1635. Xwould like to run when that item is selected.  It can be a no op, like:
  1636. X
  1637. X    nop()
  1638. X
  1639. X    {
  1640. X
  1641. X    }
  1642. X
  1643. XSo you can say:
  1644. X
  1645. X    menu ("Commands", "Start Demo", nop);
  1646. X
  1647. X
  1648. X
  1649. X
  1650. X
  1651. XIf you want to change the procedure to run when an menu/item pair is
  1652. Xselected, just call menu() again with the new procedure.  For example, if
  1653. Xyou had:
  1654. X
  1655. X    beep()
  1656. X
  1657. X    {
  1658. X
  1659. X      sysbeep(10);
  1660. X
  1661. X    }
  1662. X
  1663. Xyou can say (at any time, not just during your setup):
  1664. X
  1665. X    menu ("Commands", "Start Demo", beep);
  1666. X
  1667. X
  1668. X
  1669. XYou may use a name such as "Medium/M" or "Slow/S" and then
  1670. X
  1671. Xyou may use the keys Command-M or Command-S to invoke the menu item
  1672. Xinstead of using the mouse.  Any reference to the item name must
  1673. Xinclude the /K addition to the name.  
  1674. X
  1675. X
  1676. X
  1677. XDisabling, Enabling, Checking, or Unchecking Menu Items
  1678. X
  1679. XIf you want to disable, enable, check, or uncheck an item, you would pass 
  1680. X
  1681. Xeither 0L, 1L, 2L, or 3L.  It is best if you define constants like:
  1682. X
  1683. X    #define itemdisable 0L
  1684. X
  1685. X    #define itemenable  1L
  1686. X
  1687. X    #define itemcheck   2L
  1688. X
  1689. X    #define itemuncheck 3L
  1690. X
  1691. Xthen you can say:
  1692. X
  1693. X    menu ("Commands", "Start Demo", itemdisable);
  1694. X
  1695. Xor:        
  1696. X
  1697. X    menu ("Commands", "Start Demo", itemcheck);
  1698. X
  1699. X
  1700. X
  1701. XWhat you would probably do is have the procedure assigned to the
  1702. Xmenu/item handle the checking and unchecking.  And you would have the
  1703. Xprocedures which deactivate and activate windows do the job of disabling
  1704. Xand enabling menus. For example, take a look at this complete program:
  1705. X
  1706. X    #define itemcheck 2L
  1707. X
  1708. X    #define itemuncheck 3L
  1709. X
  1710. X    #define normal 0
  1711. X
  1712. X    #define wide   1
  1713. X
  1714. X    int pensize = normal;
  1715. X
  1716. X
  1717. X
  1718. X    setwidepen()
  1719. X
  1720. X    {
  1721. X
  1722. X      if (pensize == normal) {
  1723. X
  1724. X        menu ("Commands", "Wide Pen", itemcheck);
  1725. X
  1726. X                    pensize = wide;
  1727. X
  1728. X                  } else {
  1729. X
  1730. X        menu ("Commands", "Wide Pen", itemuncheck);
  1731. X
  1732. X        pensize = normal;
  1733. X
  1734. X                  }
  1735. X
  1736. X                }
  1737. X
  1738. X
  1739. X
  1740. X    main()
  1741. X
  1742. X    {
  1743. X
  1744. X      simpletools("Check-Uncheck Test");
  1745. X
  1746. X      menu ("Commands", "Wide Pen", setwidepen);
  1747. X
  1748. X      for (;;) simpleevents();
  1749. X
  1750. X    }    
  1751. X
  1752. X
  1753. X
  1754. XIf you call menu() to disable/enable/check/uncheck an item with a
  1755. Xmenu/item not already installed, that menu/item will be installed with a
  1756. Xno_op procedure before disabling/enabling/checking/unchecking.
  1757. X
  1758. X
  1759. X
  1760. XThe "About" Entry Under the Apple Menu
  1761. X
  1762. XTo assign a procedure or enable the first item under the apple menu, you
  1763. X
  1764. Xwould use exactly the same menu() routine.  The difficult part is what
  1765. X
  1766. Xto call the Apple menu.  I thought about making a special case for the
  1767. X
  1768. XApple menu so you might just say, menu ("Apple", "About MyProgram",
  1769. Xroutine), but that would put a "special case" into menu()'s use which I
  1770. Xdidn't want to have to remember. Instead, you must pass a regular C string
  1771. Xwith the Apple character as its contents (since that is  the name of the
  1772. Xmenu.) To simplify making such a string, I have one already defined which
  1773. Xyou can link into your program by using extern.  If you add the line:
  1774. X
  1775. X    extern char applestring[];
  1776. X
  1777. Xyou will then have a string containing the apple character.  You can then
  1778. X
  1779. Xsay:
  1780. X
  1781. X    #define itemenable 1L
  1782. X
  1783. X    extern char applestring[];
  1784. X
  1785. X
  1786. X
  1787. X    tellaboutme()    /* displays a dialog box */
  1788. X
  1789. X    {
  1790. X
  1791. X      message ("Hi.  I'm a practice program");
  1792. X
  1793. X    }
  1794. X
  1795. X
  1796. X
  1797. X    main()
  1798. X
  1799. X    {
  1800. X
  1801. X      simpletools("About Practice");
  1802. X
  1803. X      menu (applestring,"About Practice",tellaboutme);
  1804. X
  1805. X      menu (applestring,"About Practice",itemenable);
  1806. X
  1807. X      for (;;) simpleevents();
  1808. X
  1809. X    }
  1810. X
  1811. X
  1812. X
  1813. XInstalling a Window
  1814. X
  1815. XAs a tutorial example, let's say we want to put up a single window on the
  1816. X
  1817. Xscreen.  Let's say that nothing "extra" will happen with the window is
  1818. X
  1819. Xactivated, deactivated, updated or when the mouse button is pressed inside
  1820. X
  1821. Xof it.  This window will be movable, sizable, and hadeable by the user
  1822. X
  1823. Xwhile simpleevents() is being repeatedly run.  Take a look at this program:
  1824. X
  1825. X    nop()
  1826. X
  1827. X    {
  1828. X
  1829. X    }
  1830. X
  1831. X
  1832. X
  1833. X    main()
  1834. X
  1835. X    {
  1836. X
  1837. X      simpletools("Window Demo");
  1838. X
  1839. X      window ("My Window", 50, 50, 500, 300, nop, nop,
  1840. X        nop, nop);
  1841. X
  1842. X      for (;;) simpleevents();
  1843. X
  1844. X    }
  1845. X
  1846. XThis program will first install the standard apple, file, and edit menus.
  1847. X
  1848. XIt will then place a document window on the screen with its top left
  1849. Xcorner at 50, 50 and its bottom right corner at 500, 300.  Nop is used for
  1850. Xthe "thing to do" when the window is activated, deactivated, updated, or
  1851. Xwhen the mouse is clicked in the window.  
  1852. X
  1853. X
  1854. X
  1855. XAn additional menu item is added under a menu title of Windows with the
  1856. Xname of the window.  This item is enabled and when selected will bring
  1857. Xthe named window to the front and visable.  The installation of this menu
  1858. Xitem may be turned off and on as windows are created in case there are
  1859. Xsome windows you don't want in this Windows menu.  To turn this feature
  1860. Xoff, you must set the external variable "windmenu" to false while you
  1861. Xmake the window() call.  You get access to this variable with the line:
  1862. X
  1863. X    extern int windmenu;
  1864. X
  1865. X
  1866. X
  1867. X
  1868. X
  1869. X
  1870. X
  1871. XMore Detail On Window()
  1872. X
  1873. XThe window() procedure installs or modifies the "things to do" lists for
  1874. X
  1875. Xa window.  Its first argument is the name of the window.  The next four
  1876. X
  1877. Xarguments are integers describing where the window is to be placed and
  1878. X
  1879. Xhow big it is.  These positioning arguments are only used to orginally
  1880. X
  1881. Xinstall the window.  They will be ignored if the window has already been
  1882. X
  1883. Xmade!  This is so that the user has complete control of the placement of
  1884. X
  1885. Xthe window once the programmer has put one onto the screen.  The next
  1886. X
  1887. Xfour arguments are procedures to run when the system receives an event
  1888. Xto activate, deactivate, update, or that a mouse has clicked inside the
  1889. X
  1890. Xwindow.
  1891. X
  1892. X
  1893. X
  1894. XHere is an example of a program which uses windows with the window's
  1895. X
  1896. X"things to do" list not just no_ops:
  1897. X
  1898. X    #define itemenable 1L
  1899. X
  1900. X    #define itemdisable 0L
  1901. X
  1902. X
  1903. X
  1904. X    nop()
  1905. X
  1906. X    {
  1907. X
  1908. X    }
  1909. X
  1910. X
  1911. X
  1912. X    myactivate()   /* to be done when window is activated */
  1913. X
  1914. X    {
  1915. X
  1916. X      menu ("Edit", "Clear", itemenable);
  1917. X
  1918. X                   }
  1919. X
  1920. X
  1921. X
  1922. X    mydeactivate()  /* when window is deactivate */
  1923. X
  1924. X    {
  1925. X
  1926. X      menu ("Edit", "Clear", itemdisable);
  1927. X
  1928. X    }
  1929. X
  1930. X
  1931. X
  1932. X    myupdate()   /* when window needs redrawn */
  1933. X
  1934. X    {
  1935. X
  1936. X      moveto (10,10);
  1937. X
  1938. X      puts("Hi There");
  1939. X
  1940. X    }
  1941. X
  1942. X
  1943. X
  1944. X    mycontent()   /* when mouse is clicked in window */
  1945. X
  1946. X    {
  1947. X
  1948. X      sysbeep(10);
  1949. X
  1950. X    }
  1951. X
  1952. X
  1953. X
  1954. X    myclear()
  1955. X
  1956. X    {
  1957. X
  1958. X    /* something to erase the contents of the window */
  1959. X
  1960. X    }
  1961. X
  1962. X
  1963. X
  1964. X    main()
  1965. X
  1966. X    {
  1967. X
  1968. X      simpletools("More Window Demo");
  1969. X
  1970. X      menu ("Edit", "Clear", myclear);
  1971. X
  1972. X      window ("My Demo Window", 50, 50, 300, 300,
  1973. X        myactivate,mydeactivate, myupdate, mycontent);
  1974. X
  1975. X      for (;;) simpleevents();
  1976. X
  1977. X    }    
  1978. X
  1979. X
  1980. X
  1981. XThe Run and Stop Routines
  1982. X
  1983. XEach time simpleevents() is run, it calls (in addition to handling all
  1984. X
  1985. Xsystem events) any procedures you have asked it to call with the run()
  1986. X
  1987. Xcommand.  By using run(), you can make procedures look as if they are
  1988. X
  1989. Xrunning in the "background".  For example, a run procedure might display
  1990. X
  1991. Xrandom sized circles in a particular window.  Then, while anything else
  1992. X
  1993. Xis happening in your program, as long as it keeps calling simpleevents()
  1994. X
  1995. Xyou will get random sized circles appearing in a window. 
  1996. X
  1997. X
  1998. X
  1999. XYou may install up to 50 procedures to execute each time
  2000. X
  2001. Xsimpleevents is called.  For example, if you would like to count how
  2002. X
  2003. Xmany times simpleevents() is running, you could have:
  2004. X
  2005. X    long count = 0L;
  2006. X
  2007. X    countcalls()
  2008. X
  2009. X    {
  2010. X
  2011. X      count++;
  2012. X
  2013. X    }
  2014. X
  2015. Xand then say:
  2016. X
  2017. X    run (countcalls)
  2018. X
  2019. Xsomewhere in your program whenever you want to start executing
  2020. Xcountcalls.  The run() procedure DOES NOT RUN the routine you give it.  It
  2021. Xonly adds it to the list of things to run.  
  2022. X
  2023. X
  2024. X
  2025. XPROCEDURE ASSIGNED TO BE RUN SHOULD END QUICKLY.  If they don't, other
  2026. X
  2027. Xevents will be hung up.  Also, if a procedure to be run calls simpleevents(),
  2028. Xyou'll get into an infinate loop with no way out.
  2029. X
  2030. X
  2031. X
  2032. XThe stop() procedure is used to remove an item from the run list.  For
  2033. X
  2034. Xexample, in the above example we could have said:
  2035. X
  2036. X    long count = 0L;
  2037. X
  2038. X    countcalls()
  2039. X
  2040. X    {
  2041. X
  2042. X      if (count++ > 100000) {
  2043. X
  2044. X        sysbeep (10);
  2045. X
  2046. X        count = 0L;
  2047. X
  2048. X        stop (countcalls);
  2049. X
  2050. X       }
  2051. X
  2052. X    }
  2053. X
  2054. Xand then said:
  2055. X
  2056. X    run (countcalls)
  2057. X
  2058. Xafter a while, you'll hear a beep and countcalls() will be removed from
  2059. X
  2060. Xthe list of procedures to run.
  2061. X
  2062. X
  2063. X
  2064. XDirecting Output to a Window of Your Choice
  2065. X
  2066. XLet us say you have installed a window named "My First Window".  If you
  2067. X
  2068. Xwant to direct output to this window, use:
  2069. X
  2070. X    withwindow ("My First Window");
  2071. X
  2072. Xand all output (graphics and text) will go to that window.  This is
  2073. X
  2074. Xthe same as using the toolbox's setport() routine except you don't 
  2075. X
  2076. Xhave to know the window's grafport pointer.
  2077. X
  2078. X
  2079. X
  2080. XA Message Dialog
  2081. X
  2082. XYou may display a dialog box with a message by using a line like:
  2083. X
  2084. X    message ("Sorry, a window by that name already exists.");
  2085. X
  2086. X
  2087. X
  2088. X
  2089. X
  2090. XMessage() returns either TRUE or FALSE depending on whether OK or Cancel
  2091. Xwas clicked by the user.  There is enough room for a three line message. 
  2092. XYou may place Carriage Return characters to force using the next line. 
  2093. XThis is done in C with:
  2094. X
  2095. X    message ("First line\rSecond line");
  2096. X
  2097. X
  2098. X
  2099. XA Prompt Dialog
  2100. X
  2101. XYou may ask the user a question by using a dialog box with a question, an
  2102. Xeditable window for the answer, and the OK and Cancel buttons.  An
  2103. Xexample:
  2104. X
  2105. X    char answer[255];
  2106. X
  2107. X    strcpy (answer, "New Window");
  2108. X
  2109. X    prompt("Give me a unique name for the new window:",
  2110. X
  2111. X      answer);
  2112. X
  2113. X        
  2114. X
  2115. X
  2116. X
  2117. XPrompt() returns TRUE if either the OK button is pressed or RETURN is
  2118. Xtyped.  FALSE is returned if Cancel was clicked by the user.  Make sure you
  2119. Xset the answer string to at least a null string.  Random data in the answer
  2120. Xstring will generate a random default answer.
  2121. X
  2122. X
  2123. X
  2124. X+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  2125. X
  2126. X
  2127. X
  2128. XAdvanced Notes:
  2129. X
  2130. X
  2131. X
  2132. X1) Each procedure called when a menu item is selected is passed the
  2133. X
  2134. Xaddress of a string containing the name of the item which was
  2135. X
  2136. Xselected.  This is convenient if you want several menu/items to call
  2137. X
  2138. Xthe same procedure.  For example, if you had a list of baud rate
  2139. X
  2140. Xsettings in a menu.  Each item can be assigned the same routine
  2141. X
  2142. Xto run.  The routine might look like:
  2143. X
  2144. X    int brate;
  2145. X
  2146. X
  2147. X
  2148. X    setbaudrate( itemselected )
  2149. X
  2150. X    char *itemselected;
  2151. X
  2152. X    {
  2153. X
  2154. X      brate = atoi ( itemselected);
  2155. X
  2156. X            }
  2157. X
  2158. X
  2159. X
  2160. X2) Simpleevents() will set the output port to the proper window before
  2161. X
  2162. Xit calls the procedures assigned to that window.  This means that those
  2163. X
  2164. Xprocedures do not have to set output to any window.  Output will
  2165. X
  2166. Xautomatically go to the window which is being activated, deactivated,
  2167. Xupdated, or for which the mouse has been pressed.
  2168. X
  2169. X
  2170. X
  2171. X3) Each window content procedure assigned to one of your windows is
  2172. X
  2173. Xpassed the x and y position of the mouse in that window's local
  2174. X
  2175. Xcoordinates.  You could declare one of these procedures like:
  2176. X
  2177. X    dotinmywindow(x,y)
  2178. X
  2179. X    int x,y;
  2180. X
  2181. X    {
  2182. X
  2183. X      moveto (x,y);
  2184. X
  2185. X      lineto (x,y);
  2186. X
  2187. X            }
  2188. X
  2189. Xand used dotinmywindow() as a window's procedure to run when the mouse
  2190. X
  2191. Xis clicked in that window.    
  2192. X
  2193. X
  2194. X
  2195. X4) Each window procedure is passed the relavant window pointer and
  2196. X
  2197. Xthe address of the event record which caused that window to have some 
  2198. X
  2199. Xaction taken on it.
  2200. X
  2201. X
  2202. X
  2203. X5) Each run procedure is passed the address of the next event record
  2204. X
  2205. Xto be processed by simpleevents().  Maybe your run procedure would
  2206. X
  2207. Xlike to monitor this or even change it?
  2208. X
  2209. X
  2210. X
  2211. X6) A very useful function is:
  2212. X
  2213. X    windowptr windowpoint ("My Window") 
  2214. X
  2215. XThis returns the window pointer to your window named "My Window".  This
  2216. Xallows you to call nearly all of the toolbox routines which manipulate
  2217. Xwindows. You could say things like:
  2218. X
  2219. X    setport ( windowpoint ("My Window"));
  2220. X
  2221. X    hidewindow ( windowpoint ("My Window"));
  2222. X
  2223. X    showwindow ( windowpoint ("My Window"));
  2224. X
  2225. X    selectwindow ( windowpoint ("My Window"));
  2226. X
  2227. X    if (frontwindow() !=windowpoint("My Window")) {};
  2228. X
  2229. X
  2230. X
  2231. XYou can have access to this fuction after the definition:
  2232. X
  2233. X    extern windowptr windowpoint();
  2234. X
  2235. X
  2236. X
  2237. X7) Another useful fuction is:
  2238. X
  2239. X    menuhandle mhand ("Edit")
  2240. X
  2241. XThis returns a menuhandle to the named menu.  This allows you to call
  2242. Xnearly all of the toolbox routines which manipulate menus.
  2243. X
  2244. X
  2245. X
  2246. XYou can have access to this function after the definition:
  2247. X
  2248. X    extern menuhandle mhand();
  2249. X
  2250. X    
  2251. X
  2252. X8) Several of the SimpleTools routines return result codes.  You may
  2253. Xchoose to ignore these.  In case you want to use them, here is what they
  2254. Xare:
  2255. X
  2256. X    menu ()      TRUE if a new item was added
  2257. X
  2258. X        FALSE if it already existed
  2259. X
  2260. X
  2261. X
  2262. X    window ()    TRUE if a new window was added
  2263. X
  2264. X        FALSE if it already existed
  2265. X
  2266. X
  2267. X
  2268. X    withwindow ()
  2269. X
  2270. X        TRUE if window exists
  2271. X
  2272. X        FALSE if not
  2273. X
  2274. X
  2275. X
  2276. X    run ()    TRUE if installation worked
  2277. X
  2278. X        FALSE if not (too many installs)
  2279. X
  2280. X
  2281. X
  2282. X    stop ()    TRUE if procedure was found
  2283. X
  2284. X        FALSE if not
  2285. X
  2286. X
  2287. X
  2288. X    runruns()    # of routines runned
  2289. X
  2290. X
  2291. X
  2292. X9) Three external integers may be modified to affect how the window()
  2293. Xcommand works.  They are originally set to default values.  You can ignore
  2294. Xthese variables.  If you want to change them, they stay changed until you
  2295. Xchange them back to their original value.
  2296. X
  2297. X
  2298. X
  2299. X    wprocid    The window procedure id.  
  2300. X
  2301. X        0 standard document window (default)
  2302. X
  2303. X        1 alert box
  2304. X
  2305. X        2 plain box
  2306. X
  2307. X        3 plain box with shadow
  2308. X
  2309. X        4 document window without size
  2310. X
  2311. X        16 rounded corner box (DA type)
  2312. X
  2313. X
  2314. X
  2315. X    dogoaway    TRUE if go away box is used (default)
  2316. X
  2317. X
  2318. X
  2319. X    windmenu    TRUE if entry is made into Window menu
  2320. X
  2321. X
  2322. X
  2323. ________This_Is_The_END________
  2324. if test `wc -l < SimpleTools.doc` -ne 919; then
  2325.     echo 'shar: SimpleTools.doc was damaged during transit'
  2326.   echo '      (should have been 919 bytes)'
  2327. fi
  2328. fi        ; : end of overwriting check
  2329. exit 0
  2330.