home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / stdwin / Ports / mac / dialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-06  |  7.9 KB  |  377 lines  |  [TEXT/????]

  1. /* MAC STDWIN -- DIALOGS. */
  2.  
  3. /* XXX These dialogs are distinctly ugly.
  4.    Maybe we should fix their size based on the amount of text
  5.    and the number of buttons. */
  6.  
  7. #include "macwin.h"
  8. #ifdef MPW
  9. #include <Dialogs.h>
  10. #include <Packages.h>
  11. #endif
  12. #ifdef THINK_C_PRE_5_0
  13. #include <DialogMgr.h>
  14. #include <StdFilePkg.h>
  15. #endif
  16.  
  17. /* Function prototypes */
  18.  
  19. STATIC struct itemlist **mkitemlist _ARGS((void));
  20. STATIC struct item *finditem _ARGS((struct itemlist **h, int i));
  21. STATIC void additem _ARGS((struct itemlist **h,
  22.     long stuff, Rect *ppos, int type, int size, char *data));
  23. STATIC struct itemlist **ynclist _ARGS((char *prompt));
  24. STATIC struct itemlist **oklist _ARGS((char *prompt));
  25. STATIC struct itemlist **editlist _ARGS((char *prompt));
  26. STATIC int do_dialog _ARGS((struct itemlist **h,
  27.     int emphasis, int lastbutton, char *buf));
  28.  
  29. /* Mac-specific interface for applications that need different
  30.    file types */
  31.  
  32. extern OSType std_type;
  33.  
  34. #ifdef THINK_C
  35. OSType std_type= 'TEXT';
  36. #endif
  37.  
  38. OSType *wasktypelist= &std_type;
  39. int waskntypes= 1;
  40.  
  41. /* Standard File interface routine */
  42.  
  43. bool
  44. waskfile(prompt, buf, len, new)
  45.     char *prompt;
  46.     char *buf;
  47.     int len;
  48.     bool new;
  49. {
  50.     static Point corner= {80, 60};
  51.     SFReply reply;
  52.     
  53.     if (active != NULL)
  54.         rmcaret(active);
  55.     if (new) {
  56.         char *def= strrchr(buf, ':');
  57.         if (def != NULL)
  58.             ++def;
  59.         else
  60.             def= buf;
  61.         SFPutFile(PASSPOINT corner, PSTRING(prompt),
  62. #ifdef THINK_C /* XXX ??? */
  63. /* XXX I think PSTRING returns a pointer to a static buffer
  64.    so there can be only one call to PSTRING in an arg list.
  65.    Maybe I forgot that when I found this code didn't work.
  66.    Should fix it better! */
  67.             CtoPstr(def),
  68. #else
  69.             PSTRING(def),
  70. #endif
  71.             (ProcPtr)NULL, &reply);
  72.     }
  73.     else {
  74.         SFGetFile(PASSPOINT corner, (char*)NULL, (ProcPtr)NULL,
  75.             waskntypes, wasktypelist, (ProcPtr)NULL, &reply);
  76.     }
  77.     set_watch();
  78.     if (!reply.good)
  79.         return FALSE;
  80.     fullpath(buf, reply.vRefNum, p2cstr((char*)&reply.fName));
  81.     return TRUE;
  82. }
  83.  
  84. /* Data definitions for dialog item lists (from Inside Mac). */
  85.  
  86. struct item {
  87.     long stuff;        /* Handle or proc pointer */
  88.     Rect pos;        /* Position (local coord.) */
  89.     char type;        /* Item type */
  90.     char size;        /* Length of data; must be even */
  91.     char data[256];     /* The data; variable length */
  92. };
  93.  
  94. struct itemlist {
  95.     short count;        /* Number of items minus one */
  96.     struct item data;    /* First item */
  97.     /* NB: items are variable length. */
  98. };
  99.  
  100. #define ROUND_EVEN(x) (((x) + 1) & ~1) /* Round up to even */
  101.  
  102. #define FIXED_SIZE 14        /* Size of struct item w/o data */
  103.  
  104. /* Routines to manipulate Dialog item lists. */
  105.  
  106. /* Create an empty item list. */
  107.  
  108. static struct itemlist **
  109. mkitemlist()
  110. {
  111.     struct itemlist **h= (struct itemlist **) NewHandle(2);
  112.     
  113.     (*h)->count= -1;
  114.     return h;
  115. }
  116.  
  117. /* Find the i'th item, starting to count from 0.
  118.    It may be asked for the non-existing item just beyond the last,
  119.    but not beyond that. */
  120.  
  121. static struct item *
  122. finditem(h, i)
  123.     struct itemlist **h;
  124.     int i;
  125. {
  126.     int count= (*h)->count;
  127.     struct item *it= &(*h)->data;
  128.     int k;
  129.     
  130.     if (i < 0 || i > count+1) {
  131.         return NULL;
  132.     }
  133.     for (k= 0; k < i; ++k) {
  134.         /* I don't trust two casts in one expression: */
  135.         char *p= (char *) it;
  136.         int size= ROUND_EVEN(it->size);
  137.         p += FIXED_SIZE + size;
  138.         it= (struct item *) p;
  139.     }
  140.     return it;
  141. }
  142.  
  143. /* Add an item to the list. */
  144.  
  145. static void
  146. additem(h, stuff, ppos, type, size, data)
  147.     struct itemlist **h;
  148.     long stuff;
  149.     Rect *ppos;
  150.     int type;
  151.     int size;
  152.     char *data;
  153. {
  154.     struct item *it;
  155.     long totalsize;
  156.     
  157.     if (size < 0)
  158.         size= strlen(data);
  159.     it= finditem(h, (*h)->count + 1);
  160.     totalsize= (char *)it - (char *)(*h);
  161.     SetHandleSize(h, totalsize + FIXED_SIZE + ROUND_EVEN(size));
  162.     it= finditem(h, (*h)->count + 1);
  163.     it->stuff= stuff;
  164.     it->pos= *ppos;
  165.     it->type= type;
  166.     it->size= size;
  167.     BlockMove(data, it->data, size);
  168.     ++(*h)->count;
  169. }
  170.  
  171. /* Construct item list for question w/ Yes/No/Cancel response.
  172.    Note: the statText item is first, so we can distinguish between a
  173.    press on Return or Enter (when ModalDialog returns 1) and any
  174.    of the three buttons. */
  175.  
  176. static struct itemlist **
  177. ynclist(prompt)
  178.     char *prompt;
  179. {
  180.     struct itemlist **h= mkitemlist();
  181.     Rect pos;
  182.     
  183.     SetRect(&pos, 20, 20, 280, 70);
  184.     additem(h, 0L, &pos, statText|itemDisable, -1, prompt);
  185.     SetRect(&pos, 20, 80, 80, 100);
  186.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "Yes");
  187.     OffsetRect(&pos, 0, 30);
  188.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "No");
  189.     OffsetRect(&pos, 200, 0);
  190.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "Cancel");
  191.     return h;
  192. }
  193.  
  194. /* Construct item list for message w/ OK button. */
  195.  
  196. static struct itemlist **
  197. oklist(prompt)
  198.     char *prompt;
  199. {
  200.     struct itemlist **h= mkitemlist();
  201.     Rect pos;
  202.     
  203.     SetRect(&pos, 20, 20, 280, 100);
  204.     additem(h, 0L, &pos, statText|itemDisable, -1, prompt);
  205.     SetRect(&pos, 20, 110, 80, 130);
  206.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "OK");
  207.     return h;
  208. }
  209.  
  210. /* Construct item list for dialog w/ edit-text, OK and Cancel button. */
  211.  
  212. static struct itemlist **
  213. editlist(prompt)
  214.     char *prompt;
  215. {
  216.     struct itemlist **h= mkitemlist();
  217.     Rect pos;
  218.     
  219.     SetRect(&pos, 20, 20, 280, 70);
  220.     additem(h, 0L, &pos, statText|itemDisable, -1, prompt);
  221.     SetRect(&pos, 20, 110, 80, 130);
  222.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "OK");
  223.     OffsetRect(&pos, 200, 0);
  224.     additem(h, 0L, &pos, ctrlItem|btnCtrl, -1, "Cancel");
  225.     SetRect(&pos, 20, 80, 280, 96);
  226.     additem(h, 0L, &pos, editText, 0, (char *) NULL);
  227.     return h;
  228. }
  229.  
  230. /* Perform an entire dialog.
  231.    It stops when an item <= lastbutton is hit, and returns the item number.
  232.    When buf is non-NULL, the next item is assumed to be an edit-text
  233.    item and its contents are transferred to buf. */
  234.  
  235. static int
  236. do_dialog(h, emphasis, lastbutton, buf)
  237.     struct itemlist **h;
  238.     int emphasis;
  239.     int lastbutton;
  240.     char *buf;
  241. {
  242.     Rect box;
  243.     DialogPtr d;
  244.     short hit;
  245.     short type;
  246.     Handle item;
  247.     
  248.     _wresetmouse(); /* Clean up mouse down status */
  249.     if (active != NULL)
  250.         rmcaret(active);
  251.     
  252.     /* Create a box of convenient size, centered horizontally,
  253.        somewhat below the top of the screen. */
  254.     SetRect(&box, 0, 0, 300, 140);
  255.     OffsetRect(&box, (screen->portRect.right - box.right)/2, 60);
  256.     
  257.     d= NewDialog(
  258.         (Ptr)NULL,
  259.         &box,
  260.         "",
  261.         true,
  262.         dBoxProc,
  263.         (WindowPtr)(-1),
  264.         false,
  265.         0L,
  266.         h);
  267.     
  268.     if (emphasis > 0) { /* Emphasize default button */
  269.         GetDItem(d, emphasis, &type, &item, &box);
  270.         SetPort(d);
  271.         InsetRect(&box, -4, -4);
  272.         PenSize(3, 3);
  273.         FrameRoundRect(&box, 16, 16);
  274.     }
  275.     
  276.     if (buf != NULL) { /* Set edit text and focus on entire text */
  277.         GetDItem(d, lastbutton+1, &type, &item, &box);
  278.         SetIText(item, PSTRING(buf));
  279.         SelIText(d, lastbutton+1, 0, 32000);
  280.     }
  281.     
  282.     set_arrow();
  283.     
  284.     /* XXX Should support Cmd-period as shortcut for Cancel;
  285.        perhaps other shortcuts as well? */
  286.     
  287.     do {
  288.         ModalDialog((ProcPtr)NULL, &hit);
  289.     } while (hit > lastbutton);
  290.     
  291.     set_watch();
  292.     
  293.     if (hit == 1 && emphasis > 0) {
  294.         /* Pressed Return or Enter; flash default button. */
  295.         GetDItem(d, emphasis, &type, &item, &box);
  296.         HiliteControl((ControlHandle)item, inButton);
  297.     }
  298.     
  299.     if (buf != NULL) {
  300.         GetDItem(d, lastbutton+1, &type, &item, &box);
  301.         GetIText(item, buf);
  302. #ifndef CLEVERGLUE
  303.         PtoCstr(buf);
  304. #endif
  305.     }
  306.     DisposDialog(d);
  307.     return hit;
  308. }
  309.  
  310. void
  311. wmessage(prompt)
  312.     char *prompt;
  313. {
  314.     do_dialog(oklist(prompt), 2, 2, (char *)NULL);
  315. }
  316.  
  317. int
  318. waskync(prompt, def)
  319.     char *prompt;
  320. {
  321.     int emphasis;
  322.     int hit;
  323.     
  324.     switch (def) {
  325.     case 1:
  326.         emphasis= 2;
  327.         break;
  328.     case 0:
  329.         emphasis= 3;
  330.         break;
  331.     default:
  332.         emphasis= 4;
  333.         break;
  334.     }
  335.     
  336.     hit= do_dialog(ynclist(prompt), emphasis, 4, (char *) NULL);
  337.     
  338.     switch (hit) {
  339.     default: /* case 1: Return or Enter pressed */
  340.         return def;
  341.     case 2: /* Yes button */
  342.         return 1;
  343.     case 3: /* No button */
  344.         return 0;
  345.     case 4: /* Cancel button */
  346.         return -1;
  347.     }
  348. }
  349.  
  350. bool
  351. waskstr(prompt, buf, len)
  352.     char *prompt;
  353.     char *buf;
  354.     int len;
  355. {
  356.     /* This code assumes 'buf' is at least 256 bytes long! */
  357.     return do_dialog(editlist(prompt), 2, 3, buf) <= 2;
  358. }
  359.  
  360. void
  361. wperror(name)
  362.     char *name;
  363. {
  364.     char buf[256];
  365.     char *p= buf;
  366.     
  367.     if (name != NULL) {
  368.         strcpy(p, name);
  369.         strcat(p, ": ");
  370.         p += strlen(p);
  371.     }
  372.     strcat(p, "I/O error");
  373.     p += strlen(p);
  374.     sprintf(p, " %d", errno);
  375.     wmessage(buf);
  376. }
  377.