home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / M / MacPerl 4.13 source.sit / Perl Source ƒ / MacPerl / MPPreferences.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-04  |  22.6 KB  |  1,055 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl                -    Real Perl Application
  3. File        :    MPPreferences.c    -    Handle Preference Settings
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPPreferences.c,v $
  12. Revision 1.2  1994/05/04  02:52:40  neeri
  13. Inline Input.
  14.  
  15. Revision 1.1  1994/02/27  23:01:32  neeri
  16. Initial revision
  17.  
  18. Revision 0.1  1993/12/08  00:00:00  neeri
  19. Separated from MPUtils
  20.  
  21. *********************************************************************/
  22.  
  23. #include <PLStringFuncs.h>
  24. #include <Events.h>
  25. #include <Traps.h>
  26. #include <Dialogs.h>
  27. #include <Fonts.h>
  28. #include <Packages.h>
  29. #include <ToolUtils.h>
  30. #include <AppleEvents.h>
  31. #include <TFileSpec.h>
  32. #include <Folders.h>
  33. #include <Resources.h>
  34. #include <OSUtils.h>
  35. #include <Files.h>
  36. #include <Lists.h>
  37. #include <Icons.h>
  38. #include <Script.h>
  39. #include <SysEqu.h>
  40. #include <string.h>
  41. #include <GUSI.h>
  42. #include <Desk.h>
  43. #include <ctype.h>
  44. #include <stdio.h>
  45.  
  46. #include "MPPreferences.h"
  47. #include "MPUtils.h"
  48. #include "MPWindow.h"
  49. #include <patchlevel.h>
  50.  
  51. pascal void OpenPreferenceFile(FSSpec * spec)
  52. {
  53.     Str255        name;
  54.     short            oldResFile;
  55.     short            res;
  56.     short    **        defaultfont;
  57.     PerlPrefs **prefs;
  58.     
  59.     oldResFile    =    CurResFile();
  60.  
  61.     gPrefsFile = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdWrPerm);
  62.     
  63.     if (gPrefsFile == -1) {
  64.         gPrefsFile = 0;
  65.          
  66.         return;
  67.     }
  68.     
  69.     if (!Get1Resource('STR#', LibraryPaths)) {
  70.         Handle    lib;
  71.         short        count = 1;
  72.         char        len;
  73.         char *    libpath;
  74.         FSSpec    libspec;
  75.         
  76.         libspec.vRefNum    =     gAppVol;
  77.         libspec.parID    =    gAppDir;
  78.         PLstrcpy(libspec.name, "\plib");
  79.         
  80.         libpath  = FSp2FullPath(&libspec);
  81.         len        = strlen(libpath);
  82.         
  83.         PtrToHand((Ptr) &count, &lib, sizeof(short));
  84.         PtrAndHand((Ptr) &len, lib, 1);
  85.         PtrAndHand(libpath, lib, len);
  86.         
  87.         AddResource(lib, 'STR#', LibraryPaths, "\p");
  88.     }
  89.     
  90.     if (!(defaultfont = (short **) Get1Resource('PFNT', 128))) {
  91.         Handle    font;
  92.         
  93.         PtrToHand((Ptr) &gFormat.size, &font, sizeof(short));
  94.         GetFontName(gFormat.font, name);
  95.         AddResource(font, 'PFNT', 128, name);
  96.     } else {
  97.         OSType type;
  98.         
  99.         GetResInfo((Handle) defaultfont, &res, &type, name);
  100.         GetFNum(name, &gFormat.font);
  101.         
  102.         if (gFormat.font)
  103.             gFormat.size = **defaultfont;
  104.         else {
  105.             gFormat.font = GetAppFont();
  106.             gFormat.size = GetDefFontSize();
  107.         }
  108.     }
  109.  
  110.     if (!(prefs = (PerlPrefs **) Get1Resource('PPRF', 128))) {
  111.         PtrToHand((Ptr) &gPerlPrefs, (Handle *)&prefs, sizeof(PerlPrefs));
  112.         AddResource((Handle) prefs, 'PPRF', 128, "\p");
  113.     } else {
  114.         gPerlPrefs.runFinderOpens     = (*prefs)->runFinderOpens;
  115.         gPerlPrefs.checkType           = (*prefs)->checkType;
  116.         if ((*prefs)->version >= PerlPrefVersion413) {
  117.             gPerlPrefs.inlineInput    = (*prefs)->inlineInput;
  118. #ifndef RUNTIME
  119.             if (gTSMTEImplemented)
  120.                 UseInlineInput(gPerlPrefs.inlineInput);
  121. #endif
  122.         }
  123.     }
  124.     
  125.     UseResFile(oldResFile);
  126. }
  127.  
  128. pascal void OpenPreferences()
  129. {
  130.     FSSpec        prefPath;
  131.     CInfoPBRec    info;
  132.     FCBPBRec        fcb;
  133.     Str63            name;
  134.  
  135.     gPrefsFile = 0;
  136.     
  137.     GetFNum("\pMonaco", &gFormat.font);
  138.     gFormat.size = gFormat.font ? 9 : GetDefFontSize();
  139.     gFormat.font = gFormat.font ? gFormat.font : GetAppFont();
  140.     
  141.     fcb.ioNamePtr    =    &name;
  142.     fcb.ioRefNum    =    CurResFile();
  143.     fcb.ioFCBIndx    =    0;
  144.     
  145.     PBGetFCBInfoSync(&fcb);
  146.     
  147.     gAppVol    =    fcb.ioFCBVRefNum;
  148.     gAppDir    =    fcb.ioFCBParID;
  149.     
  150.     prefPath.vRefNum     = gAppVol;
  151.     prefPath.parID        = gAppDir;
  152.     PLstrcpy(prefPath.name, "\pMacPerl Preferences");
  153.     
  154.     if (FSpCatInfo(&prefPath, &info))
  155.         if (FindFolder(
  156.             kOnSystemDisk, 
  157.             kPreferencesFolderType, 
  158.             true, 
  159.             &prefPath.vRefNum,
  160.             &prefPath.parID)
  161.         )
  162.             return;
  163.             
  164.     if (FSpCatInfo(&prefPath, &info)) {
  165.         if (HCreate(prefPath.vRefNum, prefPath.parID, prefPath.name, 'McPL', 'pref'))
  166.             return;
  167.             
  168.         HCreateResFile(prefPath.vRefNum, prefPath.parID, prefPath.name);
  169.     }
  170.     
  171.     OpenPreferenceFile(&prefPath);
  172. }
  173.  
  174. static short        PrefSubDialog     =     1;
  175. static short        PathCount;
  176. static ListHandle    PathList;
  177.  
  178. pascal void DrawPrefIcon(DialogPtr dlg, short item)
  179. {
  180.     short        kind;
  181.     Handle    h;
  182.     Rect        r;
  183.     Str31        title;
  184.     FontInfo    info;
  185.         
  186.     GetDItem(dlg, item, &kind, &h, &r);
  187. #ifndef RUNTIME
  188.     PlotIconID(&r, atNone, (item == PrefSubDialog) ? ttSelected : ttNone, PrefDialog+item);
  189. #else
  190.     PlotResICN_(PrefDialog+item, &r, (item == PrefSubDialog) ? iconHilited : iconPlain);
  191. #endif
  192.     GetIndString(title, PrefDialog, item);
  193.  
  194.     TextFont(1);
  195.     TextSize(9);
  196.     GetFontInfo(&info);
  197.  
  198.     MoveTo(r.left - (StringWidth(title) - 32 >> 1), r.bottom+2+info.ascent);
  199.     DrawString(title);
  200.     
  201.     if (item == PrefSubDialog) {
  202.         
  203.         r.top     = r.bottom + 2;
  204.         r.bottom = r.top + info.ascent+info.descent+info.leading+2;
  205.         r.left     = r.left - (StringWidth(title) - 32 >> 1) - 1;
  206.         r.right  = r.left + StringWidth(title) + 2;
  207.         
  208.         InvertRect(&r);
  209.     }
  210.     
  211.     TextFont(0);
  212.     TextSize(12);
  213. }
  214.  
  215. pascal void DrawPathList(DialogPtr dlg, short item)
  216. {
  217. #pragma unused(item)
  218.     Rect    r;
  219.     
  220.     TextFont(0);
  221.     TextSize(12);
  222.     LUpdate(dlg->visRgn, PathList);
  223.     r = (*PathList)->rView;
  224.     InsetRect(&r, -1, -1);
  225.     FrameRect(&r);
  226. }
  227.  
  228. pascal Boolean PrefLibFilter(DialogPtr dlg, EventRecord * ev, short * item)
  229. {
  230.     Point         cell;
  231.     short            kind;
  232.     short            len;
  233.     int            length;
  234.     Handle        h;
  235.     Rect            r;
  236.     WindowPtr    win;
  237.     char            msg[50];
  238.     char            contents[256];
  239.     
  240.     SetPort(dlg);
  241.     switch (ev->what) {
  242.     case keyDown:
  243.         switch (ev->message & charCodeMask) {
  244.         case '\n':
  245.         case 3:
  246.             *item = pd_Done;
  247.             
  248.             return true;
  249.         case 8:
  250.             *item = pld_Remove;
  251.             
  252.             return true;
  253.         default:
  254.             break;
  255.         }
  256.     case mouseDown:
  257.         switch (FindWindow(ev->where, &win)) {
  258.         case inDrag:
  259.             if (win != dlg)
  260.                 return false;
  261.                 
  262.             r = qd.screenBits.bounds;
  263.             InsetRect(&r, 10, 10);
  264.             DragWindow(win, ev->where, &r);
  265.             
  266.             ev->what = nullEvent;
  267.             
  268.             return false;
  269.         case inSysWindow:
  270.             SystemClick(ev, win);
  271.             
  272.             ev->what = nullEvent;
  273.             
  274.             return false;
  275.         case inContent:
  276.             break;
  277.         default:
  278.             return false;
  279.         }
  280.         TextFont(0);
  281.         TextSize(12);
  282.         cell = ev->where;
  283.         GlobalToLocal(&cell);
  284.         GetDItem(dlg, pld_List, &kind, &h, &r);
  285.         if (PtInRect(cell, &r)) {
  286.             if (LClick(cell, ev->modifiers, PathList))
  287.                 for (SetPt(&cell, 0, 0); LGetSelect(true, &cell, PathList); ++cell.v) {
  288.                     len = 256;
  289.                     LGetCell(contents, &len, cell, PathList);
  290.                     contents[len] = 0;
  291.                     length = 256;
  292.                     getindstring(msg, PrefDialog, pd_ChangePath);
  293.                     if (!choose(AF_FILE, 0, msg, nil, CHOOSE_DEFAULT|CHOOSE_DIR, contents, &length))
  294.                         LSetCell((Ptr) contents, length, cell, PathList);
  295.                 } 
  296.             ev->what = nullEvent;
  297.         }
  298.         break;            
  299.     case activateEvt:
  300.         LActivate(ev->modifiers & activeFlag, PathList);
  301.         break;
  302.     case updateEvt:
  303.         if ((WindowPtr) ev->message != dlg) {
  304.             DoUpdate(DPtrFromWindowPtr((WindowPtr)ev->message));
  305.             
  306.             ev->what = nullEvent;
  307.         }
  308.         break;
  309.     }
  310.     
  311.     return false;
  312. }
  313.  
  314. static short PrefsLibDialog(DialogPtr prefs, short resFile)
  315. {
  316.     short            item;
  317.     short            kind;
  318.     short            len;
  319.     int            length;
  320.     Boolean        done;
  321.     Handle        h;
  322.     Handle        paths;
  323.     Point            cell;
  324.     Rect            bounds;
  325.     Rect            dbounds;
  326.     char            msg[50];
  327.     Str255        contents;
  328.  
  329.     UseResFile(gPrefsFile);
  330.     
  331.     paths         = Get1Resource('STR#', LibraryPaths);
  332.     PathCount    = **(short **)paths;
  333.  
  334.     UseResFile(resFile);
  335.     
  336. #ifndef RUNTIME
  337.     h    = GetResource('DITL', PrefDialog+PrefSubDialog);
  338.     AppendDITL(prefs, h, overlayDITL); 
  339. #else
  340.     Append_DITL(prefs, PrefDialog+PrefSubDialog);
  341. #endif
  342.  
  343.     GetDItem(prefs, pld_List, &kind, &h, &bounds);
  344.     SetDItem(prefs, pld_List, kind, (Handle) DrawPathList, &bounds);
  345.         
  346.     SetPt(&cell, bounds.right - bounds.left, 16);
  347.     SetRect(&dbounds, 0, 0, 1, PathCount);
  348.     PathList = LNew(&bounds, &dbounds, cell, 0, prefs, false, false, false, true);
  349.     
  350.     UseResFile(gPrefsFile);
  351.     SetPt(&cell, 0, 0);
  352.     for (; cell.v < PathCount; ++cell.v) {
  353.         GetIndString(contents, LibraryPaths, cell.v + 1);
  354.         LSetCell((Ptr)contents+1, contents[0], cell, PathList);
  355.     }
  356.     UseResFile(resFile);
  357.     
  358.     LDoDraw(true, PathList);
  359.     ShowWindow(prefs);
  360.         
  361.     for (done = false; !done; ) {
  362.         ModalDialog(PrefLibFilter, &item);
  363.         switch (item) {
  364.         case pd_Done:
  365.         case pd_ScriptIcon:
  366.         case pd_InputIcon:
  367.             done = true;
  368.             break;
  369.         case pld_Remove:
  370.             SetPt(&cell, 0, 0);
  371.             
  372.             if (LGetSelect(true, &cell, PathList) && Alert(PrefLibDelID, nil) == 1)
  373.                 do {
  374.                     LDelRow(1, cell.v, PathList);
  375.                         
  376.                     --PathCount;
  377.                 } while (LGetSelect(true, &cell, PathList));
  378.                 
  379.             break;
  380.         case pld_Add:
  381.             length = 256;
  382.             getindstring(msg, PrefDialog, pd_AddPath);
  383.             if (!choose(AF_FILE, 0, msg, nil, CHOOSE_DIR, contents, &length)) {
  384.                     SetPt(&cell, 0, PathCount);
  385.                     LAddRow(1, PathCount++, PathList);
  386.                     LSetCell(contents, length, cell, PathList);
  387.             }    
  388.             break;
  389.         }
  390.     }
  391.     
  392.     PtrToXHand(&PathCount, paths, sizeof(short));
  393.     SetPt(&cell, 0, 0);
  394.     for (; cell.v < PathCount; ++cell.v) {
  395.         len = 255;
  396.         LGetCell((Ptr) contents+1, &len, cell, PathList);
  397.         contents[0] = len;
  398.         
  399.         PtrAndHand(contents, paths, len+1);
  400.     }
  401.     
  402.     ChangedResource((Handle) paths);
  403.     WriteResource((Handle) paths);
  404.     
  405.     LDispose(PathList);
  406.  
  407. #ifndef RUNTIME
  408.     ShortenDITL(prefs, CountDITL(prefs) - pd_Outline);
  409. #else
  410.     Shorten_DITL(prefs, Count_DITL(prefs) - pd_Outline);
  411. #endif
  412.  
  413.     return item;
  414. }
  415.  
  416. pascal Boolean PrefScriptFilter(DialogPtr dlg, EventRecord * ev, short * item)
  417. {    
  418.     WindowPtr    win;
  419.     Rect            r;
  420.     
  421.     SetPort(dlg);
  422.     switch (ev->what) {
  423.     case keyDown:
  424.         switch (ev->message & charCodeMask) {
  425.         case '\n':
  426.         case 3:
  427.             *item = pd_Done;
  428.             
  429.             return true;
  430.         default:
  431.             break;
  432.         }
  433.     case mouseDown:
  434.         switch (FindWindow(ev->where, &win)) {
  435.         case inDrag:
  436.             if (win != dlg)
  437.                 return false;
  438.                 
  439.             r = qd.screenBits.bounds;
  440.             InsetRect(&r, 10, 10);
  441.             DragWindow(win, ev->where, &r);
  442.             
  443.             ev->what = nullEvent;
  444.             
  445.             return false;
  446.         case inSysWindow:
  447.             SystemClick(ev, win);
  448.             
  449.             ev->what = nullEvent;
  450.             
  451.             return false;
  452.         default:
  453.             return false;
  454.         }
  455.     case updateEvt:
  456.         if ((WindowPtr) ev->message != dlg) {
  457.             DoUpdate(DPtrFromWindowPtr((WindowPtr)ev->message));
  458.             
  459.             ev->what = nullEvent;
  460.         }
  461.         break;
  462.     }
  463.     
  464.     return false;
  465. }
  466.  
  467. static short PrefsScriptDialog(DialogPtr prefs, short resFile)
  468. {
  469.     short            item;
  470.     short            kind;
  471.     Boolean        done;
  472.     Handle        h;
  473.     Handle        pref;
  474.     Rect            bounds;
  475.     
  476. #ifndef RUNTIME
  477.     h    = GetResource('DITL', PrefDialog+PrefSubDialog);
  478.     AppendDITL(prefs, h, overlayDITL); 
  479. #else
  480.     Append_DITL(prefs, PrefDialog+PrefSubDialog);
  481. #endif
  482.     
  483.     GetDItem(prefs, psd_Edit, &kind, &h, &bounds);
  484.     SetControlValue((ControlHandle) h, !gPerlPrefs.runFinderOpens);
  485.     GetDItem(prefs, psd_Run, &kind, &h, &bounds);
  486.     SetControlValue((ControlHandle) h, gPerlPrefs.runFinderOpens);
  487.     GetDItem(prefs, psd_Check, &kind, &h, &bounds);
  488.     SetControlValue((ControlHandle) h, gPerlPrefs.checkType);
  489.             
  490.     for (done = false; !done; ) {
  491.         ModalDialog(PrefScriptFilter, &item);
  492.         switch (item) {
  493.         case pd_Done:
  494.         case pd_LibIcon:
  495.         case pd_InputIcon:
  496.             done = true;
  497.             break;
  498.         case psd_Edit:
  499.         case psd_Run:
  500.             gPerlPrefs.runFinderOpens = item == psd_Run;
  501.             GetDItem(prefs, psd_Edit, &kind, &h, &bounds);
  502.             SetControlValue((ControlHandle) h, !gPerlPrefs.runFinderOpens);
  503.             GetDItem(prefs, psd_Run, &kind, &h, &bounds);
  504.             SetControlValue((ControlHandle) h, gPerlPrefs.runFinderOpens);
  505.             break;
  506.         case psd_Check:
  507.             gPerlPrefs.checkType = !gPerlPrefs.checkType;
  508.             GetDItem(prefs, psd_Check, &kind, &h, &bounds);
  509.             SetControlValue((ControlHandle) h, gPerlPrefs.checkType);
  510.             break;
  511.         }
  512.     }
  513.  
  514.     UseResFile(gPrefsFile);
  515.     if (pref = Get1Resource('PPRF', 128)) {
  516.         PtrToXHand((Ptr) &gPerlPrefs, pref, sizeof(PerlPrefs));
  517.         ChangedResource((Handle) pref);
  518.         WriteResource((Handle) pref);
  519.     }
  520.     UseResFile(resFile);
  521.  
  522. #ifndef RUNTIME
  523.     ShortenDITL(prefs, CountDITL(prefs) - pd_Outline);
  524. #else
  525.     Shorten_DITL(prefs, Count_DITL(prefs) - pd_Outline);
  526. #endif
  527.  
  528.     return item;
  529. }
  530.  
  531. pascal Boolean PrefInputFilter(DialogPtr dlg, EventRecord * ev, short * item)
  532. {    
  533.     WindowPtr    win;
  534.     Rect            r;
  535.     
  536.     SetPort(dlg);
  537.     switch (ev->what) {
  538.     case keyDown:
  539.         switch (ev->message & charCodeMask) {
  540.         case '\n':
  541.         case 3:
  542.             *item = pd_Done;
  543.             
  544.             return true;
  545.         default:
  546.             break;
  547.         }
  548.     case mouseDown:
  549.         switch (FindWindow(ev->where, &win)) {
  550.         case inDrag:
  551.             if (win != dlg)
  552.                 return false;
  553.                 
  554.             r = qd.screenBits.bounds;
  555.             InsetRect(&r, 10, 10);
  556.             DragWindow(win, ev->where, &r);
  557.             
  558.             ev->what = nullEvent;
  559.             
  560.             return false;
  561.         case inSysWindow:
  562.             SystemClick(ev, win);
  563.             
  564.             ev->what = nullEvent;
  565.             
  566.             return false;
  567.         default:
  568.             return false;
  569.         }
  570.     case updateEvt:
  571.         if ((WindowPtr) ev->message != dlg) {
  572.             DoUpdate(DPtrFromWindowPtr((WindowPtr)ev->message));
  573.             
  574.             ev->what = nullEvent;
  575.         }
  576.         break;
  577.     }
  578.     
  579.     return false;
  580. }
  581.  
  582. static short PrefsInputDialog(DialogPtr prefs, short resFile)
  583. {
  584.     short            item;
  585.     short            kind;
  586.     Boolean        done;
  587.     Handle        h;
  588.     Handle        pref;
  589.     Rect            bounds;
  590.     
  591. #ifndef RUNTIME
  592.     h    = GetResource('DITL', PrefDialog+PrefSubDialog);
  593.     AppendDITL(prefs, h, overlayDITL); 
  594. #else
  595.     Append_DITL(prefs, PrefDialog+PrefSubDialog);
  596. #endif
  597.     
  598.     GetDItem(prefs, pid_Inline, &kind, &h, &bounds);
  599.     SetControlValue((ControlHandle) h, gPerlPrefs.inlineInput);
  600.             
  601.     for (done = false; !done; ) {
  602.         ModalDialog(PrefInputFilter, &item);
  603.         switch (item) {
  604.         case pd_Done:
  605.         case pd_LibIcon:
  606.         case pd_ScriptIcon:
  607.             done = true;
  608.             break;
  609.         case pid_Inline:
  610.             gPerlPrefs.inlineInput = !gPerlPrefs.inlineInput;
  611.             GetDItem(prefs, pid_Inline, &kind, &h, &bounds);
  612.             SetControlValue((ControlHandle) h, gPerlPrefs.inlineInput);
  613.             break;
  614.         }
  615.     }
  616.  
  617.     UseResFile(gPrefsFile);
  618.     if (pref = Get1Resource('PPRF', 128)) {
  619.         PtrToXHand((Ptr) &gPerlPrefs, pref, sizeof(PerlPrefs));
  620.         ChangedResource((Handle) pref);
  621.         WriteResource((Handle) pref);
  622.     }
  623.     UseResFile(resFile);
  624.     
  625. #ifndef RUNTIME
  626.     if (gTSMTEImplemented)
  627.         UseInlineInput(gPerlPrefs.inlineInput);
  628.  
  629.     ShortenDITL(prefs, CountDITL(prefs) - pd_Outline);
  630. #else
  631.     Shorten_DITL(prefs, Count_DITL(prefs) - pd_Outline);
  632. #endif
  633.  
  634.     return item;
  635. }
  636.  
  637. pascal void DoPrefDialog()
  638. {
  639.     short            resFile;
  640.     short            kind;
  641.     Handle        h;
  642.     DialogPtr    prefs;
  643.     Rect            bounds;
  644.     
  645.     resFile        = CurResFile();
  646.  
  647.     prefs = GetNewDialog(PrefDialog, nil, (WindowPtr) -1);
  648.  
  649.     GetDItem(prefs, pd_LibIcon, &kind, &h, &bounds);
  650.     SetDItem(prefs, pd_LibIcon, kind, (Handle) DrawPrefIcon, &bounds);
  651.  
  652.     GetDItem(prefs, pd_ScriptIcon, &kind, &h, &bounds);
  653.     SetDItem(prefs, pd_ScriptIcon, kind, (Handle) DrawPrefIcon, &bounds);
  654.  
  655.     GetDItem(prefs, pd_InputIcon, &kind, &h, &bounds);
  656.     SetDItem(prefs, pd_InputIcon, kind, (Handle) DrawPrefIcon, &bounds);
  657.  
  658.     GetDItem(prefs, pd_Boundary, &kind, &h, &bounds);
  659.     SetDItem(prefs, pd_Boundary, kind, (Handle) Separator, &bounds);
  660.  
  661.     AdornDefaultButton(prefs, pd_Outline);
  662.  
  663.     ShowWindow(prefs);
  664.  
  665.     PrefSubDialog = pd_LibIcon;
  666.     PrefSubDialog = PrefsLibDialog(prefs, resFile);
  667.     
  668.     while (PrefSubDialog != pd_Done) {
  669.         SetPort(prefs);
  670.         InvalRect(&prefs->portRect);
  671.         EraseRect(&prefs->portRect);
  672.         switch (PrefSubDialog) {
  673.         case pd_LibIcon:
  674.             PrefSubDialog = PrefsLibDialog(prefs, resFile);
  675.             break;
  676.         case pd_ScriptIcon:
  677.             PrefSubDialog = PrefsScriptDialog(prefs, resFile);
  678.             break;
  679.         case pd_InputIcon:
  680.             PrefSubDialog = PrefsInputDialog(prefs, resFile);
  681.             break;
  682.         }
  683.     }
  684.         
  685.     UpdateResFile(gPrefsFile);
  686.  
  687.     DisposeDialog(prefs);
  688. }
  689.  
  690. static ListHandle FontList;
  691. static ListHandle    SizeList;
  692.  
  693. pascal void DrawFontList(DialogPtr dlg, short item)
  694. {
  695. #pragma unused(item)
  696.     Rect    r;
  697.     
  698.     TextFont(0);
  699.     TextSize(12);
  700.     LUpdate(dlg->visRgn, FontList);
  701.     r = (*FontList)->rView;
  702.     InsetRect(&r, -1, -1);
  703.     FrameRect(&r);
  704. }
  705.  
  706. pascal void DrawSizeList(DialogPtr dlg, short item)
  707. {
  708. #pragma unused(item)
  709.     Rect    r;
  710.     
  711.     TextFont(0);
  712.     TextSize(12);
  713.     LUpdate(dlg->visRgn, SizeList);
  714.     r = (*SizeList)->rView;
  715.     InsetRect(&r, -1, -1);
  716.     FrameRect(&r);
  717. }
  718.  
  719. static short SizeChoice[] = 
  720. {
  721.     9,
  722.     10,
  723.     12,
  724.     14,
  725.     18,
  726.     24
  727. };
  728.  
  729. const short    SizeChoiceCount = 6;
  730.  
  731. pascal Boolean FormatFilter(DialogPtr dlg, EventRecord * ev, short * item)
  732. {    
  733.     WindowPtr    win;
  734.     Rect            r;
  735.     
  736.     SetPort(dlg);
  737.     switch (ev->what) {
  738.     case keyDown:
  739.         switch (ev->message & charCodeMask) {
  740.         case '\n':
  741.         case 3:
  742.             *item = fd_OK;
  743.             
  744.             return true;
  745.         case '.':
  746.             if (!(ev->modifiers & cmdKey))
  747.                 break;
  748.         case 27:
  749.             *item = fd_Cancel;
  750.             
  751.             return true;
  752.         default:
  753.             break;
  754.         }
  755.     case mouseDown:
  756.         switch (FindWindow(ev->where, &win)) {
  757.         case inDrag:
  758.             if (win != dlg)
  759.                 return false;
  760.                 
  761.             r = qd.screenBits.bounds;
  762.             InsetRect(&r, 10, 10);
  763.             DragWindow(win, ev->where, &r);
  764.             
  765.             ev->what = nullEvent;
  766.             break;
  767.         case inSysWindow:
  768.             SystemClick(ev, win);
  769.             
  770.             ev->what = nullEvent;
  771.             break;
  772.         }
  773.         return false;
  774.     case activateEvt:
  775.         LActivate(ev->modifiers & activeFlag, FontList);
  776.         LActivate(ev->modifiers & activeFlag, SizeList);
  777.         break;
  778.     case updateEvt:
  779.         if ((WindowPtr) ev->message != dlg) {
  780.             DoUpdate(DPtrFromWindowPtr((WindowPtr)ev->message));
  781.             
  782.             ev->what = nullEvent;
  783.         }
  784.         break;
  785.     }
  786.     
  787.     return false;
  788. }
  789.  
  790. short FontCellHeight(MenuHandle fonts, GrafPtr dlg)
  791. {
  792.     short        oldFont;
  793.     short        oldSize;
  794.     short        index;
  795.     short        fontNum;
  796.     short        scriptNum;
  797.     short        minHeight;
  798.     long        scriptsDone;
  799.     long        sysFont;
  800.     FontInfo    fontInfo;
  801.     Str255    contents;
  802.     
  803.     if (GetSMVariable(smEnabled) < 2)            /* Roman Script Only    */
  804.         return 16;                    /* Ascent + Descent + Leading for Chicago 12 */
  805.     
  806.     SetPort(dlg);
  807.     oldFont         = dlg->txFont;
  808.     oldSize         = dlg->txSize;
  809.     minHeight    = 16;
  810.     scriptsDone    = 0;
  811.     
  812.     for (index=0; index++ < CountMItems(fonts); ) {
  813.         GetItem(fonts, index, contents);
  814.         GetFNum(contents, &fontNum);
  815.         scriptNum = FontToScript(fontNum);
  816.         
  817.         if (scriptNum == smUninterp)
  818.             scriptNum = smRoman;
  819.         /* No point measuring a script more than once */
  820.         if (scriptNum < 32 && (scriptsDone & (1 << scriptNum)))
  821.             continue;
  822.         scriptsDone |= 1 << scriptNum;
  823. #ifndef RUNTIME
  824.         sysFont = GetScriptVariable(scriptNum, smScriptSysFondSize);
  825.         TextFont(sysFont >> 16);
  826.         TextSize(sysFont & 0xFFFF);
  827. #else
  828.         TextFont(GetScriptVariable(scriptNum, smScriptSysFond));
  829.         TextSize(12);
  830. #endif
  831.         GetFontInfo(&fontInfo);
  832.         if (fontInfo.ascent + fontInfo.descent + fontInfo.leading > minHeight)
  833.             minHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
  834.     }
  835.     
  836.     TextFont(oldFont);
  837.     TextSize(oldSize);
  838.     return minHeight;
  839. }
  840.  
  841. pascal void FontLDEF(
  842.     short         message, 
  843.     Boolean         selected, 
  844.     Rect *         cellRect,
  845.     Point            cell,
  846.     short            dataOffset,
  847.     short            dataLen,
  848.     ListHandle    list)
  849. {
  850. #pragma unused(dataOffset)
  851.     short        oldFont;
  852.     short        oldSize;
  853.     short        fontNum;
  854.     short        scriptNum;
  855.     long        result;
  856.     long        sysFont;
  857.     FontInfo    fontInfo;
  858.     Str255    contents;
  859.     
  860.     switch (message) {
  861.     case lInitMsg:
  862.         if (Gestalt(gestaltQuickdrawVersion, &result) || !result) /* B & W QD */
  863.             (*list)->refCon = 0;
  864.         else
  865.             (*list)->refCon = 1;
  866.     case lDrawMsg:
  867.         SetPort((*list)->port);
  868.         oldFont         = (*list)->port->txFont;
  869.         oldSize         = (*list)->port->txSize;
  870.         LGetCell(contents, &dataLen, cell, list);
  871.         GetFNum(contents, &fontNum);
  872.         scriptNum = FontToScript(fontNum);
  873.             
  874.         if (scriptNum == smUninterp)
  875.             scriptNum = smRoman;
  876.     #ifndef RUNTIME
  877.         sysFont = GetScriptVariable(scriptNum, smScriptSysFondSize);
  878.         TextFont(sysFont >> 16);
  879.         TextSize(sysFont & 0xFFFF);
  880.     #else
  881.         TextFont(GetScriptVariable(scriptNum, smScriptSysFond));
  882.         TextSize(12);
  883.     #endif
  884.         GetFontInfo(&fontInfo);
  885.         MoveTo(cellRect->left+5, cellRect->top + fontInfo.ascent);
  886.         DrawString(contents);
  887.         
  888.         TextFont(oldFont);
  889.         TextSize(oldSize);
  890.         
  891.         if (!selected)
  892.             break;
  893.         
  894.         /* Else fall through to select */
  895.     case lHiliteMsg:
  896.         if ((*list)->refCon)
  897.             BitClr((Ptr) HiliteMode, pHiliteBit);
  898.         InvertRect(cellRect);
  899.         break;
  900.     default:
  901.         break;
  902.     }
  903. }
  904.  
  905. short FontLDEFID()
  906. {
  907.     if (GetSMVariable(smEnabled) < 2)            /* Roman Script Only    */
  908.         return 0;
  909.     else 
  910.         return 128;
  911. }
  912.  
  913. pascal Boolean DoFormatDialog(DocFormat * form, Boolean * defaultFormat)
  914. {
  915.     short            item;
  916.     short            kind;
  917.     short         digit;
  918.     Boolean        done;
  919.     Handle        h;
  920.     DialogPtr    format;
  921.     Point            cell;
  922.     Rect            bounds;
  923.     Rect            dbounds;
  924.     Str255        contents;
  925.     MenuHandle    fonts;
  926.     
  927.     format = GetNewDialog(FormatDialog, nil, (WindowPtr) -1);
  928.  
  929.     GetDItem(format, fd_Separator, &kind, &h, &bounds);
  930.     SetDItem(format, fd_Separator, kind, (Handle) Separator, &bounds);
  931.  
  932.     GetDItem(format, fd_FontList, &kind, &h, &bounds);
  933.     SetDItem(format, fd_FontList, kind, (Handle) DrawFontList, &bounds);
  934.         
  935.     fonts = NewMenu(FormatDialog, "\pFonts");
  936.     AppendResMenu(fonts, 'FONT');
  937.  
  938.     bounds.right -= 16;
  939.     SetPt(&cell, bounds.right - bounds.left, FontCellHeight(fonts, format));
  940.     SetRect(&dbounds, 0, 0, 1, CountMItems(fonts));
  941.     FontList = LNew(&bounds, &dbounds, cell, item = FontLDEFID(), format, false, false, false, true);
  942.     
  943.     SetPt(&cell, 0, 0);
  944.     for (; cell.v < CountMItems(fonts); ++cell.v) {
  945.         GetItem(fonts, cell.v+1, contents);
  946.         if (item)
  947.             LSetCell((Ptr)contents, contents[0]+1, cell, FontList);
  948.         else
  949.             LSetCell((Ptr)contents+1, contents[0], cell, FontList);
  950.         GetFNum(contents, &kind);
  951.         LSetSelect(form->font == kind, cell, FontList);
  952.     }
  953.     LAutoScroll(FontList);
  954.     
  955.     GetDItem(format, fd_SizeList, &kind, &h, &bounds);
  956.     SetDItem(format, fd_SizeList, kind, (Handle) DrawSizeList, &bounds);
  957.  
  958.     bounds.right -= 16;
  959.     SetPt(&cell, bounds.right - bounds.left, 16);
  960.     SetRect(&dbounds, 0, 0, 1, SizeChoiceCount);
  961.     SizeList = LNew(&bounds, &dbounds, cell, 0, format, false, false, false, true);
  962.     
  963.     SetPt(&cell, 0, 0);
  964.     for (; cell.v < SizeChoiceCount; ++cell.v) {
  965.         sprintf((char *) contents, "%d", SizeChoice[cell.v]);
  966.         LSetCell((Ptr)contents, strlen((Ptr) contents), cell, SizeList);
  967.         LSetSelect(form->size == SizeChoice[cell.v], cell, SizeList);
  968.     }
  969.     
  970.     AdornDefaultButton(format, fd_Outline);
  971.  
  972.     LDoDraw(true, FontList);
  973.     LDoDraw(true, SizeList);
  974.     
  975.     sprintf((char *) contents+1, "%d", form->size);
  976.     contents[0] = strlen((Ptr) contents+1);
  977.     SetText(format, fd_SizeEdit, contents);
  978.     SelIText(format, fd_SizeEdit, 0, 32767);
  979.  
  980.     if (*defaultFormat) {
  981.         GetDItem(format, fd_MakeDefault, &kind, &h, &bounds);
  982.         SetControlValue((ControlHandle) h, 1);
  983.         HiliteControl((ControlHandle) h, 254);
  984.     }
  985.     
  986.     ShowWindow(format);
  987.         
  988.     for (done = false; !done; ) {
  989.         ModalDialog(FormatFilter, &item);
  990.         
  991.         switch (item) {
  992.         case fd_OK:
  993.             RetrieveText(format, fd_SizeEdit, contents);
  994.             if (contents[0]) {
  995.                 for (digit = 0, kind = 0; digit++ < contents[0]; )
  996.                     if (isdigit(contents[digit]))
  997.                         kind = kind * 10 + contents[digit] - '0';
  998.                     else {
  999.                         kind = 0;
  1000.                         
  1001.                         break;
  1002.                     }
  1003.                 
  1004.                 if (kind) {
  1005.                     form->size = kind;
  1006.                     SetPt(&cell, 0, 0);
  1007.                     LGetSelect(true, &cell, FontList);
  1008.                     GetItem(fonts, cell.v+1, contents);
  1009.                     GetFNum(contents, &kind);
  1010.                     form->font = kind;
  1011.                     
  1012.                     done = true;
  1013.                     break;
  1014.                 }
  1015.             }
  1016.             
  1017.             SelIText(format, fd_SizeEdit, 0, 32767);
  1018.             SysBeep(0);
  1019.             
  1020.             item = 0;
  1021.             break;
  1022.         case fd_Cancel:
  1023.             done = true;
  1024.             *defaultFormat = false;
  1025.             break;
  1026.         case fd_FontList:
  1027.             GetMouse(&cell);
  1028.             LClick(cell, 0, FontList);
  1029.             break;
  1030.         case fd_SizeList:
  1031.             GetMouse(&cell);
  1032.             LClick(cell, 0, SizeList);
  1033.             SetPt(&cell, 0, 0);
  1034.             if (LGetSelect(true, &cell, SizeList)) {
  1035.                 sprintf((char *) contents+1, "%d", SizeChoice[cell.v]);
  1036.                 contents[0] = strlen((Ptr) contents+1);
  1037.                 SetText(format, fd_SizeEdit, contents);
  1038.                 SelIText(format, fd_SizeEdit, 0, 32767);
  1039.             }
  1040.             break;
  1041.         case fd_MakeDefault:
  1042.             GetDItem(format, fd_MakeDefault, &kind, &h, &bounds);
  1043.             SetControlValue((ControlHandle) h, *defaultFormat = !*defaultFormat);
  1044.             break;
  1045.         }
  1046.     }
  1047.     
  1048.     LDispose(FontList);
  1049.     LDispose(SizeList);
  1050.     DisposeDialog(format);
  1051.     DisposeMenu(fonts);
  1052.     
  1053.     return (item == fd_OK);
  1054. }
  1055.