home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 February / macformat-047.iso / Shareware Plus / Utilities / ICeTEe 2 folder / source / ICeTEe.c < prev   
Encoding:
C/C++ Source or Header  |  1996-11-19  |  11.7 KB  |  516 lines  |  [TEXT/CWIE]

  1. /*    NAME:
  2.         ICeTEe.c
  3.  
  4.     WRITTEN BY:
  5.         Michael Schürig
  6.                 
  7.     DESCRIPTION:
  8.         This file contains a code resource to be installed as a Trap Patch.
  9.  
  10.     NOTES:
  11.         This code is applied as a patch to TEClick.
  12.         If text is command clicked it's launched as a URL with the appropriate
  13.         helper application.
  14.  
  15.     ___________________________________________________________________________
  16. */
  17. //=============================================================================
  18. //        Include files                                                                     
  19. //-----------------------------------------------------------------------------
  20. #include <Gestalt.h>
  21. #include <ToolUtils.h>
  22. #include <Processes.h>
  23. #include <TextEdit.h>
  24. #include <Notification.h>
  25. #include <LowMem.h>
  26. #include <AppleEvents.h>
  27. #include <ICTypes.h>
  28. #include <ICCAPI.h>
  29. #include <ICKeys.h>
  30. #include "A4Stuff.h"
  31. #include "SetupA4.h"
  32. #include "SignatureToApp.h"
  33. #include "ICeTEe Constants.h"
  34. #include "ICeTEe AddrsTable.h"
  35.  
  36.  
  37. //=============================================================================
  38. //        Private defines                                                                 
  39. //-----------------------------------------------------------------------------
  40. #define strMiscErr                1
  41. #define strNoCMErr                2
  42. #define strNoICErr                3
  43. #define strInsufficientICErr    4
  44. #define strNoMemoryErr            5
  45. #define strCantFindHelperErr    6
  46. #define strNoHelperErr            7
  47. #define strNoURLErr                8
  48. #define strCantHackIt            9
  49.  
  50. #define kICBookmarkHelper        "\pHelper•bookmark"
  51.  
  52. #define kCommandKey 55
  53. #define kOptionKey 58
  54.  
  55. #define KeyIsDown(k)( ( (km.arr)[k>>3] >> (k & 7) ) & 1)
  56.  
  57. //=============================================================================
  58. //        Types                                                                 
  59. //-----------------------------------------------------------------------------
  60. typedef pascal void (*TEClickProcPtr)(Point pt, Boolean fExtend, TEHandle teH);
  61. typedef    union {
  62.     UInt8    arr[16];
  63.     KeyMap    map;
  64. } KeyMapArr;
  65.  
  66.  
  67. //=============================================================================
  68. //        Global Variables                                                                 
  69. //-----------------------------------------------------------------------------
  70. TEClickProcPtr    gPrevTEClick;
  71. Handle            gExclusions;
  72. Handle            gErrors;
  73. AEEventClass    gBkEventClass;
  74. AEEventID        gBkEventID;
  75. Boolean            gAlreadyRan = false;
  76.  
  77.  
  78. //=============================================================================
  79. //        Private function prototypes                             
  80. //-----------------------------------------------------------------------------
  81. pascal    void main(Point pt, Boolean fExtend, TEHandle teH);
  82. Boolean    CurrentProcessExcluded(Handle exclusions);
  83. void    MyTEClick(TEHandle teH, short oldSelStart, short oldSelEnd, Boolean makeBookmark);
  84. ICError    DoCommandClick(TEHandle teH, long selStart, long selEnd, Boolean makeBookmark);
  85. pascal ICError AddBookmark(internetConfigurationComponent inst, Ptr urlP, long len);
  86. void    GetIndStrH(Str255 s, Handle h, short index);
  87. pascal void    MyNMResponseProc(NMRecPtr nm);
  88.  
  89.  
  90. //=============================================================================
  91. //        CurrentProcessExcluded : Check if URL clicking is disabled for this app.                                                                 
  92. //-----------------------------------------------------------------------------
  93. Boolean CurrentProcessExcluded(Handle exclusions)
  94. {
  95.     ProcessSerialNumber    PSN;
  96.     ProcessInfoRec        info;
  97.     int                    i;
  98.     Boolean                exclude = true;
  99.  
  100. #if qDebug >= 2
  101.     DebugStr("\pCurrentProcessExcluded entered");
  102. #endif
  103.  
  104.     PSN.highLongOfPSN = 0;
  105.     PSN.lowLongOfPSN = kCurrentProcess;
  106.     
  107.     info.processInfoLength = sizeof(ProcessInfoRec);
  108.     info.processName = nil;
  109.     info.processAppSpec = nil;
  110.     
  111.     if ( GetProcessInformation(&PSN, &info) == noErr )
  112.     {
  113.         exclude = false;
  114.         for (i = 0; i < GetHandleSize(exclusions) / sizeof(OSType); i++)
  115.         {
  116.             if ( (* (OSType **)exclusions)[i] == info.processSignature )
  117.             {
  118.                 exclude = true;
  119.                 break;
  120.             }
  121.         }
  122.     }
  123.  
  124. #if qDebug >= 2
  125.     DebugStr("\pCurrentProcessExcluded exit");
  126. #endif
  127.  
  128.     return(exclude);
  129. }
  130.  
  131.  
  132. //=============================================================================
  133. //        GetIndStrH : GetIndString analog for Handles instead of Resources.                                             
  134. //-----------------------------------------------------------------------------
  135. void    GetIndStrH(Str255 str, Handle h, short index)
  136. {
  137. #if qDebug >= 2
  138.     DebugStr("\pGetIndStrH entered");
  139. #endif
  140.  
  141.     if (h != nil)
  142.     {
  143.         short        count;
  144.         short        i;
  145.         StringPtr    strP;
  146.  
  147.         count = **(short**)h;
  148.         
  149.         if ( 1 <= index && index <= count )
  150.         {
  151.             strP = (StringPtr)*h + sizeof(short);
  152.             
  153.             for (i = 1; i < index; i++)
  154.             {
  155.                 strP += StrLength(strP) + 1;
  156.             }
  157.             BlockMoveData(strP, str, StrLength(strP) + 1);
  158.         }
  159.         else
  160.         {
  161.             str[0] = 0;
  162.         }
  163.     }
  164.     else
  165.     {
  166.             str[0] = 0;
  167.     }
  168.     
  169. #if qDebug >= 2
  170.     DebugStr("\pGetIndStrH exit");
  171. #endif
  172. }
  173.  
  174.  
  175. //=============================================================================
  176. //        MyNMResponseProc : Notification response & cleanup.                                                                 
  177. //-----------------------------------------------------------------------------
  178. pascal void    MyNMResponseProc(NMRecPtr nm)
  179. {
  180.     THz        oldZone;
  181.     Handle    strH;
  182.  
  183.     NMRemove(nm);
  184.  
  185.     oldZone = GetZone();
  186.     SetZone(SystemZone());
  187.     
  188.     strH = RecoverHandle((Ptr)(nm->nmStr));
  189.     if (strH != nil)
  190.         DisposeHandle(strH);
  191.  
  192.     DisposePtr((Ptr)nm);    
  193.     
  194.     SetZone(oldZone);
  195. }
  196.  
  197.  
  198. //=============================================================================
  199. //        MyTEClick : TEClick addition.                                                                 
  200. //-----------------------------------------------------------------------------
  201. void    MyTEClick(TEHandle teH, short oldSelStart, short oldSelEnd, Boolean makeBookmark)
  202. {
  203.     ICError            err;
  204.     
  205. #if qDebug >= 1
  206.     DebugStr("\pMyTEClick entered");
  207. #endif
  208.  
  209.     if ( !CurrentProcessExcluded(gExclusions) )
  210.     {
  211.         
  212.         if ( !(        (oldSelStart <= (**teH).selStart) && ((**teH).selStart <= oldSelEnd)
  213.                 &&    (oldSelStart <= (**teH).selEnd) && ((**teH).selEnd <= oldSelEnd) ) )
  214.         {
  215.             oldSelStart = (**teH).selStart;
  216.             oldSelEnd = (**teH).selEnd;
  217.         }
  218.         
  219.         err = DoCommandClick(teH, oldSelStart, oldSelEnd, makeBookmark);
  220.         
  221.         if (err != noErr)
  222.         {
  223.             Str255            errStr;
  224.             StringHandle    errStrH;
  225.             short            errStrIdx;
  226.             Str32            errNumStr;
  227.             NMRecPtr        nm;
  228.             
  229.             switch (err) {
  230.             
  231.                 case badComponentInstance:
  232.                     errStrIdx = strNoCMErr;
  233.                     break;
  234.                 case badComponentSelector:
  235.                     errStrIdx = strInsufficientICErr;
  236.                     break;
  237.                 case memFullErr:
  238.                     errStrIdx = strNoMemoryErr;
  239.                     break;
  240.                 case afpItemNotFound:
  241.                     errStrIdx = strCantFindHelperErr;
  242.                     break;
  243.                 case icPrefNotFoundErr:
  244.                     errStrIdx = strNoHelperErr;
  245.                     break;
  246.                 case icNoURLErr:
  247.                     errStrIdx = strNoURLErr;
  248.                     break;
  249.                 case noPortErr:
  250.                     errStrIdx = strCantHackIt;
  251.                     break;
  252.                 default:
  253.                     errStrIdx = strMiscErr;
  254.                     break;
  255.             }
  256.             
  257.             GetIndStrH(errStr, gErrors, errStrIdx);
  258.             errStrH = NewString(errStr);
  259.  
  260.             NumToString(err, errNumStr);
  261.             
  262.             Munger((Handle)errStrH, 0, "^0", 2, &errNumStr[1], StrLength(errNumStr));
  263.             
  264.             HLock((Handle)errStrH);
  265.             
  266.             nm = (NMRecPtr)NewPtrSysClear(sizeof(NMRec));
  267.             if (nm != nil)
  268.             {
  269.                 nm->qType = nmType;
  270.                 nm->nmMark = 0;
  271.                 nm->nmIcon = nil;
  272.                 nm->nmSound = nil;
  273.                 nm->nmStr = *errStrH;
  274.                 nm->nmResp = MyNMResponseProc;
  275.                 err = NMInstall(nm);
  276.             }
  277.             else
  278.             {
  279.                 SysBeep(10);
  280.                 DisposeHandle((Handle)errStrH);
  281.             }
  282.         }
  283.     }
  284.         
  285.         
  286. #if qDebug >= 1
  287.     DebugStr("\pMyTEClick exit");
  288. #endif
  289.  
  290. }
  291.  
  292.  
  293. //=============================================================================
  294. //        DoCommandClick : Handle the click.                                                                 
  295. //-----------------------------------------------------------------------------
  296. ICError    DoCommandClick(TEHandle teH, long selStart, long selEnd, Boolean makeBookmark)
  297. {
  298.     ComponentInstance    inst;
  299.     ICError                err, err2;
  300.  
  301.     
  302. #if qDebug >= 1
  303.     DebugStr("\pDoCommandClick entered");
  304. #endif
  305.  
  306.     err = ICCStart(&inst, kCreator);
  307.  
  308.     if (err == noErr)
  309.     {
  310.         err = ICCFindConfigFile(inst, 0, nil);
  311.         if (err == noErr)
  312.         {
  313.             Handle        textH;
  314.             SInt8        s;
  315.             StringPtr    hint, at;
  316.             Handle        urlH;
  317.                 
  318.             
  319.             textH = (Handle)TEGetText(teH);
  320.             s = HGetState(textH);
  321.             HLock(textH);
  322.         
  323.             urlH = NewHandle(0);
  324.             
  325.             hint = "\pmailto";
  326.             
  327.             err = ICCParseURL(inst, hint, *textH, GetHandleSize(textH), &selStart, &selEnd, urlH);
  328.             
  329.             if (err == noErr)
  330.             {
  331.                 hint = "\p";
  332.                 at = "\p@";
  333.                 
  334.                 if ( Munger(urlH, 0, &at[1], StrLength(at), nil, 0) >= 0 )
  335.                 {
  336.                     hint = "\pmailto";
  337.                 }
  338.                 
  339.                 if (makeBookmark)
  340.                 {
  341.                     err = AddBookmark(inst, (*textH) + selStart, selEnd - selStart);
  342.                 }
  343.                 else
  344.                 {
  345.                     err = ICCLaunchURL(inst, hint, *textH, GetHandleSize(textH), &selStart, &selEnd);
  346.                 }
  347.             }
  348.             
  349.             DisposeHandle(urlH);
  350.             
  351.             TESetSelect(selStart, selEnd, teH);
  352.             
  353.             if (err == noErr)
  354.             {
  355.                 SInt32    junk;
  356.                 SInt16    i = LMGetMenuFlash();
  357.                 
  358.                 while (i--)
  359.                 {
  360.                     Delay(5, &junk);
  361.                     TEDeactivate(teH);
  362.                     Delay(5, &junk);
  363.                     TEActivate(teH);                    
  364.                 }
  365.             }
  366.             HSetState(textH, s);
  367.         }
  368.         err2 = ICCStop(inst);
  369.         
  370.         if (err == noErr)
  371.             err = err2;
  372.     }
  373.  
  374. #if qDebug >= 1
  375.     DebugStr("\pDoCommandClick exit");
  376. #endif
  377.  
  378.     return(err);
  379. }
  380.  
  381.  
  382. //=============================================================================
  383. //        AddBookmark : Send a bookmark event to the bookmark app.                                 
  384. //-----------------------------------------------------------------------------
  385. pascal ICError AddBookmark(internetConfigurationComponent inst, Ptr urlP, long len)
  386. {
  387.     ICAttr                junkAttr;
  388.     ICAppSpec            bookmHelper;
  389.     long                helperSize;
  390.     ProcessSerialNumber    psn;
  391.     ICError                err;
  392.     
  393. #if qDebug >= 1
  394.     DebugStr("\pAddBookmark entered");
  395. #endif
  396.  
  397.     helperSize = sizeof(bookmHelper);
  398.     err = ICCGetPref(inst, kICBookmarkHelper, &junkAttr, (void *)&bookmHelper, &helperSize);
  399.     
  400.  
  401.     err = SignatureToApp(bookmHelper.fCreator, nil, &psn, nil, nil,
  402.                         Sig2App_LaunchApplication, launchContinue | launchDontSwitch);
  403.  
  404.  
  405.     if (err == noErr)
  406.     {
  407.         AEAddressDesc    target;
  408.         
  409.         err = AECreateDesc(typeProcessSerialNumber, &psn, sizeof(psn), &target);
  410.         if (err == noErr)
  411.         {
  412.             AppleEvent        theEvent;
  413.     
  414.             err = AECreateAppleEvent(gBkEventClass, gBkEventID, &target, kAutoGenerateReturnID, kAnyTransactionID, &theEvent);        
  415.             if (err == noErr)
  416.             {
  417.                 char *u = urlP;
  418.                 long l = len;
  419.                 
  420.                 if (u[0] == '<')
  421.                 {
  422.                     u++;
  423.                     l--;
  424.                 }
  425.                 if (u[l-1] == '>')
  426.                     l--;
  427.                 
  428.                 err = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, u, l);
  429.                 if (err == noErr)
  430.                 {
  431.                     AppleEvent    reply;
  432.                     err = AESend(&theEvent, &reply, kAENoReply, kAEHighPriority, kNoTimeOut, nil, nil);
  433.                 }                
  434.                 AEDisposeDesc(&theEvent);
  435.             }
  436.             AEDisposeDesc(&target);
  437.         }
  438.     }
  439. #if qDebug >= 1
  440.     DebugStr("\pAddBookmark exit");
  441. #endif
  442.  
  443.     return err;
  444. }
  445.  
  446.  
  447. //=============================================================================
  448. //        main : Entry point to our code resource.                                                                 
  449. //-----------------------------------------------------------------------------
  450. pascal void main(Point pt, Boolean fExtend, TEHandle teH)
  451. {
  452.     long                oldA4;
  453.     short                oldSelStart, oldSelEnd;
  454.     KeyMapArr            km;
  455.     Boolean                commandKey;
  456.     Boolean                optionKey;
  457.     
  458.     // Set up A4
  459. #ifndef powerc
  460.     oldA4 = SetCurrentA4();
  461. #endif
  462.     
  463. #if qDebug >= 2
  464.     DebugStr("\pICeTEe entered");
  465. #endif
  466.  
  467.     // Save old selection    
  468.     oldSelStart = (**teH).selStart;
  469.     oldSelEnd = (**teH).selEnd;
  470.     
  471.     // Get modifier keys
  472.     GetKeys(km.map);
  473.     commandKey = KeyIsDown(kCommandKey);
  474.     optionKey = KeyIsDown(kOptionKey);
  475.     
  476.         
  477.     // If we've not already been called, do our one time initialisation stuff
  478.     if (!gAlreadyRan)
  479.     {
  480.         ICeTEeAddressTable    *theAddressTable;
  481.         
  482.         Gestalt(kICeTEeAddressTable, (long *) &theAddressTable);        
  483.         gPrevTEClick    = (TEClickProcPtr) ((long) theAddressTable->theTable[kTEClick]);
  484.         gExclusions        = theAddressTable->exclusions;
  485.         gErrors            = theAddressTable->errors;
  486.         gBkEventClass    = theAddressTable->bkEventClass;
  487.         gBkEventID        = theAddressTable->bkEventID;
  488.         gAlreadyRan        = true;
  489.     }
  490.  
  491.     // Call the original TEClick()
  492.     gPrevTEClick(pt, fExtend, teH);
  493.  
  494.     // Do our thing
  495.     if (commandKey)
  496.     {
  497.         THz    oldZone;
  498.  
  499.         oldZone = GetZone();
  500.         SetZone(SystemZone());
  501.         
  502.         MyTEClick(teH, oldSelStart, oldSelEnd, optionKey);
  503.         
  504.         SetZone(oldZone);
  505.     }
  506.  
  507. #if qDebug >= 2
  508.     DebugStr("\pICeTEe exit");
  509. #endif
  510.  
  511.     // Restore A4 and return
  512. #ifndef powerc
  513.     SetA4(oldA4);
  514. #endif
  515. }
  516.