home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / lang / lsc30p4d.hqx / text0000.txt < prev   
Encoding:
INI File  |  1988-09-10  |  10.9 KB  |  388 lines

  1. [Dialog management in Think C 3.0]
  2.  
  3. I picked this up from Paul DuBois' BlobMgrDemo source a while back, and
  4. slightly enhanced it to handle the Return or Enter keys and to highlight
  5. the default OK button.  This works under Think's LightSpeed C.  It's
  6. public domain code.
  7.  
  8. ---
  9.  /*
  10.     Present a dialog box with a text rectangle, a scroll bar, and an OK
  11.     button.  This can be used as a help dialog.  Pass in a dialog
  12.     resource number and a handle to the text.  The dialog should
  13.     have the OK button as the first item, and user items for the
  14.     second and third items.  The second is the rect in which the
  15.     control is drawn, the third is the rect in which text is drawn.
  16.     Only the OK button should be enabled.
  17.  
  18.     The text handle should be locked before calling TextDlog and
  19.     unlocked after.
  20.  
  21.     Original author:                    dubois@uwmacc.UUCP (Paul DuBois)
  22.     with a few changes & cleanup by:    blob@apple.com  (Brian Bechtel)
  23. */
  24.  
  25. #include   <EventMgr.h>
  26. #include   <DialogMgr.h>
  27. #include   <ControlMgr.h>
  28.  
  29.  
  30. #define    nil     0L
  31.  
  32. #define ETX 03      /* Enter key */
  33. #define CR  13      /* Return key */
  34.  
  35. enum        /* item numbers */
  36. {
  37.     OKButton = 1,
  38.     scrollBarUser,
  39.     textRectUser
  40. };
  41.  
  42. static ControlHandle    theScroll;
  43. static Boolean          needScroll; /* true if need scroll bar */
  44. static int              curLine;
  45. static int              halfPage;
  46. static TEHandle         teHand;
  47.  
  48.  
  49.  
  50. /************************************************************************
  51.  *
  52.  *  Function:       HighLightDefault
  53.  *
  54.  *  Purpose:        highlight the default button in a dialog
  55.  *
  56.  *  Returns:        nothing
  57.  *
  58.  *  Side Effects:   standard box is drawn around highlight box
  59.  *
  60.  *  Description:    draws the heavy rounded box around the OK button,
  61.  *                  so that the user knows that hitting enter or return
  62.  *                  is the same as pressing the OK button.
  63.  *
  64.  ************************************************************************/
  65. static void
  66. HighLightDefault(dPtr)
  67. DialogPtr dPtr;
  68. {
  69.     int unusedItemType;
  70.     Handle unusedItemHandle;
  71.     Rect box;
  72.     PenState p;
  73.  
  74.     /*  This next little piece of code puts the default heavy rounded
  75.         box around the "OK" button, so the user knows that pressing
  76.         return is the same as hitting "OK"
  77.     */
  78.     SetPort(dPtr);      /* without this, can't highlite OK */
  79.     GetDItem(dPtr, OKButton, &unusedItemType, &unusedItemHandle, &box);
  80.     GetPenState(&p);
  81.     PenSize(3,3);
  82.     InsetRect(&box, -4, -4);
  83.     FrameRoundRect(&box, 16, 16);
  84.     PenSize(p.pnSize.h, p.pnSize.v);
  85. }
  86.  
  87. /************************************************************************
  88.  *
  89.  *  Function:       DrawScroll
  90.  *
  91.  *  Purpose:        draw scroll bar user item
  92.  *
  93.  *  Returns:        nothing
  94.  *
  95.  *  Side Effects:   draws scroll bar user item
  96.  *
  97.  *  Description:    if we need to scroll, show the control.
  98.  *
  99.  ************************************************************************/
  100. static pascal void DrawScroll (theDialog, itemNo)
  101. DialogPtr   theDialog;
  102. int         itemNo;
  103. {
  104.     if (needScroll)
  105.         ShowControl (theScroll);
  106. }
  107.  
  108.  
  109. /*
  110.     Proc for drawing text display user item.
  111. */
  112.  
  113.  
  114. /************************************************************************
  115.  *
  116.  *  Function:       DrawTextRect
  117.  *
  118.  *  Purpose:        draw text display user item
  119.  *
  120.  *  Returns:        nothing
  121.  *
  122.  *  Side Effects:   shows the text
  123.  *
  124.  *  Description:    Get the rectangle for our text.  If we need to scroll,
  125.  *                  frame the rectangle so that it will look correct.
  126.  *                  Get the view rectangle of our text rectangle, and do
  127.  *                  a TEUpdate so that text edit will properly handle
  128.  *                  updating the rectangle.
  129.  *
  130.  ************************************************************************/
  131. static pascal void DrawTextRect (theDialog, itemNo)
  132. DialogPtr   theDialog;
  133. int         itemNo;
  134. {
  135. Rect    r;
  136. int     itemType;
  137. Handle  itemHandle;
  138.  
  139.     GetDItem (theDialog, textRectUser, &itemType, &itemHandle, &r);
  140.     if (needScroll)
  141.         FrameRect (&r);
  142.     r = (**teHand).viewRect;
  143.     TEUpdate (&r, teHand);
  144. }
  145.  
  146.  
  147. /************************************************************************
  148.  *
  149.  *  Function:       DoScroll
  150.  *
  151.  *  Purpose:        scroll to correct position
  152.  *
  153.  *  Returns:        nothing.
  154.  *
  155.  *  Side Effects:   text is scrolled to new position
  156.  *
  157.  *  Description:
  158.  *                  Scroll to the correct position.  lDelta is the
  159.  *                  amount to CHANGE the current scroll setting by.
  160.  *
  161.  ************************************************************************/
  162. static void
  163. DoScroll (lDelta)
  164. int     lDelta;
  165. {
  166. int newLine;
  167.  
  168.     newLine = curLine + lDelta;
  169.     if (newLine < 0) newLine = 0;
  170.     if (newLine > GetCtlMax (theScroll)) newLine = GetCtlMax (theScroll);
  171.     SetCtlValue (theScroll, newLine);
  172.     lDelta = (curLine - newLine ) * (**teHand).lineHeight;
  173.     TEScroll (0, lDelta, teHand);
  174.     curLine = newLine;
  175. }
  176.  
  177.  
  178.  
  179. /************************************************************************
  180.  *
  181.  *  Function:       __TrackScroll
  182.  *
  183.  *  Purpose:        track the scrolling
  184.  *
  185.  *  Returns:        nothing
  186.  *
  187.  *  Side Effects:   scrolling
  188.  *
  189.  *  Description:    get the control part that we're in.  If we're still
  190.  *                  in the same part, we're going to scroll.  Check what
  191.  *                  kind of part we're in, and set our delta accordingly.
  192.  *                  Call DoScroll to actually handle the scrolling.
  193.  *
  194.  ************************************************************************/
  195. static pascal void __TrackScroll (theScroll, partCode)
  196. ControlHandle   theScroll;
  197. int             partCode;
  198. {
  199. int lDelta;
  200.  
  201.     if (partCode == GetCRefCon (theScroll)) /* still in same part? */
  202.     {
  203.         switch (partCode)
  204.         {
  205.             case inUpButton: lDelta = -1; break;
  206.             case inDownButton: lDelta = 1; break;
  207.             case inPageUp: lDelta = -halfPage; break;
  208.             case inPageDown: lDelta = halfPage; break;
  209.         }
  210.         DoScroll (lDelta);
  211.     }
  212. }
  213.  
  214.  
  215. /*
  216.     Filter to handle hits in scroll bar
  217. */
  218.  
  219.  
  220. /************************************************************************
  221.  *
  222.  *  Function:       TextFilter
  223.  *
  224.  *  Purpose:        filter to handle hits in scroll bar
  225.  *
  226.  *  Returns:        false (indicating we should continue within our
  227.  *                  modal dialog)
  228.  *
  229.  *  Side Effects:   May scroll the text
  230.  *
  231.  *  Description:    We're being called as part of a ModalDialog call.
  232.  *                  Check what kind of event activated us.  If it was a
  233.  *                  mouseDown, handle it.  If we were in the thumb, track
  234.  *                  the thumb, otherwise scroll the indicated amount.
  235.  *
  236.  ************************************************************************/
  237. static pascal Boolean TextFilter (theDialog, theEvent, itemHit)
  238. DialogPtr   theDialog;
  239. EventRecord *theEvent;
  240. int         *itemHit;
  241. {
  242. Point   thePoint;
  243. int     thePart;
  244. Boolean result;
  245.  
  246.     result = false;
  247.     switch (theEvent->what)
  248.     {
  249.         case mouseDown:
  250.             thePoint = theEvent->where;
  251.             GlobalToLocal (&thePoint);
  252.             thePart = TestControl (theScroll, thePoint);
  253.             if (thePart == inThumb)
  254.             {
  255.                 (void) TrackControl (theScroll, thePoint, nil);
  256.                 DoScroll (GetCtlValue (theScroll) - curLine);
  257.             }
  258.             else if (thePart != 0)
  259.             {
  260.                 SetCRefCon (theScroll, (long) thePart);
  261.                 (void) TrackControl (theScroll, thePoint, __TrackScroll);
  262.             }
  263.             break;
  264.         case keyDown:
  265.             if ((theEvent->message & charCodeMask) == ETX)
  266.             {
  267.                 *itemHit = 1;
  268.                 result = true;
  269.             }
  270.             if ((theEvent->message & charCodeMask) == CR)
  271.             {
  272.                 *itemHit = 1;
  273.                 result = true;
  274.             }
  275.             break;
  276.         case updateEvt:
  277.         case activateEvt:
  278.             HighLightDefault(theDialog);
  279.             break;
  280.     }
  281.     return (result);
  282. }
  283.  
  284.  
  285.  
  286. /************************************************************************
  287.  *
  288.  *  Function:       TextDialog
  289.  *
  290.  *  Purpose:        put up text dialog with optional scroll bar
  291.  *
  292.  *  Returns:        nothing
  293.  *
  294.  *  Side Effects:   none
  295.  *
  296.  *  Description:    Pass in a dialog number, a handle to the text to
  297.  *                  display, a font number, font size, and a boolean
  298.  *                  indicating whether you want the text to wrap or not.
  299.  *
  300.  *                  The dialog referenced by dlogNum should have the 
  301.  *                  OK button as the first item, and user items for the
  302.  *                  second and third items.  The second is the rect in
  303.  *                  which the control is drawn, the third is the rect in
  304.  *                  which text is drawn. Only the OK button should be
  305.  *                  enabled.
  306.  *
  307.  *                  The text handle should be locked before calling us,
  308.  *                  and unlocked afterwards.
  309.  *
  310.  *                  Of course, the font number and size should exist in
  311.  *                  the current system, or it will default to something
  312.  *                  ugly.
  313.  *
  314.  ************************************************************************/
  315. void
  316. TextDialog (dlogNum, textHandle, fontNum, fontSize, wrap)
  317. int     dlogNum;
  318. Handle  textHandle;
  319. int     fontNum;
  320. int     fontSize;
  321. Boolean wrap;
  322. {
  323. GrafPtr     oldPort;
  324. DialogPtr   theDialog;
  325. int         itemNo;
  326. int         itemType;
  327. Handle      itemHandle;
  328. Rect        r;
  329. int         scrollLines;
  330. int         viewLines;
  331. Handle      oldHText;
  332. ProcPtr     filterProc = nil;
  333.  
  334.     GetPort (&oldPort);
  335.     theDialog = GetNewDialog (dlogNum, nil, -1L);
  336.  
  337.     GetDItem (theDialog, textRectUser, &itemType, &itemHandle, &r);
  338.     SetDItem (theDialog, textRectUser, itemType, DrawTextRect, &r);
  339. /*
  340.     incorporate text into a TERec.
  341. */
  342.     SetPort (theDialog);
  343.     TextFont (fontNum);
  344.     TextSize (fontSize);
  345.  
  346.     InsetRect (&r, 4, 4);
  347.     teHand = TENew (&r, &r);
  348.     if (!wrap)
  349.         (**teHand).crOnly = -1;
  350.     oldHText = (**teHand).hText;        /* save this.  restore later */
  351.     (**teHand).hText = textHandle;
  352.     TECalText (teHand);
  353.     viewLines = (r.bottom - r.top) / (**teHand).lineHeight;
  354.     scrollLines = (**teHand).nLines - viewLines;
  355.     needScroll = (scrollLines > 0);
  356.     GetDItem (theDialog, scrollBarUser, &itemType, &itemHandle, &r);
  357.     SetDItem (theDialog, scrollBarUser, itemType, DrawScroll, &r);
  358.     if (needScroll)
  359.     {
  360.         theScroll = NewControl (theDialog, &r, "\p", false, 0, 0, 0,
  361.                         scrollBarProc, nil);
  362.         SetCtlMax (theScroll, scrollLines);
  363.         halfPage = viewLines / 2;
  364.         curLine = 0;
  365.         filterProc = (ProcPtr) TextFilter;
  366.     }
  367.  
  368.     ShowWindow (theDialog);
  369.  
  370.     do {
  371.         ModalDialog (filterProc, &itemNo);
  372.     } while (itemNo != OKButton);
  373.  
  374. /*
  375.     restore hText field of TE record before disposing of it.
  376. */
  377.     (**teHand).hText = oldHText;
  378.     TEDispose (teHand);
  379.  
  380.     if (needScroll)
  381.         DisposeControl (theScroll);
  382.     SetPort (oldPort);
  383.     DisposDialog(theDialog);
  384. }
  385. ---
  386.  
  387.  
  388.