home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / gui / CPasteSnooper.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  8.8 KB  |  300 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. // ===========================================================================
  20. //    CPasteSnooper.cp
  21. //    an attachment for filtering characters from a paste command
  22. // ===========================================================================
  23.  
  24. #include "CPasteSnooper.h"
  25.  
  26. #include "PascalString.h"
  27. #include "xp_mcom.h"
  28.  
  29. #include <PP_Messages.h>
  30. #include <UTETextAction.h>
  31.  
  32. #ifndef __TYPES__
  33. #include <Types.h>
  34. #endif
  35.  
  36. #ifndef __SCRAP__
  37. #include <Scrap.h>
  38. #endif
  39.  
  40. #ifndef __TOOLUTILS__
  41. #include <ToolUtils.h>
  42. #endif
  43.  
  44. class CPasteActionSnooper : public LTEPasteAction {
  45. public:
  46.                     CPasteActionSnooper (
  47.                         TEHandle    inMacTEH,
  48.                         LCommander    *inTextCommander,
  49.                         LPane        *inTextPane,
  50.                         char        *inFind,
  51.                         char        *inReplace);
  52.             
  53. protected:
  54.             void    DoReplace(char inFind, char inReplace);
  55.             void    DoDelete(char inDelete);
  56.             void    StripLeading(char inStrip);
  57.             void    DoFilter(char inFilter);
  58. };
  59.  
  60. // goal is to make this more general
  61. CPasteSnooper::CPasteSnooper (char *inFind, char *inReplace) :
  62.     // first param to LAttachment says we want to intercept paste commmands
  63.     // second param says that we're going to take care of handling the
  64.     // action and that our host should do nothing
  65.     LAttachment(cmd_Paste, false)
  66. {
  67.     mFind = XP_STRDUP(inFind);
  68.     mReplace = XP_STRDUP(inReplace);
  69. }
  70.  
  71. CPasteSnooper::~CPasteSnooper ()
  72. {
  73.     XP_FREEIF(mFind);
  74.     XP_FREEIF(mReplace);
  75. }
  76.  
  77. // there's no beef here. look in CPasteActionSnooper's
  78. // constructor to see where the actual filtering is done
  79. void CPasteSnooper::ExecuteSelf (MessageT inMessage, void * /* ioParam */)
  80. {
  81.  
  82.     // did we get called with good params?
  83.     if (!mFind || !mReplace)
  84.         return;
  85.     Assert_(strlen(mFind) == strlen(mReplace));
  86.     if (strlen(mFind) != strlen(mReplace))
  87.         return;
  88.         
  89.     // paranoia
  90.     Assert_(inMessage == cmd_Paste);
  91.     
  92.     // if you used something other than an LEditField you're in trouble
  93.     LEditField    *editField = dynamic_cast<LEditField *>(mOwnerHost);
  94.     Assert_(editField != nil);
  95.     if (!editField)
  96.         return;
  97.     
  98.     // here's where the paste gets done... but our CPasteActionSnooper gets a shot
  99.     // at it first to take out all the unwanted characters
  100.     editField->PostAction(
  101.         new CPasteActionSnooper(editField->GetMacTEH(), editField, editField, mFind, mReplace)
  102.     );
  103. }
  104.  
  105. // here's where we actually filter stuff
  106. CPasteActionSnooper::CPasteActionSnooper (
  107.     TEHandle    inMacTEH,
  108.     LCommander    *inTextCommander,
  109.     LPane        *inTextPane,
  110.     char        *inFind,
  111.     char        *inReplace)
  112.         : LTEPasteAction(inMacTEH, inTextCommander, inTextPane)
  113. {
  114.     for (int i = 0; inFind[i] != '\0'; i++)
  115.         switch (inReplace[i]) {
  116.             case '\b':
  117.                 DoDelete(inFind[i]);
  118.                 break;
  119.             case '\f':
  120.                 DoFilter(inFind[i]);
  121.                 break;
  122.             case '\a':
  123.                 StripLeading(inFind[i]);
  124.             default:
  125.                 DoReplace(inFind[i], inReplace[i]);
  126.         }
  127. }
  128.  
  129. // removes all instances of inDelete from mPastedTextH
  130. // Example:
  131. //        if mPastedTextH referenced the string "\r\rHello World!\rMy Name is Andy!\r"
  132. //        a call to DoDelete('\r') would make mPastedTextH
  133. //        reference "Hello World!My Name is Andy!" upon completion
  134. void CPasteActionSnooper::DoDelete (char inDelete) {
  135.     // did our inherited class succeed in allocating memory for the scrap?
  136.     if (*mPastedTextH == nil)
  137.         return;
  138.  
  139.     Int32    scrapLength = ::GetHandleSize(mPastedTextH);
  140.     
  141.     // make sure this is a legal operation
  142.     if (scrapLength < 0)
  143.         return;
  144.     
  145.     // create a new handle to store our result
  146.     Handle    newScrapText = ::NewHandle(scrapLength);
  147.  
  148.     // did it work?
  149.     if (*newScrapText == nil)
  150.         return;
  151.         
  152.      // we're going to work with dereferenced handles from here
  153.      // on so we'd better lock them
  154.      ::HLock(mPastedTextH);
  155.     ::HLock(newScrapText);
  156.     
  157.     // search through mPastedTextH and copy all characters except
  158.     // inFind over to newScrapText
  159.     Int32    srcIndex = 0;
  160.     Int32    destIndex = 0;
  161.     
  162.     do {
  163.         if ((*mPastedTextH)[srcIndex] != inDelete)
  164.             (*newScrapText)[destIndex++] = (*mPastedTextH)[srcIndex];
  165.     } while (++srcIndex < scrapLength);
  166.     
  167.     // unlock our handles
  168.     ::HUnlock(newScrapText);
  169.     ::HUnlock(mPastedTextH);
  170.     
  171.     // shrink newScrapText down to the minimum size
  172.     ::SetHandleSize(newScrapText, destIndex);
  173.  
  174.     // dispose of the text we were going to paste...
  175.     ::DisposeHandle(mPastedTextH);
  176.     
  177.     // ...and replace it with the new text that we really wanted to paste
  178.     mPastedTextH = newScrapText;
  179. }
  180.  
  181. // strips leading occurences of inFilter in mPastedTextH and then
  182. // clips mPastedTextH right before the next occurence of inFind
  183. // Example:
  184. //        if mPastedTextH referenced the string "\r\rHello World!\rMy Name is Andy!\r"
  185. //        a call to DoFilter('\r') would make mPastedTextH
  186. //        reference "Hello World!" upon completion
  187. void CPasteActionSnooper::DoFilter (char inFilter) {
  188.     StripLeading(inFilter);
  189.     
  190.     // did our inherited class succeed in allocating memory for the scrap?
  191.     if (*mPastedTextH == nil)
  192.         return;
  193.  
  194.     Int32    scrapLength = ::GetHandleSize(mPastedTextH);
  195.     
  196.     // make sure this is a legal operation
  197.     if (scrapLength < 0)
  198.         return;
  199.     
  200.      // we're going to work with the dereferenced handle from here
  201.      // on so I'll just lock it out of habit
  202.      ::HLock(mPastedTextH);
  203.  
  204.     // only take characters up to the first occurence of inFind
  205.     int    endOfNewScrap = 0;
  206.     while ((*mPastedTextH)[endOfNewScrap] != inFilter && endOfNewScrap < scrapLength)
  207.         endOfNewScrap++;
  208.  
  209.     // OK, all done with dereferencing
  210.     ::HUnlock(mPastedTextH);
  211.     
  212.     // truncate the handle after the first occurence of inFind
  213.     if (endOfNewScrap < scrapLength)
  214.         ::SetHandleSize(mPastedTextH, endOfNewScrap);
  215. }
  216.  
  217. // strips leading occurences of inFind
  218. // Example:
  219. //         if mPastedTextH referenced the string "\t\tI luv\tCS\t\t"
  220. //        a call to StripLeading('\t') would make mPastedTextH
  221. //        reference "I luv\tCS\t\t" upon completion
  222. void CPasteActionSnooper::StripLeading (char inStrip) {
  223.     // did our inherited class succeed in allocating memory for the scrap?
  224.     if (*mPastedTextH == nil)
  225.         return;
  226.  
  227.     Int32    scrapLength = ::GetHandleSize(mPastedTextH);
  228.     
  229.     // make sure this is a legal operation
  230.     if (scrapLength < 0)
  231.         return;
  232.     
  233.      // we're going to work with the dereferenced handle from here
  234.      // on so we'd better lock it
  235.      ::HLock(mPastedTextH);
  236.  
  237.     Int32    startOfNewScrap;
  238.     Int32    newScrapSize;
  239.     Handle    newScrapText = nil;
  240.  
  241.     // skip over initial occurences of inStrip
  242.     startOfNewScrap = 0;
  243.     while ((*mPastedTextH)[startOfNewScrap] == inStrip)
  244.         startOfNewScrap++;
  245.             
  246.     // make a new Handle to hold the characters we really want
  247.     newScrapSize = scrapLength - startOfNewScrap;
  248.     newScrapText = ::NewHandle(newScrapSize);
  249.  
  250.     // did NewHandle work?
  251.     if (*newScrapText == nil) {
  252.         // better not forget to do this
  253.         ::HUnlock(mPastedTextH);
  254.         return;
  255.     }
  256.  
  257.     // now copy those characters into the new handle
  258.     ::HLock(newScrapText);
  259.     ::BlockMove((*mPastedTextH + startOfNewScrap), *newScrapText, newScrapSize);
  260.     ::HUnlock(newScrapText);
  261.     
  262.     // unlock and dispose of the text we were going to paste...
  263.     ::HUnlock(mPastedTextH);
  264.     ::DisposeHandle(mPastedTextH);
  265.     
  266.     // ...and replace it with the new text that we really wanted to paste
  267.     mPastedTextH = newScrapText;
  268. }
  269.  
  270. // replaces all instances of inFind in mPastedTextH with inReplace
  271. // Example:
  272. //        if mPastedTextH referenced the string "\r\rHello World!\rMy Name is Andy!\r"
  273. //        a call to DoReplace('\r', '#') would make mPastedTextH
  274. //        reference "##Hello World!#My Name is Andy!#" upon completion
  275. void CPasteActionSnooper::DoReplace (char inFind, char inReplace) {
  276.     // did our inherited class succeed in allocating memory for the scrap?
  277.     if (*mPastedTextH == nil)
  278.         return;
  279.  
  280.     Int32    scrapLength = ::GetHandleSize(mPastedTextH);
  281.     
  282.     // make sure this is a legal operation
  283.     if (scrapLength < 0)
  284.         return;
  285.     
  286.      // we're going to work the dereferenced handle from here
  287.      // on so we'd better lock it
  288.      ::HLock(mPastedTextH);
  289.     
  290.     // search through mPastedTextH and replace all occurences
  291.     // of inFind with inReplace
  292.     for (int i = 0; i < scrapLength; i++) {
  293.         if ((*mPastedTextH)[i] == inFind)
  294.             (*mPastedTextH)[i] = inReplace;
  295.     }
  296.     
  297.     // unlock our handle and we're done!
  298.     ::HUnlock(mPastedTextH);
  299. }
  300.