home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Snippets / Help / Help.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-02  |  8.9 KB  |  280 lines  |  [TEXT/MMCC]

  1. /* =============================================================
  2.    ======================= Help.c ==============================
  3.    =============================================================
  4.    
  5.    ©1994 by Thomas Reed
  6.    Written using Metrowerks CodeWarrior 4
  7.    
  8.    Please do not distribute modified versions of this code.
  9.    
  10.    If you decide to use this code in a program without making significant
  11.    changes, I don't ask for much -- just mention my name in the About box or
  12.    in a Read Me file (since About box real estate can be valuable!  ;-)
  13.    
  14.    To use Help.c, simply add it to your project.  (Don't use #include,
  15.    choose Add... from the Source menu.)
  16.    
  17.    Here's what you need to do to use it:
  18.    
  19.    1)  #include the header "Help.h" in your project.
  20.    
  21.    2)  Put a 'STR#' resource into the project's resource fork.  Then,
  22.        change the kUtilStrings constant to the ID number of this resource.
  23.    
  24.    3)  Insert as the first string in the resource the title you'd like
  25.        displayed in the title bar of the Help window.
  26.        
  27.    4)  Put a 'TEXT' resource into the project's resource, and type in the
  28.        text you want to appear in the Help window's scrollable text field.
  29.        
  30.    5)  If the ID of this 'TEXT' resource isn't 128, change the kHelpTextID
  31.        constant to the correct ID.
  32.        
  33.    6)  When you want the Help window to be displayed, call DoHelp(?).
  34.        DoHelp will handle all the events until the user clicks the Done
  35.        button or presses return.  If you want to play a sound when the
  36.        help window appears, pass it's ID to DoHelp, otherwise pass 0.  Also,
  37.        you must add the following line to the prefix of your program:
  38.        (Choose Options & go to Prefix)
  39.        
  40.          #define USE_HELP_SOUNDS 1
  41.        
  42.        Lastly, you must include my Sounds.c library in your program.
  43.        
  44.        You must also pass a pointer to an update procedure that must be
  45.        defined like this:
  46.        
  47.          void (*UpdateProc) (EventRecord *event)
  48.        
  49.    That's all there is to it!  Hope you like it!
  50.    
  51.    ==============================================================
  52.    
  53.    ============================================================== */
  54.  
  55. #include "Help.h"
  56.  
  57. pascal MyAction(ControlHandle myControl, short partCode);
  58.  
  59. #define NIL  0L
  60. #define MAXLONG 0x7FFFFFFF
  61.  
  62. #define kEnter        (char) 0x03
  63. #define kReturn        (char) 0x0D
  64.  
  65. #define kUtilStrings        128
  66. #define kHelpWTitleString    1
  67.  
  68. #define kHelpTextID            128
  69.  
  70. #define kHelpSound            128
  71.  
  72. pascal MyAction(ControlHandle myControl, short partCode)
  73. {
  74.   short            oldCtlVal, newCtlVal, temp, lHeight, i, maxVal;
  75.   long            numLines;
  76.   TEHandle        textH;
  77.   TEStyleHandle    styleH;
  78.  
  79.   if ((partCode > 0) && (partCode != inThumb))
  80.   {
  81.     textH = (TEHandle) (*myControl)->contrlRfCon;
  82.     styleH = GetStylHandle(textH);
  83.     oldCtlVal = GetCtlValue(myControl);
  84.     switch (partCode)
  85.     {
  86.       case inUpButton: 
  87.         i = oldCtlVal - 1;
  88.         temp = 0;
  89.         if (i < 1)
  90.           i = 1;
  91.         else
  92.           temp = (*(*styleH)->lhTab)[i - 1].lhHeight;
  93.         break;
  94.       case inDownButton: 
  95.         i = oldCtlVal + 1;
  96.         temp = 0;
  97.         if (i > GetCtlMax(myControl))
  98.           i = GetCtlMax(myControl);
  99.         else
  100.           temp = (*(*styleH)->lhTab)[i - 2].lhHeight;
  101.         break;
  102.       case inPageUp: 
  103.         temp = 0;
  104.         i = oldCtlVal - 2;
  105.         while ((i >= 0) && (temp + (*(*styleH)->lhTab)[i].lhHeight <= (*textH)->viewRect.bottom - (*textH)->viewRect.top))
  106.         {
  107.           temp = temp + (*(*styleH)->lhTab)[i].lhHeight;
  108.           i--;
  109.         }
  110.         i = i + 2;
  111.         break;
  112.       case inPageDown: 
  113.         temp = 0;
  114.         i = oldCtlVal - 1;
  115.         maxVal = GetCtlMax(myControl);
  116.         while ((i < maxVal - 1) && (temp + (*(*styleH)->lhTab)[i].lhHeight <= (*textH)->viewRect.bottom - (*textH)->viewRect.top))
  117.         {
  118.           temp = temp + (*(*styleH)->lhTab)[i].lhHeight;
  119.           i++;
  120.         }
  121.         i++;
  122.         break;
  123.     }  /* end of switch */
  124.     SetCtlValue(myControl, i);
  125.     newCtlVal = i;
  126.     lHeight = 0;
  127.     if (oldCtlVal < newCtlVal)
  128.       lHeight = -temp;
  129.     else
  130.       lHeight = temp;
  131.     TEScroll(0, lHeight, textH);
  132.   }  /* end if */
  133. }  /* end MyAction */
  134.  
  135. void DoHelp(short soundID, void (*UpdateProc) (EventRecord *event))
  136. {
  137.   WindowPtr            helpWindow, whichWindow;
  138.   Rect                tempRect, txRect;
  139.   short                top, left, i, lHeight, temp;
  140.   Handle            myText;
  141.   TEHandle            textH;
  142.   TEStyleHandle        styleH;
  143.   StScrpHandle        styleScrp;
  144.   ControlHandle        scrollControl, buttonControl, whichControl;
  145.   EventRecord        myEvent;
  146.   short                controlPart, oldCtlVal, newCtlVal;
  147.   long                numLines;
  148.   Point                thePt;
  149.   ProcPtr            myProc;
  150.   Boolean            done;
  151.   long                numTicks;
  152.   Str255            title;
  153.   short                whereClicked, radius;
  154.   char                key;
  155.   
  156.   GDHandle            oldDevice;
  157.   CGrafPtr            oldPort;
  158.       
  159.   GetGWorld(&oldPort, &oldDevice);
  160.  
  161.   myProc = (ProcPtr) &MyAction;
  162.   left = (qd.screenBits.bounds.right - 350) / 2;
  163.   top = (qd.screenBits.bounds.bottom - 250) / 2;
  164.   SetRect(&tempRect, left, top, left + 350, top + 262);
  165.   GetIndString(title, kUtilStrings, kHelpWTitleString);
  166.   helpWindow = NewWindow(NIL, &tempRect, title, TRUE, noGrowDocProc, (WindowPtr) -1, TRUE, 0);
  167.   SetPort(helpWindow);
  168.   myText = GetResource('TEXT', kHelpTextID);
  169.   SetRect(&txRect, 0, 0, qd.thePort->portRect.right - 15, qd.thePort->portRect.bottom);
  170.   textH = TEStylNew(&txRect, &txRect);
  171.   InsetRect(&(*textH)->destRect, 3, 3);
  172.   InsetRect(&(*textH)->viewRect, 3, 3);
  173.   styleScrp = (StScrpHandle) GetResource('styl', kHelpTextID);
  174.   TEStylInsert(*myText, SizeResource(myText), styleScrp, textH);
  175.   styleH = GetStylHandle(textH);
  176.   SetRect(&tempRect, txRect.right, txRect.top - 1, txRect.right + 16, txRect.bottom + 1);
  177.   temp = 0;
  178.   i = 1;
  179.   while ((i - 1 >= 0) && (temp + (*(*styleH)->lhTab)[i - 1].lhHeight <= (*textH)->viewRect.bottom - (*textH)->viewRect.top))
  180.   {
  181.     temp = temp + (*(*styleH)->lhTab)[i - 1].lhHeight;
  182.     i++;
  183.   }
  184.   numLines = i;
  185.   scrollControl = NewControl(helpWindow, &tempRect, "\p", TRUE, 1, 1, (*textH)->nLines - numLines + 2, scrollBarProc, 0);
  186.   (*scrollControl)->contrlRfCon = (long) textH;
  187.   if (i < 0)
  188.     HiliteControl(scrollControl, 255);
  189.   
  190.   #ifdef USE_HELP_SOUNDS
  191.     if (soundID != 0)
  192.     {
  193.       InitChan();
  194.       PlayResFromDisk(soundID, 30);
  195.     }
  196.   #endif
  197.  
  198.   done = FALSE;
  199.   while (!done)
  200.   {
  201.     #ifdef USE_HELP_SOUNDS
  202.       if (soundID != 0)
  203.         IdleSounds();
  204.     #endif
  205.     if (GetNextEvent(everyEvent, &myEvent))
  206.       switch (myEvent.what)
  207.       {
  208.         case keyDown:
  209.         case autoKey:
  210.           key = myEvent.message & charCodeMask;
  211.           if (((key == 'w') || (key == 'W')) && (myEvent.modifiers & cmdKey))
  212.             done = TRUE;
  213.           else
  214.             SysBeep(1);
  215.           break;
  216.         case mouseDown:
  217.           whereClicked = FindWindow(myEvent.where, &whichWindow);
  218.           if (whichWindow == helpWindow)
  219.             switch (whereClicked)
  220.             {
  221.               case inContent:
  222.                 thePt = myEvent.where;
  223.                 GlobalToLocal(&thePt);
  224.                 controlPart = FindControl(thePt, helpWindow, &whichControl);
  225.                 if (controlPart == inThumb)
  226.                 {
  227.                   oldCtlVal = GetCtlValue(scrollControl);
  228.                   controlPart = TrackControl(whichControl, thePt, NIL);
  229.                   newCtlVal = GetCtlValue(scrollControl);
  230.                   lHeight = 0;
  231.                   if (oldCtlVal < newCtlVal)
  232.                     for (i = oldCtlVal - 1; i <= newCtlVal - 2; i++)
  233.                       lHeight = lHeight - (*(*styleH)->lhTab)[i].lhHeight;
  234.                   else
  235.                     for (i = newCtlVal - 1; i <= oldCtlVal - 2; i++)
  236.                       lHeight = lHeight + (*(*styleH)->lhTab)[i].lhHeight;
  237.                   TEScroll(0, lHeight, textH);
  238.                 }
  239.                 else
  240.                   if (controlPart > 0)
  241.                     controlPart = TrackControl(whichControl, thePt, NewControlActionProc(myProc));
  242.                 break;
  243.               case inDrag:
  244.                 DragWindow(helpWindow, myEvent.where, &qd.screenBits.bounds);
  245.                 break;
  246.               case inGoAway:
  247.                 if (TrackGoAway(helpWindow, myEvent.where))
  248.                   done = TRUE;
  249.                 break;
  250.               default:
  251.                 SysBeep(1);
  252.             }  /* end switch */
  253.           break;
  254.         case updateEvt:
  255.           if ((WindowPtr) myEvent.message == helpWindow)
  256.           {
  257.             PenNormal();
  258.             BeginUpdate(helpWindow);
  259.             TEUpdate(&(*textH)->viewRect, textH);
  260.             DrawControls(helpWindow);
  261.             EndUpdate(helpWindow);
  262.           }
  263.           else
  264.             UpdateProc(&myEvent);
  265.           break;
  266.       }  /* end switch */
  267.   }  /* end while */
  268.   DisposeControl(scrollControl);
  269.   TEDispose(textH);
  270.   DisposeWindow(helpWindow);
  271.   ReleaseResource(myText);
  272.   ReleaseResource((Handle) styleScrp);
  273.   
  274.   SetGWorld(oldPort, oldDevice);
  275.   
  276.   #ifdef USE_HELP_SOUNDS
  277.     if (soundID != 0)
  278.       KillSounds();
  279.   #endif
  280. }