home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacPerl 5.0.3 / MacPerl Source ƒ / MacPerl5 / MPPreferences.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-14  |  23.1 KB  |  1,050 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.             done = true;
  384.             break;
  385.         case pld_Remove:
  386.             SetPt(&cell, 0, 0);
  387.             
  388.             if (LGetSelect(true, &cell, PathList) && Alert(PrefLibDelID, nil) == 1)
  389.                 do {
  390.                     LDelRow(1, cell.v, PathList);
  391.                         
  392.                     --PathCount;
  393.                 } while (LGetSelect(true, &cell, PathList));
  394.                 
  395.             break;
  396.         case pld_Add:
  397.             length = 256;
  398.             getindstring(msg, PrefDialog, pd_AddPath);
  399.             if (!choose(AF_FILE, 0, msg, nil, CHOOSE_DIR, contents, &length)) {
  400.                     SetPt(&cell, 0, PathCount);
  401.                     LAddRow(1, PathCount++, PathList);
  402.                     LSetCell(contents, length, cell, PathList);
  403.             }    
  404.             break;
  405.         }
  406.     }
  407.     
  408.     PtrToXHand(&PathCount, paths, sizeof(short));
  409.     SetPt(&cell, 0, 0);
  410.     
  411.     {
  412.         FSSpec    homedir;
  413.         FSSpec    item;
  414.         char *    shortpath;
  415.         
  416.         homedir.vRefNum    =     gAppVol;
  417.         homedir.parID    =    gAppDir;
  418.         
  419.         FSpUp(&homedir);
  420.         
  421.         for (; cell.v < PathCount; ++cell.v) {
  422.             len = 255;
  423.             LGetCell((Ptr) contents+1, &len, cell, PathList);
  424.             contents[0]      = len;
  425.             contents[len+1] = 0;
  426.             if (!Path2FSSpec((char *)contents+1, &item)) {
  427.                 shortpath = FSp2DirRelPath(&item, &homedir);
  428.                 if (!strchr(shortpath, ':')) {
  429.                     memcpy(contents+2, shortpath, *contents = strlen(shortpath));
  430.                     ++*contents;
  431.                     contents[1] = ':';
  432.                 } else
  433.                     memcpy(contents+1, shortpath, *contents = strlen(shortpath));
  434.             }
  435.         
  436.             PtrAndHand(contents, paths, *contents+1);
  437.         }
  438.     }
  439.     
  440.     ChangedResource((Handle) paths);
  441.     WriteResource((Handle) paths);
  442.     
  443.     LDispose(PathList);
  444.  
  445.     ShortenDITL(prefs, CountDITL(prefs) - pd_Outline);
  446.  
  447.     return item;
  448. }
  449.  
  450. pascal Boolean PrefScriptFilter(DialogPtr dlg, EventRecord * ev, short * item)
  451. {    
  452.     WindowPtr    win;
  453.     Rect            r;
  454.     
  455.     SetPort(dlg);
  456.     switch (ev->what) {
  457.     case keyDown:
  458.         switch (ev->message & charCodeMask) {
  459.         case '\n':
  460.         case 3:
  461.             *item = pd_Done;
  462.             
  463.             return true;
  464.         default:
  465.             break;
  466.         }
  467.     case mouseDown:
  468.         switch (FindWindow(ev->where, &win)) {
  469.         case inDrag:
  470.             if (win != dlg)
  471.                 return false;
  472.                 
  473.             r = qd.screenBits.bounds;
  474.             InsetRect(&r, 10, 10);
  475.             DragWindow(win, ev->where, &r);
  476.             
  477.             ev->what = nullEvent;
  478.             
  479.             return false;
  480.         case inSysWindow:
  481.             SystemClick(ev, win);
  482.             
  483.             ev->what = nullEvent;
  484.             
  485.             return false;
  486.         default:
  487.             return false;
  488.         }
  489.     case updateEvt:
  490.         win = (WindowPtr) ev->message;
  491.         if (win != dlg) {
  492.             DoUpdate(DPtrFromWindowPtr(win), win);
  493.             
  494.             ev->what = nullEvent;
  495.         }
  496.         break;
  497.     }
  498.     
  499.     return false;
  500. }
  501.  
  502. #if USESROUTINEDESCRIPTORS
  503. RoutineDescriptor    uPrefScriptFilter = 
  504.         BUILD_ROUTINE_DESCRIPTOR(uppModalFilterProcInfo, PrefScriptFilter);
  505. #else
  506. #define uPrefScriptFilter *(ModalFilterUPP)&PrefScriptFilter
  507. #endif
  508.  
  509. static short PrefsScriptDialog(DialogPtr prefs, short resFile)
  510. {
  511.     short            item;
  512.     short            kind;
  513.     Boolean        done;
  514.     Handle        h;
  515.     Handle        pref;
  516.     Rect            bounds;
  517.     
  518.     h    = GetResource('DITL', PrefDialog+PrefSubDialog);
  519.     AppendDITL(prefs, h, overlayDITL); 
  520.     
  521.     GetDItem(prefs, psd_Edit, &kind, &h, &bounds);
  522.     SetControlValue((ControlHandle) h, !gPerlPrefs.runFinderOpens);
  523.     GetDItem(prefs, psd_Run, &kind, &h, &bounds);
  524.     SetControlValue((ControlHandle) h, gPerlPrefs.runFinderOpens);
  525.     GetDItem(prefs, psd_Check, &kind, &h, &bounds);
  526.     SetControlValue((ControlHandle) h, gPerlPrefs.checkType);
  527.     HMSetDialogResID(PrefDialog+PrefSubDialog);
  528.             
  529.     for (done = false; !done; ) {
  530.         ModalDialog(&uPrefScriptFilter, &item);
  531.         switch (item) {
  532.         case pd_Done:
  533.         case pd_LibIcon:
  534.         case pd_InputIcon:
  535.             done = true;
  536.             break;
  537.         case psd_Edit:
  538.         case psd_Run:
  539.             gPerlPrefs.runFinderOpens = item == psd_Run;
  540.             GetDItem(prefs, psd_Edit, &kind, &h, &bounds);
  541.             SetControlValue((ControlHandle) h, !gPerlPrefs.runFinderOpens);
  542.             GetDItem(prefs, psd_Run, &kind, &h, &bounds);
  543.             SetControlValue((ControlHandle) h, gPerlPrefs.runFinderOpens);
  544.             break;
  545.         case psd_Check:
  546.             gPerlPrefs.checkType = !gPerlPrefs.checkType;
  547.             GetDItem(prefs, psd_Check, &kind, &h, &bounds);
  548.             SetControlValue((ControlHandle) h, gPerlPrefs.checkType);
  549.             break;
  550.         }
  551.     }
  552.  
  553.     UseResFile(gPrefsFile);
  554.     if (pref = Get1Resource('PPRF', 128)) {
  555.         PtrToXHand((Ptr) &gPerlPrefs, pref, sizeof(PerlPrefs));
  556.         ChangedResource((Handle) pref);
  557.         WriteResource((Handle) pref);
  558.     }
  559.     UseResFile(resFile);
  560.  
  561.     ShortenDITL(prefs, CountDITL(prefs) - pd_Outline);
  562.  
  563.     return item;
  564. }
  565.  
  566. pascal Boolean PrefInputFilter(DialogPtr dlg, EventRecord * ev, short * item)
  567. {    
  568.     WindowPtr    win;
  569.     Rect            r;
  570.     
  571.     SetPort(dlg);
  572.     switch (ev->what) {
  573.     case keyDown:
  574.         switch (ev->message & charCodeMask) {
  575.         case '\n':
  576.         case 3:
  577.             *item = pd_Done;
  578.             
  579.             return true;
  580.         default:
  581.             break;
  582.         }
  583.     case mouseDown:
  584.         switch (FindWindow(ev->where, &win)) {
  585.         case inDrag:
  586.             if (win != dlg)
  587.                 return false;
  588.                 
  589.             r = qd.screenBits.bounds;
  590.             InsetRect(&r, 10, 10);
  591.             DragWindow(win, ev->where, &r);
  592.             
  593.             ev->what = nullEvent;
  594.             
  595.             return false;
  596.         case inSysWindow:
  597.             SystemClick(ev, win);
  598.             
  599.             ev->what = nullEvent;
  600.             
  601.             return false;
  602.         default:
  603.             return false;
  604.         }
  605.     case updateEvt:
  606.         win = (WindowPtr) ev->message;
  607.         if (win != dlg) {
  608.             DoUpdate(DPtrFromWindowPtr(win), win);
  609.             
  610.             ev->what = nullEvent;
  611.         }
  612.         break;
  613.     }
  614.     
  615.     return false;
  616. }
  617.  
  618. #if USESROUTINEDESCRIPTORS
  619. RoutineDescriptor    uPrefInputFilter = 
  620.         BUILD_ROUTINE_DESCRIPTOR(uppModalFilterProcInfo, PrefInputFilter);
  621. #else
  622. #define uPrefInputFilter *(ModalFilterUPP)&PrefInputFilter
  623. #endif
  624.  
  625. static short PrefsInputDialog(DialogPtr prefs, short resFile)
  626. {
  627.     short            item;
  628.     short            kind;
  629.     Boolean        done;
  630.     Handle        h;
  631.     Handle        pref;
  632.     Rect            bounds;
  633.     
  634.     h    = GetResource('DITL', PrefDialog+PrefSubDialog);
  635.     AppendDITL(prefs, h, overlayDITL); 
  636.     
  637.     GetDItem(prefs, pid_Inline, &kind, &h, &bounds);
  638.     SetControlValue((ControlHandle) h, gPerlPrefs.inlineInput);
  639.     HMSetDialogResID(PrefDialog+PrefSubDialog);
  640.             
  641.     for (done = false; !done; ) {
  642.         ModalDialog(&uPrefInputFilter, &item);
  643.         switch (item) {
  644.         case pd_Done:
  645.         case pd_LibIcon:
  646.         case pd_ScriptIcon:
  647.             done = true;
  648.             break;
  649.         case pid_Inline:
  650.             gPerlPrefs.inlineInput = !gPerlPrefs.inlineInput;
  651.             GetDItem(prefs, pid_Inline, &kind, &h, &bounds);
  652.             SetControlValue((ControlHandle) h, gPerlPrefs.inlineInput);
  653.             break;
  654.         }
  655.     }
  656.  
  657.     UseResFile(gPrefsFile);
  658.     if (pref = Get1Resource('PPRF', 128)) {
  659.         PtrToXHand((Ptr) &gPerlPrefs, pref, sizeof(PerlPrefs));
  660.         ChangedResource((Handle) pref);
  661.         WriteResource((Handle) pref);
  662.     }
  663.     UseResFile(resFile);
  664.     
  665.     if (gTSMTEImplemented)
  666.         UseInlineInput(gPerlPrefs.inlineInput);
  667.  
  668.     ShortenDITL(prefs, CountDITL(prefs) - pd_Outline);
  669.  
  670.     return item;
  671. }
  672.  
  673. pascal void DoPrefDialog()
  674. {
  675.     short            resFile;
  676.     short            kind;
  677.     Handle        h;
  678.     DialogPtr    prefs;
  679.     Rect            bounds;
  680.     
  681.     resFile        = CurResFile();
  682.  
  683.     prefs = GetNewDialog(PrefDialog, nil, (WindowPtr) -1);
  684.  
  685.     GetDItem(prefs, pd_LibIcon, &kind, &h, &bounds);
  686.     SetDItem(prefs, pd_LibIcon, kind, (Handle) &uDrawPrefIcon, &bounds);
  687.  
  688.     GetDItem(prefs, pd_ScriptIcon, &kind, &h, &bounds);
  689.     SetDItem(prefs, pd_ScriptIcon, kind, (Handle) &uDrawPrefIcon, &bounds);
  690.  
  691.     GetDItem(prefs, pd_InputIcon, &kind, &h, &bounds);
  692.     SetDItem(prefs, pd_InputIcon, kind, (Handle) &uDrawPrefIcon, &bounds);
  693.  
  694.     GetDItem(prefs, pd_Boundary, &kind, &h, &bounds);
  695.     SetDItem(prefs, pd_Boundary, kind, (Handle) &uSeparator, &bounds);
  696.  
  697.     AdornDefaultButton(prefs, pd_Outline);
  698.  
  699.     ShowWindow(prefs);
  700.  
  701.     PrefSubDialog = pd_LibIcon;
  702.     PrefSubDialog = PrefsLibDialog(prefs, resFile);
  703.     
  704.     while (PrefSubDialog != pd_Done) {
  705.         SetPort(prefs);
  706.         InvalRect(&prefs->portRect);
  707.         EraseRect(&prefs->portRect);
  708.         switch (PrefSubDialog) {
  709.         case pd_LibIcon:
  710.             PrefSubDialog = PrefsLibDialog(prefs, resFile);
  711.             break;
  712.         case pd_ScriptIcon:
  713.             PrefSubDialog = PrefsScriptDialog(prefs, resFile);
  714.             break;
  715.         case pd_InputIcon:
  716.             PrefSubDialog = PrefsInputDialog(prefs, resFile);
  717.             break;
  718.         }
  719.     }
  720.         
  721.     UpdateResFile(gPrefsFile);
  722.  
  723.     DisposeDialog(prefs);
  724.  
  725.     HMSetDialogResID(-1);
  726. }
  727.  
  728. static ListHandle FontList;
  729. static ListHandle    SizeList;
  730.  
  731. pascal void DrawFontList(DialogPtr dlg, short item)
  732. {
  733. #if !defined(powerc) && !defined(__powerc)
  734. #pragma unused(item)
  735. #endif
  736.     Rect    r;
  737.     
  738.     TextFont(0);
  739.     TextSize(12);
  740.     LUpdate(dlg->visRgn, FontList);
  741.     r = (*FontList)->rView;
  742.     InsetRect(&r, -1, -1);
  743.     FrameRect(&r);
  744. }
  745.  
  746. #if USESROUTINEDESCRIPTORS
  747. RoutineDescriptor    uDrawFontList = 
  748.         BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawFontList);
  749. #else
  750. #define uDrawFontList *(UserItemUPP)&DrawFontList
  751. #endif
  752.  
  753. pascal void DrawSizeList(DialogPtr dlg, short item)
  754. {
  755. #if !defined(powerc) && !defined(__powerc)
  756. #pragma unused(item)
  757. #endif
  758.     Rect    r;
  759.     
  760.     TextFont(0);
  761.     TextSize(12);
  762.     LUpdate(dlg->visRgn, SizeList);
  763.     r = (*SizeList)->rView;
  764.     InsetRect(&r, -1, -1);
  765.     FrameRect(&r);
  766. }
  767.  
  768. #if USESROUTINEDESCRIPTORS
  769. RoutineDescriptor    uDrawSizeList = 
  770.         BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawSizeList);
  771. #else
  772. #define uDrawSizeList *(UserItemUPP)&DrawSizeList
  773. #endif
  774.  
  775. static short SizeChoice[] = 
  776. {
  777.     9,
  778.     10,
  779.     12,
  780.     14,
  781.     18,
  782.     24
  783. };
  784.  
  785. const short    SizeChoiceCount = 6;
  786.  
  787. pascal Boolean FormatFilter(DialogPtr dlg, EventRecord * ev, short * item)
  788. {    
  789.     WindowPtr    win;
  790.     Rect            r;
  791.     
  792.     SetPort(dlg);
  793.     switch (ev->what) {
  794.     case keyDown:
  795.         switch (ev->message & charCodeMask) {
  796.         case '\n':
  797.         case 3:
  798.             *item = fd_OK;
  799.             
  800.             return true;
  801.         case '.':
  802.             if (!(ev->modifiers & cmdKey))
  803.                 break;
  804.         case 27:
  805.             *item = fd_Cancel;
  806.             
  807.             return true;
  808.         default:
  809.             break;
  810.         }
  811.     case mouseDown:
  812.         switch (FindWindow(ev->where, &win)) {
  813.         case inDrag:
  814.             if (win != dlg)
  815.                 return false;
  816.                 
  817.             r = qd.screenBits.bounds;
  818.             InsetRect(&r, 10, 10);
  819.             DragWindow(win, ev->where, &r);
  820.             
  821.             ev->what = nullEvent;
  822.             break;
  823.         case inSysWindow:
  824.             SystemClick(ev, win);
  825.             
  826.             ev->what = nullEvent;
  827.             break;
  828.         }
  829.         return false;
  830.     case activateEvt:
  831.         LActivate(ev->modifiers & activeFlag, FontList);
  832.         LActivate(ev->modifiers & activeFlag, SizeList);
  833.         break;
  834.     case updateEvt:
  835.         win = (WindowPtr) ev->message;
  836.         if (win != dlg) {
  837.             DoUpdate(DPtrFromWindowPtr(win), win);
  838.             
  839.             ev->what = nullEvent;
  840.         }
  841.         break;
  842.     }
  843.     
  844.     return false;
  845. }
  846.  
  847. #if USESROUTINEDESCRIPTORS
  848. RoutineDescriptor    uFormatFilter = 
  849.         BUILD_ROUTINE_DESCRIPTOR(uppModalFilterProcInfo, FormatFilter);
  850. #else
  851. #define uFormatFilter *(ModalFilterUPP)&FormatFilter
  852. #endif
  853.  
  854. short FontCellHeight(MenuHandle fonts, GrafPtr dlg)
  855. {
  856.     short        oldFont;
  857.     short        oldSize;
  858.     short        index;
  859.     short        fontNum;
  860.     short        scriptNum;
  861.     short        minHeight;
  862.     long        scriptsDone;
  863.     long        sysFont;
  864.     FontInfo    fontInfo;
  865.     Str255    contents;
  866.     
  867.     if (GetScriptManagerVariable(smEnabled) < 2)            /* Roman Script Only    */
  868.         return 16;                    /* Ascent + Descent + Leading for Chicago 12 */
  869.     
  870.     SetPort(dlg);
  871.     oldFont         = dlg->txFont;
  872.     oldSize         = dlg->txSize;
  873.     minHeight    = 16;
  874.     scriptsDone    = 0;
  875.     
  876.     for (index=0; index++ < CountMItems(fonts); ) {
  877.         GetItem(fonts, index, contents);
  878.         GetFNum(contents, &fontNum);
  879.         scriptNum = FontToScript(fontNum);
  880.         
  881.         if (scriptNum == smUninterp)
  882.             scriptNum = smRoman;
  883.         /* No point measuring a script more than once */
  884.         if (scriptNum < 32 && (scriptsDone & (1 << scriptNum)))
  885.             continue;
  886.         scriptsDone |= 1 << scriptNum;
  887.         sysFont = GetScriptVariable(scriptNum, smScriptSysFondSize);
  888.         TextFont(sysFont >> 16);
  889.         TextSize(sysFont & 0xFFFF);
  890.         GetFontInfo(&fontInfo);
  891.         if (fontInfo.ascent + fontInfo.descent + fontInfo.leading > minHeight)
  892.             minHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
  893.     }
  894.     
  895.     TextFont(oldFont);
  896.     TextSize(oldSize);
  897.     return minHeight;
  898. }
  899.  
  900. short FontLDEFID()
  901. {
  902.     if (GetScriptManagerVariable(smEnabled) < 2)            /* Roman Script Only    */
  903.         return 0;
  904.     else 
  905.         return 128;
  906. }
  907.  
  908. pascal Boolean DoFormatDialog(DocFormat * form, Boolean * defaultFormat)
  909. {
  910.     short            item;
  911.     short            kind;
  912.     short         digit;
  913.     Boolean        done;
  914.     Handle        h;
  915.     DialogPtr    format;
  916.     Point            cell;
  917.     Rect            bounds;
  918.     Rect            dbounds;
  919.     Str255        contents;
  920.     MenuHandle    fonts;
  921.     
  922.     format = GetNewDialog(FormatDialog, nil, (WindowPtr) -1);
  923.  
  924.     GetDItem(format, fd_Separator, &kind, &h, &bounds);
  925.     SetDItem(format, fd_Separator, kind, (Handle) &uSeparator, &bounds);
  926.  
  927.     GetDItem(format, fd_FontList, &kind, &h, &bounds);
  928.     SetDItem(format, fd_FontList, kind, (Handle) &uDrawFontList, &bounds);
  929.         
  930.     fonts = NewMenu(FormatDialog, (StringPtr) "\pFonts");
  931.     AppendResMenu(fonts, 'FONT');
  932.  
  933.     bounds.right -= 16;
  934.     SetPt(&cell, bounds.right - bounds.left, FontCellHeight(fonts, format));
  935.     SetRect(&dbounds, 0, 0, 1, CountMItems(fonts));
  936.     FontList = LNew(&bounds, &dbounds, cell, item = FontLDEFID(), format, false, false, false, true);
  937.     
  938.     SetPt(&cell, 0, 0);
  939.     for (; cell.v < CountMItems(fonts); ++cell.v) {
  940.         GetItem(fonts, cell.v+1, contents);
  941.         if (item)
  942.             LSetCell((Ptr)contents, contents[0]+1, cell, FontList);
  943.         else
  944.             LSetCell((Ptr)contents+1, contents[0], cell, FontList);
  945.         GetFNum(contents, &kind);
  946.         LSetSelect(form->font == kind, cell, FontList);
  947.     }
  948.     LAutoScroll(FontList);
  949.     
  950.     GetDItem(format, fd_SizeList, &kind, &h, &bounds);
  951.     SetDItem(format, fd_SizeList, kind, (Handle) &uDrawSizeList, &bounds);
  952.  
  953.     bounds.right -= 16;
  954.     SetPt(&cell, bounds.right - bounds.left, 16);
  955.     SetRect(&dbounds, 0, 0, 1, SizeChoiceCount);
  956.     SizeList = LNew(&bounds, &dbounds, cell, 0, format, false, false, false, true);
  957.     
  958.     SetPt(&cell, 0, 0);
  959.     for (; cell.v < SizeChoiceCount; ++cell.v) {
  960.         sprintf((char *) contents, "%d", SizeChoice[cell.v]);
  961.         LSetCell((Ptr)contents, strlen((Ptr) contents), cell, SizeList);
  962.         LSetSelect(form->size == SizeChoice[cell.v], cell, SizeList);
  963.     }
  964.     
  965.     AdornDefaultButton(format, fd_Outline);
  966.  
  967.     LDoDraw(true, FontList);
  968.     LDoDraw(true, SizeList);
  969.     
  970.     sprintf((char *) contents+1, "%d", form->size);
  971.     contents[0] = strlen((Ptr) contents+1);
  972.     SetText(format, fd_SizeEdit, contents);
  973.     SelIText(format, fd_SizeEdit, 0, 32767);
  974.  
  975.     if (*defaultFormat) {
  976.         GetDItem(format, fd_MakeDefault, &kind, &h, &bounds);
  977.         SetControlValue((ControlHandle) h, 1);
  978.         HiliteControl((ControlHandle) h, 254);
  979.     }
  980.     
  981.     ShowWindow(format);
  982.         
  983.     for (done = false; !done; ) {
  984.         ModalDialog(&uFormatFilter, &item);
  985.         
  986.         switch (item) {
  987.         case fd_OK:
  988.             RetrieveText(format, fd_SizeEdit, contents);
  989.             if (contents[0]) {
  990.                 for (digit = 0, kind = 0; digit++ < contents[0]; )
  991.                     if (isdigit(contents[digit]))
  992.                         kind = kind * 10 + contents[digit] - '0';
  993.                     else {
  994.                         kind = 0;
  995.                         
  996.                         break;
  997.                     }
  998.                 
  999.                 if (kind) {
  1000.                     form->size = kind;
  1001.                     SetPt(&cell, 0, 0);
  1002.                     LGetSelect(true, &cell, FontList);
  1003.                     GetItem(fonts, cell.v+1, contents);
  1004.                     GetFNum(contents, &kind);
  1005.                     form->font = kind;
  1006.                     
  1007.                     done = true;
  1008.                     break;
  1009.                 }
  1010.             }
  1011.             
  1012.             SelIText(format, fd_SizeEdit, 0, 32767);
  1013.             SysBeep(0);
  1014.             
  1015.             item = 0;
  1016.             break;
  1017.         case fd_Cancel:
  1018.             done = true;
  1019.             *defaultFormat = false;
  1020.             break;
  1021.         case fd_FontList:
  1022.             GetMouse(&cell);
  1023.             LClick(cell, 0, FontList);
  1024.             break;
  1025.         case fd_SizeList:
  1026.             GetMouse(&cell);
  1027.             LClick(cell, 0, SizeList);
  1028.             SetPt(&cell, 0, 0);
  1029.             if (LGetSelect(true, &cell, SizeList)) {
  1030.                 sprintf((char *) contents+1, "%d", SizeChoice[cell.v]);
  1031.                 contents[0] = strlen((Ptr) contents+1);
  1032.                 SetText(format, fd_SizeEdit, contents);
  1033.                 SelIText(format, fd_SizeEdit, 0, 32767);
  1034.             }
  1035.             break;
  1036.         case fd_MakeDefault:
  1037.             GetDItem(format, fd_MakeDefault, &kind, &h, &bounds);
  1038.             SetControlValue((ControlHandle) h, *defaultFormat = !*defaultFormat);
  1039.             break;
  1040.         }
  1041.     }
  1042.     
  1043.     LDispose(FontList);
  1044.     LDispose(SizeList);
  1045.     DisposeDialog(format);
  1046.     DisposeMenu(fonts);
  1047.     
  1048.     return (item == fd_OK);
  1049. }
  1050.