home *** CD-ROM | disk | FTP | other *** search
- /* NAME:
- ICeTEe.c
-
- WRITTEN BY:
- Michael Schürig
-
- DESCRIPTION:
- This file contains a code resource to be installed as a Trap Patch.
-
- NOTES:
- This code is applied as a patch to TEClick.
- If text is command clicked it's launched as a URL with the appropriate
- helper application.
-
- ___________________________________________________________________________
- */
- //=============================================================================
- // Include files
- //-----------------------------------------------------------------------------
- #include <Gestalt.h>
- #include <ToolUtils.h>
- #include <Processes.h>
- #include <TextEdit.h>
- #include <Notification.h>
- #include <LowMem.h>
- #include <AppleEvents.h>
- #include <ICTypes.h>
- #include <ICCAPI.h>
- #include <ICKeys.h>
- #include "A4Stuff.h"
- #include "SetupA4.h"
- #include "SignatureToApp.h"
- #include "ICeTEe Constants.h"
- #include "ICeTEe AddrsTable.h"
-
-
- //=============================================================================
- // Private defines
- //-----------------------------------------------------------------------------
- #define strMiscErr 1
- #define strNoCMErr 2
- #define strNoICErr 3
- #define strInsufficientICErr 4
- #define strNoMemoryErr 5
- #define strCantFindHelperErr 6
- #define strNoHelperErr 7
- #define strNoURLErr 8
- #define strCantHackIt 9
-
- #define kICBookmarkHelper "\pHelper•bookmark"
-
- #define kCommandKey 55
- #define kOptionKey 58
-
- #define KeyIsDown(k)( ( (km.arr)[k>>3] >> (k & 7) ) & 1)
-
- //=============================================================================
- // Types
- //-----------------------------------------------------------------------------
- typedef pascal void (*TEClickProcPtr)(Point pt, Boolean fExtend, TEHandle teH);
- typedef union {
- UInt8 arr[16];
- KeyMap map;
- } KeyMapArr;
-
-
- //=============================================================================
- // Global Variables
- //-----------------------------------------------------------------------------
- TEClickProcPtr gPrevTEClick;
- Handle gExclusions;
- Handle gErrors;
- AEEventClass gBkEventClass;
- AEEventID gBkEventID;
- Boolean gAlreadyRan = false;
-
-
- //=============================================================================
- // Private function prototypes
- //-----------------------------------------------------------------------------
- pascal void main(Point pt, Boolean fExtend, TEHandle teH);
- Boolean CurrentProcessExcluded(Handle exclusions);
- void MyTEClick(TEHandle teH, short oldSelStart, short oldSelEnd, Boolean makeBookmark);
- ICError DoCommandClick(TEHandle teH, long selStart, long selEnd, Boolean makeBookmark);
- pascal ICError AddBookmark(internetConfigurationComponent inst, Ptr urlP, long len);
- void GetIndStrH(Str255 s, Handle h, short index);
- pascal void MyNMResponseProc(NMRecPtr nm);
-
-
- //=============================================================================
- // CurrentProcessExcluded : Check if URL clicking is disabled for this app.
- //-----------------------------------------------------------------------------
- Boolean CurrentProcessExcluded(Handle exclusions)
- {
- ProcessSerialNumber PSN;
- ProcessInfoRec info;
- int i;
- Boolean exclude = true;
-
- #if qDebug >= 2
- DebugStr("\pCurrentProcessExcluded entered");
- #endif
-
- PSN.highLongOfPSN = 0;
- PSN.lowLongOfPSN = kCurrentProcess;
-
- info.processInfoLength = sizeof(ProcessInfoRec);
- info.processName = nil;
- info.processAppSpec = nil;
-
- if ( GetProcessInformation(&PSN, &info) == noErr )
- {
- exclude = false;
- for (i = 0; i < GetHandleSize(exclusions) / sizeof(OSType); i++)
- {
- if ( (* (OSType **)exclusions)[i] == info.processSignature )
- {
- exclude = true;
- break;
- }
- }
- }
-
- #if qDebug >= 2
- DebugStr("\pCurrentProcessExcluded exit");
- #endif
-
- return(exclude);
- }
-
-
- //=============================================================================
- // GetIndStrH : GetIndString analog for Handles instead of Resources.
- //-----------------------------------------------------------------------------
- void GetIndStrH(Str255 str, Handle h, short index)
- {
- #if qDebug >= 2
- DebugStr("\pGetIndStrH entered");
- #endif
-
- if (h != nil)
- {
- short count;
- short i;
- StringPtr strP;
-
- count = **(short**)h;
-
- if ( 1 <= index && index <= count )
- {
- strP = (StringPtr)*h + sizeof(short);
-
- for (i = 1; i < index; i++)
- {
- strP += StrLength(strP) + 1;
- }
- BlockMoveData(strP, str, StrLength(strP) + 1);
- }
- else
- {
- str[0] = 0;
- }
- }
- else
- {
- str[0] = 0;
- }
-
- #if qDebug >= 2
- DebugStr("\pGetIndStrH exit");
- #endif
- }
-
-
- //=============================================================================
- // MyNMResponseProc : Notification response & cleanup.
- //-----------------------------------------------------------------------------
- pascal void MyNMResponseProc(NMRecPtr nm)
- {
- THz oldZone;
- Handle strH;
-
- NMRemove(nm);
-
- oldZone = GetZone();
- SetZone(SystemZone());
-
- strH = RecoverHandle((Ptr)(nm->nmStr));
- if (strH != nil)
- DisposeHandle(strH);
-
- DisposePtr((Ptr)nm);
-
- SetZone(oldZone);
- }
-
-
- //=============================================================================
- // MyTEClick : TEClick addition.
- //-----------------------------------------------------------------------------
- void MyTEClick(TEHandle teH, short oldSelStart, short oldSelEnd, Boolean makeBookmark)
- {
- ICError err;
-
- #if qDebug >= 1
- DebugStr("\pMyTEClick entered");
- #endif
-
- if ( !CurrentProcessExcluded(gExclusions) )
- {
-
- if ( !( (oldSelStart <= (**teH).selStart) && ((**teH).selStart <= oldSelEnd)
- && (oldSelStart <= (**teH).selEnd) && ((**teH).selEnd <= oldSelEnd) ) )
- {
- oldSelStart = (**teH).selStart;
- oldSelEnd = (**teH).selEnd;
- }
-
- err = DoCommandClick(teH, oldSelStart, oldSelEnd, makeBookmark);
-
- if (err != noErr)
- {
- Str255 errStr;
- StringHandle errStrH;
- short errStrIdx;
- Str32 errNumStr;
- NMRecPtr nm;
-
- switch (err) {
-
- case badComponentInstance:
- errStrIdx = strNoCMErr;
- break;
- case badComponentSelector:
- errStrIdx = strInsufficientICErr;
- break;
- case memFullErr:
- errStrIdx = strNoMemoryErr;
- break;
- case afpItemNotFound:
- errStrIdx = strCantFindHelperErr;
- break;
- case icPrefNotFoundErr:
- errStrIdx = strNoHelperErr;
- break;
- case icNoURLErr:
- errStrIdx = strNoURLErr;
- break;
- case noPortErr:
- errStrIdx = strCantHackIt;
- break;
- default:
- errStrIdx = strMiscErr;
- break;
- }
-
- GetIndStrH(errStr, gErrors, errStrIdx);
- errStrH = NewString(errStr);
-
- NumToString(err, errNumStr);
-
- Munger((Handle)errStrH, 0, "^0", 2, &errNumStr[1], StrLength(errNumStr));
-
- HLock((Handle)errStrH);
-
- nm = (NMRecPtr)NewPtrSysClear(sizeof(NMRec));
- if (nm != nil)
- {
- nm->qType = nmType;
- nm->nmMark = 0;
- nm->nmIcon = nil;
- nm->nmSound = nil;
- nm->nmStr = *errStrH;
- nm->nmResp = MyNMResponseProc;
- err = NMInstall(nm);
- }
- else
- {
- SysBeep(10);
- DisposeHandle((Handle)errStrH);
- }
- }
- }
-
-
- #if qDebug >= 1
- DebugStr("\pMyTEClick exit");
- #endif
-
- }
-
-
- //=============================================================================
- // DoCommandClick : Handle the click.
- //-----------------------------------------------------------------------------
- ICError DoCommandClick(TEHandle teH, long selStart, long selEnd, Boolean makeBookmark)
- {
- ComponentInstance inst;
- ICError err, err2;
-
-
- #if qDebug >= 1
- DebugStr("\pDoCommandClick entered");
- #endif
-
- err = ICCStart(&inst, kCreator);
-
- if (err == noErr)
- {
- err = ICCFindConfigFile(inst, 0, nil);
- if (err == noErr)
- {
- Handle textH;
- SInt8 s;
- StringPtr hint, at;
- Handle urlH;
- long tmpSelStart = selStart;
- long tmpSelEnd = selEnd;
-
- textH = (Handle)TEGetText(teH);
- s = HGetState(textH);
- HLock(textH);
-
- urlH = NewHandle(0);
-
- hint = "\pmailto";
-
- err = ICCParseURL(inst, hint, *textH, GetHandleSize(textH), &tmpSelStart, &tmpSelEnd, urlH);
-
- if (err == noErr)
- {
- hint = "\p";
- at = "\p@";
-
- if ( Munger(urlH, 0, &at[1], StrLength(at), nil, 0) >= 0 )
- {
- hint = "\pmailto";
- }
-
- if (makeBookmark)
- {
- err = AddBookmark(inst, (*textH) + tmpSelStart, tmpSelEnd - tmpSelStart);
- TESetSelect(tmpSelStart, tmpSelEnd, teH);
- }
- else
- {
- err = ICCLaunchURL(inst, hint, *textH, GetHandleSize(textH), &selStart, &selEnd);
- TESetSelect(selStart, selEnd, teH);
- }
- }
-
- DisposeHandle(urlH);
-
- if (err == noErr)
- {
- SInt32 junk;
- SInt16 i = LMGetMenuFlash();
-
- while (i--)
- {
- Delay(5, &junk);
- TEDeactivate(teH);
- Delay(5, &junk);
- TEActivate(teH);
- }
- }
- HSetState(textH, s);
- }
- err2 = ICCStop(inst);
-
- if (err == noErr)
- err = err2;
- }
-
- #if qDebug >= 1
- DebugStr("\pDoCommandClick exit");
- #endif
-
- return(err);
- }
-
-
- //=============================================================================
- // AddBookmark : Send a bookmark event to the bookmark app.
- //-----------------------------------------------------------------------------
- pascal ICError AddBookmark(internetConfigurationComponent inst, Ptr urlP, long len)
- {
- ICAttr junkAttr;
- ICAppSpec bookmHelper;
- long helperSize;
- ProcessSerialNumber psn;
- ICError err;
-
- #if qDebug >= 1
- DebugStr("\pAddBookmark entered");
- #endif
-
- helperSize = sizeof(bookmHelper);
- err = ICCGetPref(inst, kICBookmarkHelper, &junkAttr, (void *)&bookmHelper, &helperSize);
-
-
- err = SignatureToApp(bookmHelper.fCreator, nil, &psn, nil, nil,
- Sig2App_LaunchApplication, launchContinue | launchDontSwitch);
-
-
- if (err == noErr)
- {
- AEAddressDesc target;
-
- err = AECreateDesc(typeProcessSerialNumber, &psn, sizeof(psn), &target);
- if (err == noErr)
- {
- AppleEvent theEvent;
-
- err = AECreateAppleEvent(gBkEventClass, gBkEventID, &target, kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
- if (err == noErr)
- {
- char *u = urlP;
- long l = len;
-
- if (u[0] == '<')
- {
- u++;
- l--;
- }
- if (u[l-1] == '>')
- l--;
-
- err = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, u, l);
- if (err == noErr)
- {
- AppleEvent reply;
- err = AESend(&theEvent, &reply, kAENoReply, kAEHighPriority, kNoTimeOut, nil, nil);
- }
- AEDisposeDesc(&theEvent);
- }
- AEDisposeDesc(&target);
- }
- }
- #if qDebug >= 1
- DebugStr("\pAddBookmark exit");
- #endif
-
- return err;
- }
-
-
- //=============================================================================
- // main : Entry point to our code resource.
- //-----------------------------------------------------------------------------
- pascal void main(Point pt, Boolean fExtend, TEHandle teH)
- {
- long oldA4;
- short oldSelStart, oldSelEnd;
- KeyMapArr km;
- Boolean commandKey;
- Boolean optionKey;
-
- // Set up A4
- #ifndef powerc
- oldA4 = SetCurrentA4();
- #endif
-
- #if qDebug >= 2
- DebugStr("\pICeTEe entered");
- #endif
-
- // Save old selection
- oldSelStart = (**teH).selStart;
- oldSelEnd = (**teH).selEnd;
-
- // Get modifier keys
- GetKeys(km.map);
- commandKey = KeyIsDown(kCommandKey);
- optionKey = KeyIsDown(kOptionKey);
-
-
- // If we've not already been called, do our one time initialisation stuff
- if (!gAlreadyRan)
- {
- ICeTEeAddressTable *theAddressTable;
-
- Gestalt(kICeTEeAddressTable, (long *) &theAddressTable);
- gPrevTEClick = (TEClickProcPtr) ((long) theAddressTable->theTable[kTEClick]);
- gExclusions = theAddressTable->exclusions;
- gErrors = theAddressTable->errors;
- gBkEventClass = theAddressTable->bkEventClass;
- gBkEventID = theAddressTable->bkEventID;
- gAlreadyRan = true;
- }
-
- // Call the original TEClick()
- gPrevTEClick(pt, fExtend, teH);
-
- // Do our thing
- if (commandKey)
- {
- THz oldZone;
-
- oldZone = GetZone();
- SetZone(SystemZone());
-
- MyTEClick(teH, oldSelStart, oldSelEnd, optionKey);
-
- SetZone(oldZone);
- }
-
- #if qDebug >= 2
- DebugStr("\pICeTEe exit");
- #endif
-
- // Restore A4 and return
- #ifndef powerc
- SetA4(oldA4);
- #endif
- }
-