home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / MacPerl / MPHelp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-14  |  6.8 KB  |  347 lines

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