home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / MacPerl ƒ / Perl Source ƒ / MacPerl / MPHelp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-08  |  6.5 KB  |  333 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPHelp.c            -    Various helpful functions
  4. Author    :    Matthias Neeracher
  5. Started    :    09Aug93                                Language    :    MPW C
  6. Modified    :    17Aug93    MN    Use Application directory
  7.                 08Sep93    MN    Corrected some misunderstandings of dbm
  8. Last        :    08Sep93
  9. *********************************************************************/
  10.  
  11. #ifndef RUNTIME
  12.  
  13. #include "MPHelp.h"
  14. #include "MPConsole.h"
  15.  
  16. #include <Balloons.h>
  17. #include <ToolUtils.h>
  18. #include <TFileSpec.h>
  19. #include <ndbm.h>
  20. #include <ctype.h>
  21. #include <PLStringFuncs.h>
  22. #include <Folders.h>
  23. #include <fcntl.h>
  24. #include <ioctl.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27.  
  28. #include "icemalloc.h"
  29.  
  30. static DBM *             OperatorBalloons = nil;
  31. static char                BalloonState = '?';
  32. static FSSpec            BalloonPath;
  33. static _mem_pool_ptr    HelpMem;
  34. static int                SavePoolID;
  35.  
  36. Boolean HasBalloons()
  37. {
  38.     CInfoPBRec    info;
  39.     
  40.     if (!HelpMem)
  41.         if (!(HelpMem = new_malloc_pool(4711, (16 * 1024))))
  42.             return false;
  43.             
  44.     SavePoolID = _default_mem_pool->id;
  45.     set_default_pool(4711);
  46.     
  47.     if (OperatorBalloons)
  48.         return true;
  49.         
  50.     switch (BalloonState) {
  51.     case '+':
  52.         if (OperatorBalloons = dbm_open(FSp2FullPath(&BalloonPath), DBM_RDONLY, 0))
  53.             return true;
  54.     case '?':
  55.         BalloonState             = '+';
  56.         BalloonPath.vRefNum     = gAppVol;
  57.         BalloonPath.parID        = gAppDir;
  58.         PLstrcpy(BalloonPath.name, "\pMacPerl Help");
  59.         
  60.         if (!FSpCatInfo(&BalloonPath, &info)) 
  61.             if (OperatorBalloons = dbm_open(FSp2FullPath(&BalloonPath), DBM_RDONLY, 0))
  62.                 return true;
  63.         
  64.         if (!FindFolder(
  65.                 kOnSystemDisk, 
  66.                 kPreferencesFolderType, 
  67.                 false, 
  68.                 &BalloonPath.vRefNum,
  69.                 &BalloonPath.parID)
  70.             && !FSpCatInfo(&BalloonPath, &info) 
  71.         )     
  72.             if (OperatorBalloons = dbm_open(FSp2FullPath(&BalloonPath), DBM_RDONLY, 0))
  73.                 return true;
  74.         
  75.         BalloonState = '-';
  76.     case '-':
  77.         set_default_pool(SavePoolID);
  78.         return false;
  79.     }
  80. }
  81.  
  82. void HideBalloons()
  83. {
  84.     dbm_close(OperatorBalloons);
  85.         
  86.     OperatorBalloons = nil;
  87.  
  88.     set_default_pool(SavePoolID);
  89. }
  90.  
  91. void DoHelp(WindowPtr win, DPtr doc, Point pt, Boolean inText)
  92. {
  93.     short                    index;
  94.     short                    last;
  95.     short                    length;
  96.     datum                    key;
  97.     datum                    data;
  98.     Ptr                    txt;
  99.     Rect                    r;
  100.     HMMessageRecord    help;
  101.     
  102.     if (!HMGetBalloons() || HMIsBalloon())
  103.         return;
  104.         
  105.     if (inText) {
  106.         index = TEGetOffset(pt, doc->theText);
  107.         length= (*doc->theText)->teLength;
  108.         
  109.         if (index <= 0 || index >= length)
  110.             return;
  111.  
  112.         txt    = *(*doc->theText)->hText;
  113.         
  114.         if (islower(txt[index])) {
  115.             for (last = index+1; last < (*doc->theText)->teLength; last++)
  116.                 if (islower(txt[last]))
  117.                     continue;
  118.                 else if (isalnum(txt[last]))
  119.                     return;
  120.                 else
  121.                     break;
  122.             
  123.             while (index-- > 0) 
  124.                 if (islower(txt[index]))
  125.                     continue;
  126.                 else if (isalnum(txt[index]))
  127.                     return;
  128.                 else
  129.                     break;
  130.             
  131.             ++index;
  132.         } else {
  133.             last = index+1;
  134.         }
  135.         
  136.         if (!HasBalloons())
  137.             return;
  138.  
  139.         HLock((*doc->theText)->hText);
  140.         key.dptr = *(*doc->theText)->hText + index;
  141.         key.dsize = last - index;
  142.         data = dbm_fetch(OperatorBalloons, key);
  143.         HUnlock((*doc->theText)->hText);
  144.         
  145.         HideBalloons();
  146.         
  147.         if (!data.dptr)
  148.             return;
  149.             
  150.         help.hmmHelpType = kHMStringItem;
  151.         help.u.hmmString[0] = data.dsize;
  152.         memcpy(&help.u.hmmString+1, data.dptr, data.dsize);
  153.  
  154.         LocalToGlobal(&pt);
  155.         *(Point *) &r.top = pt;
  156.         *(Point *) &r.bottom = pt;
  157.         InsetRect(&r, -5, -5);
  158.         
  159.         HMShowBalloon(&help, pt, &r, nil, 0, 0, kHMRegularWindow);
  160.     } else {
  161.         r = win->portRect;
  162.         
  163.         r.right = 30;
  164.         r.top   = r.bottom-15;
  165.     
  166.         if (PtInRect(pt, &r)) {
  167.             help.hmmHelpType = kHMStringItem;
  168.             
  169.             switch (doc->lastState) {
  170.             case stateDocument+stateRdWr:
  171.                 index = 1;
  172.                 break;
  173.             case stateDocument+stateRdOnly:
  174.                 index = 2;
  175.                 break;
  176.             case stateConsole+stateRdWr:
  177.                 index = 3;
  178.                 break;
  179.             case stateConsole+stateRdOnly:
  180.                 index = 4;
  181.                 break;
  182.             case stateConsole+stateBlocked:
  183.                 index = 5;
  184.                 break;
  185.             default:
  186.                 return;
  187.             }
  188.             GetIndString(help.u.hmmString, 256, index);
  189.             
  190.             LocalToGlobal((Point *) &r.top);
  191.             LocalToGlobal((Point *) &r.bottom);
  192.             LocalToGlobal(&pt);
  193.             
  194.             HMShowBalloon(&help, pt, &r, nil, 0, 0, kHMRegularWindow);
  195.         }
  196.     }
  197. }
  198.  
  199. typedef struct {
  200.     long    start;
  201.     long    end;
  202. } HelpOffsets;
  203.  
  204. void Explain(DPtr doc)
  205. {
  206.     datum         key;
  207.     datum         data;
  208.     FILE *        help;
  209.     HelpOffsets    offsets;
  210.     Handle        txt;
  211.     char *        text;
  212.     short            pos;
  213.     
  214.     if (!HasBalloons())
  215.         return;
  216.  
  217.     if (doc) {
  218.         TEHandle        te;
  219.         
  220.         te = doc->theText;
  221.             
  222.         if (pos = (*te)->selEnd - (*te)->selStart) {
  223.             HLock((*te)->hText);
  224.             PtrToHand(*(*te)->hText + (*te)->selStart - 1, &txt, pos + 2);
  225.             HUnlock((*te)->hText);
  226.         }
  227.     } else
  228.         pos = 0;
  229.     
  230.     if (!pos) {
  231.         pos = 12;
  232.         PtrToHand("xMacPerl…Help", &txt, pos + 2);
  233.     }
  234.     
  235.     (*txt)[0] = 0;
  236.     (*txt)[pos + 1] = 0;
  237.     
  238.     HLock(txt);
  239.     key.dptr = *txt;
  240.     key.dsize = pos + 1;
  241.     data = dbm_fetch(OperatorBalloons, key);
  242.     
  243.     if (!data.dptr) {
  244.         SysBeep(0);
  245.         
  246.         DisposeHandle(txt);
  247.         HideBalloons();
  248.         return;
  249.     }
  250.  
  251.     help = fopen("Dev:Console:Perl Help", "a");
  252.     
  253.     fprintf(help, "\n------------- %s ---------------\n\n", *txt+1);
  254.     
  255.     DisposeHandle(txt);
  256.     
  257.     memcpy(&offsets, data.dptr, sizeof(HelpOffsets));
  258.     txt        =    NewHandle(offsets.end - offsets.start + 1);
  259.     HLock(txt);
  260.     
  261.     lseek(OperatorBalloons->fd(OperatorBalloons), offsets.start, 0);
  262.     (*txt)[read(OperatorBalloons->fd(OperatorBalloons), *txt, offsets.end - offsets.start)] = 0;
  263.  
  264.     HideBalloons();
  265.     
  266.     for (pos = 0, text = *txt; *text; ) {
  267.         if (!pos && *text == 'æ') {
  268.             if (text[1] == 'C' && isspace(text[2])) {
  269.                 for (text += 3; isspace(*text); ++text);
  270.                 
  271.                 goto nextchar;
  272.             } else if (text[1] == 'K' && text[2] == 'L' && isspace(text[3])) { 
  273.                 for (text += 3; isspace(*text); ++text);
  274.                 
  275.                 for (pos = 0;;++text)
  276.                     switch (*text) {
  277.                     case 'æ':
  278.                         if (pos) {
  279.                             putc(*text, help);
  280.                             ++pos;
  281.                             break;
  282.                         } else {
  283.                             putc('\n', help);
  284.                             pos = 0;
  285.                         
  286.                             goto nextchar;
  287.                         }
  288.                     case 0:
  289.                         if (pos)
  290.                             putc('\n', help);
  291.                         putc('\n', help);
  292.                     
  293.                         goto nextchar;
  294.                     case '\n':
  295.                         if (text[1] == '\n' || !pos || pos >= 30) {
  296.                             putc('\n', help);
  297.                             pos = 0;
  298.                         } else
  299.                             while (pos < 30) {
  300.                                 putc(' ', help);
  301.                                 ++pos;
  302.                             }
  303.                         break;
  304.                     case ' ':
  305.                     case '\t':
  306.                         break;
  307.                     default:
  308.                         putc(*text, help);
  309.                         ++pos;
  310.                         break;
  311.                     }
  312.             } else if (text[1] == 'D' && text[2] == 'T' && isspace(text[3]))
  313.                 for (text += 3; *text; )
  314.                     if (*text++ == '\n') {
  315.                         pos = 0;
  316.                         
  317.                         goto nextchar;
  318.                     }
  319.         }
  320.         putc(*text, help);
  321.             
  322.         pos = (*text++ != '\n');
  323. nextchar:
  324.         ;
  325.     }
  326.     
  327.     ioctl(fileno(help), WIOSELECT, NULL);
  328.     
  329.     fclose(help);
  330.     DisposeHandle(txt);
  331. }    
  332.  
  333. #endif