home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Text⁄Files / FaceLift / FaceLift Folder / FLMapWind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-22  |  21.3 KB  |  1,026 lines  |  [TEXT/KAHL]

  1. # include    "TransSkel.h"
  2.  
  3. # include    "FLMaca.h"
  4. # include    "FLMapInfo.h"
  5. # include    "FaceLift.h"
  6.  
  7. # define    enter    3
  8. # define    cr        '\r'
  9.  
  10.  
  11. /*
  12.  * Local data for creating controls
  13.  */
  14.  
  15.  
  16. /*
  17.  * maxSize = number of point-size selection radio buttons
  18.  * maxStyle = number of style selection check boxes
  19.  * maxFonts = maximum number of fonts allowed in scrollable list
  20.  */
  21.  
  22. # define    maxSize        7
  23. # define    maxStyle    9
  24. # define    maxFonts    102
  25.  
  26.  
  27. typedef enum    /* control types, by function */
  28. {
  29.     sizeType,    /* size radio button */
  30.     styleType    /* style check box */
  31. };
  32.  
  33.  
  34. typedef struct CtrlInfo
  35. {
  36.     Str255    cTitle;        /* initial control title */
  37.     int        ch, cv;        /* location of upper left corner */
  38. } CtrlInfo;
  39.  
  40.  
  41. static CtrlInfo    ctrlInfo[maxSize+maxStyle] =
  42. {
  43.     { "\pSame",                188,    20 },
  44.     { "\p9",                172,    40 },
  45.     { "\p10",                172,    60 },
  46.     { "\p12",                172,    80 },
  47.     { "\p14",                217,    40 },
  48.     { "\p18",                217,    60 },
  49.     { "\p24",                217,    80 },
  50.     { "\pSame",                312,    20 },
  51.     { "\pPlain",            265,    40 },
  52.     { "\pBold",                265,    60 },
  53.     { "\pItalic",            265,    80 },
  54.     { "\pUnderline",        265,    100 },
  55.     { "\pOutline",            355,    40 },
  56.     { "\pShadow",            355,    60 },
  57.     { "\pSuperscript",        355,    80 },
  58.     { "\pSubscript",        355,    100 }
  59. };
  60.  
  61.  
  62. static ControlHandle    styleCtrl[maxStyle];
  63. static ControlHandle    sizeCtrl[maxSize];
  64. static ControlHandle    sizeScroll;
  65. static int                trackPart;
  66.  
  67.  
  68. /*
  69.  * Standard MacWrite point sizes, plus the "any size" selection.
  70.  * The order of these corresponds to the size radio buttons.
  71.  */
  72.  
  73. static int        sizeInfo[maxSize] = { anySize, 9, 10, 12, 14, 18, 24 };
  74.  
  75.  
  76. /*
  77.  * Masks for manipulating style selections.  The order of these
  78.  * corresponds to the style check boxes.
  79.  */
  80.  
  81.  
  82. static int        styleMask[maxStyle] =
  83. {
  84.     anyStyle,
  85.     0,                /* plain; special-cased */
  86.     styleBold,
  87.     styleItalic,
  88.     styleUnder,
  89.     styleOutline,
  90.     styleShadow,
  91.     styleSuper,
  92.     styleSub
  93. };
  94.  
  95.  
  96. /*
  97.  * Standard font specifications
  98.  */
  99.  
  100.  
  101. typedef struct
  102. {
  103.     int                fontNum;
  104.     StringHandle    fontName;
  105. } FontSpec;
  106.  
  107.  
  108. static FontSpec    fontSpecs[maxFonts];
  109. static int        nFontSpecs;
  110.  
  111.  
  112. static short        fontOffsets[2] = { 0, 137 };
  113.  
  114.  
  115. static LineList    fontStruct =
  116. {
  117.     nil,                        /* port - filled in later        */
  118.     nil,                        /* control - filled in later     */
  119.     { 20, 5, 116, 141 },        /* text display rect, t, l, b, r */
  120.     0,                            /* max lines                     */
  121.     6,                            /* max visible lines             */
  122.     0,                            /* top visible line              */
  123.     16,                            /* line height                   */
  124.     0,                            /* number of lines               */
  125.     noLine,                        /* current line                  */
  126.     false,                        /* no hiliting                   */
  127.     1,                            /* number of fields/line         */
  128.     fontOffsets,                /* field offsets                 */
  129.     nil                            /* line array                    */
  130. };
  131.  
  132.  
  133. static LListPtr    fontList = &fontStruct;
  134.  
  135.  
  136. static MapSpec    *curMSpec;
  137. static ConvSpec    *curCSpec;
  138. static int        curMSpecNo;
  139.  
  140.  
  141. /* ---------------------------------------------------------------- */
  142. /*                    General Control Operations                        */
  143. /* ---------------------------------------------------------------- */
  144.  
  145.  
  146.  
  147. /*
  148.  * Set a control value, but only when it changes, to avoid
  149.  * unnecessary redrawing (ugly, since gobs of them are usually
  150.  * changed together).
  151.  *
  152.  * Use for check boxes and radio buttons only, not scroll bars!
  153.  * (The value is boolean (on/off), not a range.)
  154.  */
  155.  
  156. static void
  157. SetControl (ControlHandle ctrl, Boolean value)
  158. {
  159.     if (mapWind != FrontWindow ())
  160.         value = false;
  161.     if (GetCtlValue (ctrl) != value)
  162.         SetCtlValue (ctrl, value);
  163. }
  164.  
  165.  
  166. /*
  167.  * Reset a control's title, if it's different than the current one.
  168.  * The control bounds rectangle is validated because changing the
  169.  * title seems to invalidate it, resulting in an update event.
  170.  * Since the thing was just redrawn, there's no need waste time on
  171.  * an update.
  172.  */
  173.  
  174. static void
  175. SetControlTitle (ControlHandle ctrl, StringPtr title)
  176. {
  177. Str255    curTitle;
  178. Rect    r;
  179.  
  180.     GetCTitle (ctrl, curTitle);
  181.     if (CompareString (curTitle, title) != 0)
  182.     {
  183.         SetCTitle (ctrl, title);
  184.         r = (**ctrl).contrlRect;
  185.         ValidRect (&r);
  186.     }
  187. }
  188.  
  189.  
  190. /* ---------------------------------------------------------------- */
  191. /*                        Font List Operations                        */
  192. /* ---------------------------------------------------------------- */
  193.  
  194.  
  195. /*
  196.  * Add a font to the spec list.  Return false if there's overrun.
  197.  */
  198.  
  199. Boolean
  200. SetFontSpec (int fNum, StringPtr fName)
  201. {
  202. StringHandle    h;
  203. Str255            s;
  204. short            i, result;
  205.  
  206.     for (i = 0; i < nFontSpecs; ++i)    /* see if already there */
  207.     {
  208.         h = fontSpecs[i].fontName;
  209.         HLock ((Handle) h);
  210.         result = CompareString (*h, fName);
  211.         HUnlock ((Handle) h);
  212.         if (result == 0)        /* font name's a duplicate */
  213.             return (true);        /* but that's ok */
  214.     }
  215.  
  216.     if (nFontSpecs >= fontList->maxLines)    /* will list be too full? */
  217.     {
  218.         NumToString ((long) maxFonts - 2, s);
  219.         Message3 ("\pSorry, I am such a brain-damaged program that I only allow ",
  220.                     s, "\p fonts!");
  221.         return (false);
  222.     }
  223.  
  224.     h = (StringHandle) NewHandle ((long) (fName[0] + 1));
  225.     HLock ((Handle) h);
  226.     CopyString (fName, *h);
  227.     HUnlock ((Handle) h);
  228.     fontSpecs[nFontSpecs].fontName = h;
  229.     fontSpecs[nFontSpecs++].fontNum = fNum;
  230.     return (true);
  231. }
  232.  
  233.  
  234. /*
  235.  * Set up to construct a new font list.  Note that the other
  236.  * selector controls must have been initialized by this point.
  237.  */
  238.  
  239. void
  240. ResetFontList (void)
  241. {
  242. short    i;
  243.  
  244.     for (i = 0; i < fontList->nLines; ++i)
  245.         DisposeHandle ((Handle) fontSpecs[i].fontName);
  246.     nFontSpecs = 0;
  247.     ResetList (fontList);
  248.     SetFontSpec (anyFont, "\pAny");
  249.     SetFontSpec (applFont, "\pApplication");
  250. }
  251.  
  252.  
  253. /*
  254.  * Sync information in fontSpec to fontList by constructing the LineList
  255.  * elements.
  256.  */
  257.  
  258. void
  259. SyncFontSpecs (void)
  260. {
  261. short        i, j;
  262. short        tmp;
  263. FontSpec    *f1, *f2;
  264. StringHandle    h1, h2;
  265. LineHandle        hField;
  266.  
  267.     /*
  268.      * Sort font names, except for "Any" and "Application", which
  269.      * stay at the front of the list.
  270.      */
  271.  
  272.     for (i = 2; i < nFontSpecs - 1; ++i)
  273.     {
  274.         for (j = i + 1; j < nFontSpecs; ++j)
  275.         {
  276.             f1 = &fontSpecs[i];
  277.             f2 = &fontSpecs[j];
  278.             h1 = f1->fontName;
  279.             h2 = f2->fontName;
  280.             HLock ((Handle) h1);
  281.             HLock ((Handle) h2);
  282.             if (CompareString (*h1, *h2) > 0)
  283.             {
  284.                 f1->fontName = h2;
  285.                 f2->fontName = h1;
  286.                 tmp = f1->fontNum;
  287.                 f1->fontNum = f2->fontNum;
  288.                 f2->fontNum = tmp;
  289.             }
  290.             HUnlock ((Handle) h1);
  291.             HUnlock ((Handle) h2);
  292.         }
  293.     }
  294.  
  295.     /*
  296.      * Add names to fontList
  297.      */
  298.  
  299.     ResetList (fontList);
  300.     for (i = 0; i < nFontSpecs; ++i)
  301.     {
  302.         h1 = fontSpecs[i].fontName;
  303.         HLock ((Handle) h1);
  304.         hField = NewLine (1);
  305.         SetFieldStr (hField, *h1);
  306.         HUnlock ((Handle) h1);
  307.         (void) InsertLine (fontList, hField, i);
  308.     }
  309.     SelectLine (fontList, 0);
  310.     ScrollToLine (fontList, 0);        /* force scroll to top */
  311. }
  312.  
  313.  
  314. /*
  315.  * Given a font number, find its index in the stdFontSpecs
  316.  * array.  Return -1 if it's not there.
  317.  */
  318.  
  319. short
  320. FontIndex (int fontNum)
  321. {
  322. int        i;
  323.  
  324.     for (i = 0; i < fontList->nLines; ++i)
  325.     {
  326.         if (fontNum == fontSpecs[i].fontNum)
  327.             return (i);
  328.     }
  329.     return (-1);
  330. }
  331.  
  332.  
  333. /*
  334.  * Return a font name corresponding to the given index
  335.  */
  336.  
  337. void
  338. FontName (int fontIndex, StringPtr str)
  339. {
  340. StringHandle    hStr;
  341.  
  342.     hStr = fontSpecs[fontIndex].fontName;
  343.     HLock ((Handle) hStr);
  344.     CopyString (*hStr, str);
  345.     HUnlock ((Handle) hStr);
  346. }
  347.  
  348.  
  349. /* ---------------------------------------------------------------- */
  350. /*                        Size Control Operations                        */
  351. /* ---------------------------------------------------------------- */
  352.  
  353.  
  354. /*
  355.  * Given a point size, find its index in the sizeInfo
  356.  * array.  (Return -1 if it's not there.)
  357.  */
  358.  
  359. short
  360. SizeIndex (int size)
  361. {
  362. int        i;
  363.  
  364.     for (i = 0; i < maxSize; ++i)
  365.     {
  366.         if (size == sizeInfo[i])
  367.             return (i);
  368.     }
  369.     return (-1);
  370. }
  371.  
  372.  
  373. static void
  374. SetSizeScroll (int hilite)
  375. {
  376. int        value;
  377.  
  378.     value = curCSpec->size;
  379.     if (value == anySize)
  380.         value = 0;
  381.     if (mapWind != FrontWindow ())    /* don't hilite if window not front */
  382.         hilite = 255;
  383.     if (hilite == 0)
  384.     {
  385.         if (value != GetCtlValue (sizeScroll))
  386.             SetCtlValue (sizeScroll, value);
  387.     }
  388.     if (hilite != (**sizeScroll).contrlHilite)
  389.         HiliteControl (sizeScroll, hilite);
  390. }
  391.  
  392.  
  393. /*
  394.  * Set the size scroll to the current size value, and turn on the
  395.  * appropriate radio button if the size is one of the standard
  396.  * MacWrite sizes.
  397.  */
  398.  
  399. static void
  400. SetSizeCtrls (void)
  401. {
  402. int    i;
  403.  
  404.     SetSizeScroll (0);
  405.     for (i = 0; i < maxSize; ++i)
  406.         SetControl (sizeCtrl[i], sizeInfo[i] == curCSpec->size);
  407. }
  408.  
  409.  
  410. /* ---------------------------------------------------------------- */
  411. /*                        Style Control Operations                    */
  412. /* ---------------------------------------------------------------- */
  413.  
  414.  
  415. /*
  416.  * Set the style controls based on the current value of theStyle.
  417.  *
  418.  * The any/same bit and the attributes bits cause the corresponding
  419.  * boxes to be checked if they are set.  If the style is zero, it's
  420.  * plain.
  421.  */
  422.  
  423. static void
  424. SetStyleCtrls (void)
  425. {
  426. int        i;
  427. Boolean    any;
  428. int        theStyle;
  429.  
  430.     theStyle = curCSpec->style;
  431.     any = ((theStyle & anyStyle) != 0);
  432.     SetControl (styleCtrl[0], any);
  433.  
  434.     if (any)
  435.     {
  436.         for (i = 1; i < maxStyle; ++i)
  437.             SetControl (styleCtrl[i], false);
  438.     }
  439.     else if (theStyle == 0)                    /* plain */
  440.     {
  441.         SetControl (styleCtrl[1], true);
  442.         for (i = 2; i < maxStyle; ++i)
  443.             SetControl (styleCtrl[i], false);
  444.     }
  445.     else                                    /* not plain */
  446.     {
  447.         SetControl (styleCtrl[1], false);
  448.         for (i = 2; i < maxStyle; ++i)
  449.             SetControl (styleCtrl[i], (theStyle & styleMask[i]) != 0);
  450.     }
  451. }
  452.  
  453.  
  454. /*
  455.  * Determine style value.  The argument is an index into the control
  456.  * array not a style value itself.  Style controls interact in
  457.  * wretched complexity.
  458.  *
  459.  * If any/same is toggled on, all the other style boxes are toggled off.
  460.  * If it's toggled off, plain is toggled on.
  461.  *
  462.  * If plain is toggled on, all the other style boxes are toggled off.
  463.  * If it's toggled off, any/same is toggled on.
  464.  *
  465.  * The other style boxes correspond to style attributes.  If any of
  466.  * them are toggled on, then any/same and plain are toggle off if
  467.  * they were on.  If all the attributes are toggled off, plain is
  468.  * toggled on.  Superscript and subscript are mutually exclusive,
  469.  * so that if one of them is toggled on, the other is toggled off.
  470.  */
  471.  
  472. static int
  473. NewStyleValue (int i)
  474. {
  475. int    curValue;
  476. int    theStyle;
  477.  
  478.     curValue = GetCtlValue (styleCtrl[i]);    /* current value - new value */
  479.                                             /* will be opposite */
  480.     theStyle = curCSpec->style;
  481.  
  482.     if (i == 0)            /* any/same box clicked */
  483.     {
  484.         if (curValue)    /*  currently any, turn off (implies plain) */
  485.             theStyle = 0;
  486.         else
  487.             theStyle = styleMask[0];    /* currently off, turn on */
  488.     }
  489.     else if (i == 1)    /* plain box clicked */
  490.     {
  491.         if (curValue)    /*  currently plain, turn off (implies any/same) */
  492.             theStyle = styleMask[0];
  493.         else
  494.             theStyle = 0;    /* currently off, turn on */
  495.     }
  496.     else
  497.     {
  498.         /*
  499.          * Flip box value.
  500.          * Can't have superscript and subscript at the same time.
  501.          */
  502.         if (curValue)    /* currently on, turn off */
  503.             theStyle &= ~styleMask[i];
  504.         else            /* currently off, turn on (turn any/same off) */
  505.         {
  506.             theStyle |= styleMask[i];
  507.             theStyle &= ~styleMask[0];
  508.         }
  509.  
  510.         if (i == 7)    /* superscript.  if turning on, turn off sub */
  511.         {
  512.             if (curValue == 0)
  513.                 theStyle &= ~styleMask[8];
  514.         }
  515.         if (i == 8)    /* subscript.  if turning on, turn off super */
  516.         {
  517.             if (curValue == 0)
  518.                 theStyle &= ~styleMask[7];
  519.         }
  520.     }
  521.     return (theStyle);
  522. }
  523.  
  524.  
  525. /* ---------------------------------------------------------------- */
  526.  
  527.  
  528. /*
  529.  * Set a field in the currently selected line.  Don't call this if
  530.  * no line is selected, or if the field already has the same value.
  531.  */
  532.  
  533. void
  534. SetMapFieldValue (int fieldType, int value)
  535. {
  536. int            fieldOffset;
  537. Str255        s;
  538. StringPtr    defStr;
  539.  
  540.     /*
  541.      * Figure out the default string for putting in the mapping if
  542.      * any/same was selected.
  543.      */
  544.  
  545.     if (curMSpec->isInput == true)
  546.     {
  547.         defStr = (StringPtr) "\pAny";
  548.         fieldOffset = 0;
  549.     }
  550.     else
  551.     {
  552.         defStr = (StringPtr) "\pSame";
  553.         fieldOffset = mapList->nFields/2;
  554.     }
  555.  
  556.     switch (fieldType)
  557.     {
  558.  
  559.     case fontField:
  560.         undoVal = curCSpec->font;
  561.         FontToStr (value, s, defStr);
  562.         curCSpec->font = value;
  563.         SelectLine (fontList, FontIndex (value));
  564.         break;
  565.  
  566.     case sizeField:
  567.         undoVal = curCSpec->size;
  568.         SizeToStr (value, s, defStr);
  569.         curCSpec->size = value;
  570.         SetSizeCtrls ();
  571.         break;
  572.  
  573.     case styleField:
  574.         undoVal = curCSpec->style;
  575.         StyleToStr (value, s, defStr);
  576.         curCSpec->style = value;
  577.         SetStyleCtrls ();
  578.         break;
  579.     }
  580.  
  581.     PasteField (mapList, mapList->curLine, fieldOffset + fieldType, s);
  582.     mapModified = true;
  583.     undoOp = undoFieldChg;
  584.     undoFieldType = fieldType;
  585. }
  586.  
  587.  
  588. /*
  589.  * Set the selection controls and font list to reflect currently
  590.  * selected conversion specification.  Also sets current MapSpec
  591.  * and ConvSpec pointers.
  592.  */
  593.  
  594. void
  595. SetSelectors (int lineNo)
  596. {
  597. int    i;
  598. StringPtr        anySame;
  599. FieldHandle        hField;
  600.  
  601.     if (lineNo == noLine)                /* no map line selected */
  602.     {
  603.         curMSpec = nil;
  604.         curMSpecNo = noLine;
  605.  
  606.         ListActivate (fontList, false);
  607.     
  608.         SetSizeScroll (255);
  609.         for (i = 0; i < maxSize; ++i)
  610.             SetControl (sizeCtrl[i], false);
  611.     
  612.         for (i = 0; i < maxStyle; ++i)
  613.             SetControl (styleCtrl[i], false);
  614.     
  615.         /*SetIO ();*/
  616.  
  617.         return;
  618.     }
  619.  
  620.     curMSpec = &mapSpec[curMSpecNo = lineNo];
  621.     if (curMSpec->isInput)
  622.     {
  623.         curCSpec = &curMSpec->inFmt;
  624.         anySame = (StringPtr) "\pAny";
  625.     }
  626.     else
  627.     {
  628.         curCSpec = &curMSpec->outFmt;
  629.         anySame = (StringPtr) "\pSame";
  630.     }
  631.  
  632.     hField = ListLine (fontList, 0);
  633.     HLock ((Handle) hField);
  634.     if (CompareString ((**hField).fStr, anySame) != 0)
  635.         PasteField (fontList, 0, 0, anySame);
  636.     HUnlock ((Handle) hField);
  637.     SetControlTitle (sizeCtrl[0], anySame);
  638.     SetControlTitle (styleCtrl[0], anySame);
  639.  
  640.     SelectLine (fontList, FontIndex (curCSpec->font));
  641.     ListActivate (fontList, true);
  642.     if (showCurFont)
  643.         ScrollToLine (fontList, fontList->curLine);
  644.     SetSizeCtrls ();
  645.     SetStyleCtrls ();
  646.     /*SetIO ();*/
  647. }
  648.  
  649.  
  650. static void
  651. SetIO (Boolean value)
  652. {
  653. Str255    s;
  654.  
  655.     MarkToStr (value, s);
  656.     PasteField (mapList, mapList->curLine, markField, s);
  657.     MarkToStr (!value, s);
  658.     PasteField (mapList, mapList->curLine, markField+mapList->nFields/2, s);
  659. }
  660.  
  661.  
  662. static pascal void
  663. TrackScroll (ControlHandle theScroll, short partCode)
  664. {
  665. short    value, curVal;
  666.  
  667.     if (partCode == trackPart)            /* still in same part? */
  668.     {
  669.         switch (partCode)
  670.         {
  671.             case inUpButton: value = -1; break;
  672.             case inDownButton: value = 1; break;
  673.             case inPageUp: value = -5; break;
  674.             case inPageDown: value = 5; break;
  675.         }
  676.         curVal = GetCtlValue (sizeScroll);
  677.         SetCtlValue (sizeScroll, curVal + value);
  678.         value = GetCtlValue (sizeScroll);
  679.         if (value != curVal)                /* did it change? */
  680.         {
  681.             if (value == 0)
  682.                 value = anySize;
  683.             SetMapFieldValue (sizeField, value);
  684.         }
  685.     }
  686. }
  687.  
  688.  
  689. /*
  690.  * Map window mouse handler.
  691.  *
  692.  * First test the scroll bars, and return if one was hit; they
  693.  * require no further action.
  694.  *
  695.  * Then check for hit in map list.  If a new line was selected, or
  696.  * if the click was in the other half of the current line, set the
  697.  * selectors to the values, and disable undo.
  698.  *
  699.  * Then, if a line is currently selected, check the selection controls.
  700.  * If one is hit, change the values in the current line and reset the
  701.  * controls properly - but only if the current values *change*.
  702.  */
  703.  
  704. static pascal void
  705. Mouse (Point pt, long t, short mods)
  706. {
  707. ControlHandle    ctrl;
  708. int                index;
  709. int                type;
  710. long            refCon;
  711. int                newVal;
  712. int                curLine;
  713.  
  714.     if (ListTestScroll (mapList, pt) || ListTestScroll (fontList, pt))
  715.         return;
  716.  
  717.     curLine = mapList->curLine;                /* current line */
  718.     if (ListTestText (mapList, pt))
  719.     {
  720.         if (curLine != mapList->curLine)    /* different now? */
  721.             undoOp = noUndo;
  722.         GetMouse (&pt);
  723.         if (mapList->curLine != noLine)
  724.         {
  725.         Boolean    newIO;
  726.  
  727.             newIO = (Boolean) (pt.h
  728.                     < mapList->textRect.left + mapList->offset[mapList->nFields/2]);
  729.             if (/*newVal*/ newIO != mapSpec[mapList->curLine].isInput)
  730.             {
  731.                 undoOp = noUndo;
  732.                 mapSpec[mapList->curLine].isInput = newIO;
  733.                 SetIO (newIO);
  734.             }
  735.         }
  736.         SetSelectors (mapList->curLine);
  737.         FixMenus ();
  738.         return;
  739.     }
  740.  
  741.     if (curMSpec == nil)
  742.         return;                /* no current line - controls irrelevant */
  743.  
  744.     if (ListTestText (fontList, pt))
  745.     {
  746.         if (fontList->curLine == noLine)
  747.             SelectLine (fontList, fontList->nLines - 1);
  748.         newVal = fontSpecs[fontList->curLine].fontNum;    
  749.         if (curCSpec->font != newVal)
  750.         {
  751.             SetMapFieldValue (fontField, newVal);
  752.             FixMenus ();
  753.         }
  754.         return;
  755.     }
  756.  
  757.     /*
  758.      * If a control isn't hit and it's not a check box, it's the size
  759.      * scroll.  Track as necessary.  Otherwise the control is a check
  760.      * box or radio button. The control type and index is coded in
  761.      * the reference constant (see MakeControl).
  762.      */
  763.  
  764.     if ((trackPart = FindControl (pt, mapWind, &ctrl)) != 0)
  765.     {
  766.         if (trackPart != inCheckBox)
  767.         {
  768.             int        saveVal;
  769.  
  770.             /*
  771.              * This isn't quite right, because non-thumb hits might not change
  772.              * the value - if already at end of range, for instance.
  773.              */
  774.  
  775.             if (trackPart == inThumb)
  776.             {
  777.                 /*
  778.                  * Track thumb and reset size if it changed
  779.                  */
  780.                 (void) TrackControl (sizeScroll, pt, nil);
  781.                 newVal = GetCtlValue (sizeScroll);
  782.                 if (newVal == 0)
  783.                     newVal = anySize;
  784.                 if (newVal != curCSpec->size)
  785.                     SetMapFieldValue (sizeField, newVal);
  786.             }
  787.             else
  788.             {
  789.                 /*
  790.                  * Track other parts.  Save starting value, because
  791.                  * SetMapFieldValue (called by TrackScroll) may set
  792.                  * the value many times, but the undo value is really
  793.                  * the start value of the scroll.
  794.                  */
  795.                 saveVal = curCSpec->size;
  796.                 (void) TrackControl (sizeScroll, pt, TrackScroll);
  797.                 undoVal = saveVal;
  798.             }
  799.         }
  800.         else if (TrackControl (ctrl, pt, nil) == inCheckBox)
  801.         {
  802.             refCon = GetCRefCon (ctrl);
  803.             index = refCon & 0x00ff;
  804.             type = (refCon & 0xff00) >> 8;
  805.  
  806.             switch (type)
  807.             {
  808.  
  809.             case sizeType:
  810.                 newVal = sizeInfo[index];
  811.                 if (newVal != curCSpec->size)
  812.                     SetMapFieldValue (sizeField, newVal);
  813.                 break;
  814.  
  815.             case styleType:
  816.                 newVal = NewStyleValue (index);
  817.                 if (newVal != curCSpec->style)
  818.                     SetMapFieldValue (styleField, newVal);
  819.                 break;
  820.  
  821.             }
  822.  
  823.         }
  824.         FixMenus ();
  825.         return;
  826.     }
  827. }
  828.  
  829.  
  830. /*
  831.  * Process key click in window for mark string.  Only keys used are tab,
  832.  * enter and return.  Typing any of them selects the next line.  If the
  833.  * shift key is down, then the previous line is selected.
  834.  */
  835.  
  836. static pascal void
  837. Key (short c, short code, short mods)
  838. {
  839.     if (curMSpec == nil)
  840.         return;
  841.  
  842.     switch (c)
  843.     {
  844.     
  845.     case '\t':
  846.     case enter:
  847.     case cr:
  848.         undoOp = noUndo;
  849.         if (mods & shiftKey)
  850.         {
  851.             if (--curMSpecNo < 0)
  852.                 curMSpecNo = mapList->nLines - 1;
  853.         }
  854.         else
  855.         {
  856.             if (++curMSpecNo >= mapList->nLines)
  857.                 curMSpecNo = 0;
  858.         }
  859.         SelectMapping (curMSpecNo);
  860.         break;
  861.  
  862.     }
  863. }
  864.  
  865.  
  866. static pascal void
  867. Update (Boolean resized)
  868. {
  869. int    i;
  870. Rect    r;
  871.  
  872.     MoveTo (65, 14);
  873.     DrawString ("\pFont");
  874.     MoveTo (180, 14);
  875.     DrawString ("\pPoint Size");
  876.     MoveTo (322, 14);
  877.     DrawString ("\pStyle");
  878.     DrawControls (mapWind);
  879.     DrawListFrame (fontList);
  880.     DrawListFrame (mapList);
  881.  
  882.     MoveTo (68, 143);
  883.     DrawString ("\pInput Formats");
  884.     MoveTo (287, 143);
  885.     DrawString ("\pOutput Formats");
  886.  
  887.     DrawListText (fontList);
  888.     DrawListText (mapList);
  889. }
  890.  
  891.  
  892. /*
  893.  * When the window is activated, do appropriate map list and font list
  894.  * line and scroll bar hiliting, and set size and style controls to
  895.  * current values.
  896.  *
  897.  * When the window is deactivated, all hiliting is turned off, the
  898.  * scroll bars are unhilited and the size and style controls go blank.
  899.  *
  900.  * Note that SetSelectors takes care of setting font list line and scroll
  901.  * bar hiliting and size scroll hiliting; it doesn't have to be done here.
  902.  */
  903.  
  904. static pascal void
  905. Activate (Boolean active)
  906. {
  907.     if (active)
  908.     {
  909.         SkelDoUpdates ();
  910.         ListActivate (mapList, true);
  911.         SetSelectors (mapList->curLine);
  912.     }
  913.     else
  914.     {
  915.         SetSelectors (noLine);
  916.         ListActivate (mapList, false);
  917.     }
  918.     FixMenus ();
  919. }
  920.  
  921.  
  922. static pascal void
  923. Clobber (void)
  924. {
  925.     HideWindow (mapWind);
  926.     /*DisposeList (mapList);
  927.     DisposeList (fontList);*/
  928.     DisposeWindow (mapWind);
  929. }
  930.  
  931.  
  932. /*
  933.  * Create controls.  These are created in the same order as the specs
  934.  * in the ctrlInfo array.
  935.  */
  936.  
  937. static ControlHandle
  938. MakeControl (int proc, int type, int index)
  939. {
  940. static short    i = 0;    /* used to step through ctrlInfo array */
  941. CtrlInfo    *cInfo;
  942. Rect        r;
  943. StringPtr    title;
  944. short        h, v;
  945. ControlHandle    ctrl;
  946.  
  947.     cInfo = &ctrlInfo[i++];
  948.     title = cInfo->cTitle;
  949.     h = cInfo->ch;
  950.     v = cInfo->cv;
  951.     SetRect (&r, h, v, h + StringWidth (title) + 20, v + 20);
  952.     ctrl = NewControl (mapWind,
  953.                         &r,
  954.                         title,
  955.                         true,
  956.                         0, 0, 1,
  957.                         proc,
  958.                         (long) (type << 8 | index));
  959.     return (ctrl);
  960. }
  961.  
  962.  
  963. void
  964. MapSetup (void)
  965. {
  966. short    i;
  967. Rect    r;
  968.  
  969.     SetRect (&r, 0, 0, 460, 251);
  970.     if (SkelQuery (skelQHasColorQD))
  971.     {
  972.         mapWind = NewCWindow (nil, &r, "\p", false, noGrowDocProc,
  973.                                     (WindowPtr) -1L, false, 0L);
  974.     }
  975.     else
  976.     {
  977.         mapWind = NewWindow (nil, &r, "\p", false, noGrowDocProc,
  978.                                     (WindowPtr) -1L, false, 0L);
  979.     }
  980.     (void) SkelWindow (mapWind,
  981.                 Mouse,
  982.                 Key,
  983.                 Update,
  984.                 Activate,
  985.                 nil,
  986.                 Clobber,
  987.                 nil,
  988.                 false);
  989.  
  990.     TextFont (0);            /* do this so StringWidth calculations */
  991.     TextSize (0);            /* for controls will be accurate */
  992.  
  993.     SetRect (&r, 167, 104, 256, 120);
  994.     sizeScroll = NewControl (mapWind, &r, "\p", true, 0, 0, maxPtSize,
  995.                         scrollBarProc, 0L);
  996.     for (i = 0; i < maxSize; ++i)
  997.         sizeCtrl[i] = MakeControl (radioButProc, sizeType, i);
  998.  
  999.     for (i = 0; i < maxStyle; ++i)
  1000.         styleCtrl[i] = MakeControl (checkBoxProc, styleType, i);
  1001.  
  1002.     /*
  1003.      * These two are created with title "Same" so that the control bounds
  1004.      * rect will be big enough for both "Same" and "Any".  Change title now
  1005.      * because initial title should really be "Any".
  1006.      */
  1007.  
  1008.     SetControlTitle (sizeCtrl[0], "\pAny");
  1009.     SetControlTitle (styleCtrl[0], "\pAny");
  1010.  
  1011.     InitList (fontList, maxFonts);        /* initialize empty list */
  1012.     InitList (mapList, maxMappings);
  1013.  
  1014.     /*
  1015.      * Add default set of fonts:  ImageWriter fonts and LaserWriter fonts.
  1016.      */
  1017.  
  1018.     ResetFontList ();
  1019.     StrFonts (false);
  1020.  
  1021.     ClearMapName ();
  1022.     SkelPositionWindow (mapWind, skelPositionOnMainDevice,
  1023.                                     FixRatio (1, 2), FixRatio (1, 5));
  1024.     ShowWindow (mapWind);
  1025. }
  1026.