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