home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- // ===========================================================================
- // CPasteSnooper.cp
- // an attachment for filtering characters from a paste command
- // ===========================================================================
-
- #include "CPasteSnooper.h"
-
- #include "PascalString.h"
- #include "xp_mcom.h"
-
- #include <PP_Messages.h>
- #include <UTETextAction.h>
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __SCRAP__
- #include <Scrap.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- class CPasteActionSnooper : public LTEPasteAction {
- public:
- CPasteActionSnooper (
- TEHandle inMacTEH,
- LCommander *inTextCommander,
- LPane *inTextPane,
- char *inFind,
- char *inReplace);
-
- protected:
- void DoReplace(char inFind, char inReplace);
- void DoDelete(char inDelete);
- void StripLeading(char inStrip);
- void DoFilter(char inFilter);
- };
-
- // goal is to make this more general
- CPasteSnooper::CPasteSnooper (char *inFind, char *inReplace) :
- // first param to LAttachment says we want to intercept paste commmands
- // second param says that we're going to take care of handling the
- // action and that our host should do nothing
- LAttachment(cmd_Paste, false)
- {
- mFind = XP_STRDUP(inFind);
- mReplace = XP_STRDUP(inReplace);
- }
-
- CPasteSnooper::~CPasteSnooper ()
- {
- XP_FREEIF(mFind);
- XP_FREEIF(mReplace);
- }
-
- // there's no beef here. look in CPasteActionSnooper's
- // constructor to see where the actual filtering is done
- void CPasteSnooper::ExecuteSelf (MessageT inMessage, void * /* ioParam */)
- {
-
- // did we get called with good params?
- if (!mFind || !mReplace)
- return;
- Assert_(strlen(mFind) == strlen(mReplace));
- if (strlen(mFind) != strlen(mReplace))
- return;
-
- // paranoia
- Assert_(inMessage == cmd_Paste);
-
- // if you used something other than an LEditField you're in trouble
- LEditField *editField = dynamic_cast<LEditField *>(mOwnerHost);
- Assert_(editField != nil);
- if (!editField)
- return;
-
- // here's where the paste gets done... but our CPasteActionSnooper gets a shot
- // at it first to take out all the unwanted characters
- editField->PostAction(
- new CPasteActionSnooper(editField->GetMacTEH(), editField, editField, mFind, mReplace)
- );
- }
-
- // here's where we actually filter stuff
- CPasteActionSnooper::CPasteActionSnooper (
- TEHandle inMacTEH,
- LCommander *inTextCommander,
- LPane *inTextPane,
- char *inFind,
- char *inReplace)
- : LTEPasteAction(inMacTEH, inTextCommander, inTextPane)
- {
- for (int i = 0; inFind[i] != '\0'; i++)
- switch (inReplace[i]) {
- case '\b':
- DoDelete(inFind[i]);
- break;
- case '\f':
- DoFilter(inFind[i]);
- break;
- case '\a':
- StripLeading(inFind[i]);
- default:
- DoReplace(inFind[i], inReplace[i]);
- }
- }
-
- // removes all instances of inDelete from mPastedTextH
- // Example:
- // if mPastedTextH referenced the string "\r\rHello World!\rMy Name is Andy!\r"
- // a call to DoDelete('\r') would make mPastedTextH
- // reference "Hello World!My Name is Andy!" upon completion
- void CPasteActionSnooper::DoDelete (char inDelete) {
- // did our inherited class succeed in allocating memory for the scrap?
- if (*mPastedTextH == nil)
- return;
-
- Int32 scrapLength = ::GetHandleSize(mPastedTextH);
-
- // make sure this is a legal operation
- if (scrapLength < 0)
- return;
-
- // create a new handle to store our result
- Handle newScrapText = ::NewHandle(scrapLength);
-
- // did it work?
- if (*newScrapText == nil)
- return;
-
- // we're going to work with dereferenced handles from here
- // on so we'd better lock them
- ::HLock(mPastedTextH);
- ::HLock(newScrapText);
-
- // search through mPastedTextH and copy all characters except
- // inFind over to newScrapText
- Int32 srcIndex = 0;
- Int32 destIndex = 0;
-
- do {
- if ((*mPastedTextH)[srcIndex] != inDelete)
- (*newScrapText)[destIndex++] = (*mPastedTextH)[srcIndex];
- } while (++srcIndex < scrapLength);
-
- // unlock our handles
- ::HUnlock(newScrapText);
- ::HUnlock(mPastedTextH);
-
- // shrink newScrapText down to the minimum size
- ::SetHandleSize(newScrapText, destIndex);
-
- // dispose of the text we were going to paste...
- ::DisposeHandle(mPastedTextH);
-
- // ...and replace it with the new text that we really wanted to paste
- mPastedTextH = newScrapText;
- }
-
- // strips leading occurences of inFilter in mPastedTextH and then
- // clips mPastedTextH right before the next occurence of inFind
- // Example:
- // if mPastedTextH referenced the string "\r\rHello World!\rMy Name is Andy!\r"
- // a call to DoFilter('\r') would make mPastedTextH
- // reference "Hello World!" upon completion
- void CPasteActionSnooper::DoFilter (char inFilter) {
- StripLeading(inFilter);
-
- // did our inherited class succeed in allocating memory for the scrap?
- if (*mPastedTextH == nil)
- return;
-
- Int32 scrapLength = ::GetHandleSize(mPastedTextH);
-
- // make sure this is a legal operation
- if (scrapLength < 0)
- return;
-
- // we're going to work with the dereferenced handle from here
- // on so I'll just lock it out of habit
- ::HLock(mPastedTextH);
-
- // only take characters up to the first occurence of inFind
- int endOfNewScrap = 0;
- while ((*mPastedTextH)[endOfNewScrap] != inFilter && endOfNewScrap < scrapLength)
- endOfNewScrap++;
-
- // OK, all done with dereferencing
- ::HUnlock(mPastedTextH);
-
- // truncate the handle after the first occurence of inFind
- if (endOfNewScrap < scrapLength)
- ::SetHandleSize(mPastedTextH, endOfNewScrap);
- }
-
- // strips leading occurences of inFind
- // Example:
- // if mPastedTextH referenced the string "\t\tI luv\tCS\t\t"
- // a call to StripLeading('\t') would make mPastedTextH
- // reference "I luv\tCS\t\t" upon completion
- void CPasteActionSnooper::StripLeading (char inStrip) {
- // did our inherited class succeed in allocating memory for the scrap?
- if (*mPastedTextH == nil)
- return;
-
- Int32 scrapLength = ::GetHandleSize(mPastedTextH);
-
- // make sure this is a legal operation
- if (scrapLength < 0)
- return;
-
- // we're going to work with the dereferenced handle from here
- // on so we'd better lock it
- ::HLock(mPastedTextH);
-
- Int32 startOfNewScrap;
- Int32 newScrapSize;
- Handle newScrapText = nil;
-
- // skip over initial occurences of inStrip
- startOfNewScrap = 0;
- while ((*mPastedTextH)[startOfNewScrap] == inStrip)
- startOfNewScrap++;
-
- // make a new Handle to hold the characters we really want
- newScrapSize = scrapLength - startOfNewScrap;
- newScrapText = ::NewHandle(newScrapSize);
-
- // did NewHandle work?
- if (*newScrapText == nil) {
- // better not forget to do this
- ::HUnlock(mPastedTextH);
- return;
- }
-
- // now copy those characters into the new handle
- ::HLock(newScrapText);
- ::BlockMove((*mPastedTextH + startOfNewScrap), *newScrapText, newScrapSize);
- ::HUnlock(newScrapText);
-
- // unlock and dispose of the text we were going to paste...
- ::HUnlock(mPastedTextH);
- ::DisposeHandle(mPastedTextH);
-
- // ...and replace it with the new text that we really wanted to paste
- mPastedTextH = newScrapText;
- }
-
- // replaces all instances of inFind in mPastedTextH with inReplace
- // Example:
- // if mPastedTextH referenced the string "\r\rHello World!\rMy Name is Andy!\r"
- // a call to DoReplace('\r', '#') would make mPastedTextH
- // reference "##Hello World!#My Name is Andy!#" upon completion
- void CPasteActionSnooper::DoReplace (char inFind, char inReplace) {
- // did our inherited class succeed in allocating memory for the scrap?
- if (*mPastedTextH == nil)
- return;
-
- Int32 scrapLength = ::GetHandleSize(mPastedTextH);
-
- // make sure this is a legal operation
- if (scrapLength < 0)
- return;
-
- // we're going to work the dereferenced handle from here
- // on so we'd better lock it
- ::HLock(mPastedTextH);
-
- // search through mPastedTextH and replace all occurences
- // of inFind with inReplace
- for (int i = 0; i < scrapLength; i++) {
- if ((*mPastedTextH)[i] == inFind)
- (*mPastedTextH)[i] = inReplace;
- }
-
- // unlock our handle and we're done!
- ::HUnlock(mPastedTextH);
- }
-