home *** CD-ROM | disk | FTP | other *** search
/ ftp.swcp.com / ftp.swcp.com.zip / ftp.swcp.com / mac / mozilla-macos9-1.3.1.sea.bin / Mozilla1.3.1 / Chrome / comm.jar / content / editor / EdReplace.js < prev    next >
Text File  |  2003-06-08  |  13KB  |  401 lines

  1. /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  *
  13.  * The Original Code is Mozilla Communicator client code, released March
  14.  * 31, 1998.
  15.  *
  16.  * The Initial Developer of the Original Code is Netscape Communications
  17.  * Corporation. Portions created by Netscape are
  18.  * Copyright (C) 1998 Netscape Communications Corporation. All
  19.  * Rights Reserved.
  20.  *
  21.  * Contributor(s):
  22.  *                 Kin Blas <kin@netscape.com>
  23.  *                 Akkana Peck <akkana@netscape.com>
  24.  *
  25.  */
  26.  
  27. var gReplaceDialog;      // Quick access to document/form elements.
  28. var gFindInst;           // nsIWebBrowserFind that we're going to use
  29. var gFindService;        // Global service which remembers find params
  30. var gEditor;             // the editor we're using
  31.  
  32. function initDialogObject()
  33. {
  34.   // Create gReplaceDialog object and initialize.
  35.   gReplaceDialog = {};
  36.   gReplaceDialog.findInput       = document.getElementById("dialog.findInput");
  37.   gReplaceDialog.replaceInput    = document.getElementById("dialog.replaceInput");
  38.   gReplaceDialog.caseSensitive   = document.getElementById("dialog.caseSensitive");
  39.   gReplaceDialog.wrap            = document.getElementById("dialog.wrap");
  40.   gReplaceDialog.searchBackwards = document.getElementById("dialog.searchBackwards");
  41.   gReplaceDialog.findNext        = document.getElementById("findNext");
  42.   gReplaceDialog.replace         = document.getElementById("replace");
  43.   gReplaceDialog.replaceAndFind  = document.getElementById("replaceAndFind");
  44.   gReplaceDialog.replaceAll      = document.getElementById("replaceAll");
  45. }
  46.  
  47. function loadDialog()
  48. {
  49.   // Set initial dialog field contents.
  50.   // Set initial dialog field contents. Use the gFindInst attributes first,
  51.   // this is necessary for window.find()
  52.   gReplaceDialog.findInput.value         = (gFindInst.searchString
  53.                                             ? gFindInst.searchString
  54.                                             : gFindService.searchString);
  55.   gReplaceDialog.replaceInput.value = gFindService.replaceString;
  56.   gReplaceDialog.caseSensitive.checked   = (gFindInst.matchCase
  57.                                             ? gFindInst.matchCase
  58.                                             : gFindService.matchCase);
  59.   gReplaceDialog.wrap.checked            = (gFindInst.wrapFind
  60.                                             ? gFindInst.wrapFind
  61.                                             : gFindService.wrapFind);
  62.   gReplaceDialog.searchBackwards.checked = (gFindInst.findBackwards
  63.                                             ? gFindInst.findBackwards
  64.                                             : gFindService.findBackwards);
  65.  
  66.   doEnabling();
  67. }
  68.  
  69. function onLoad()
  70. {
  71.   // If we don't get the editor, then we won't allow replacing.
  72.   gEditor = GetCurrentEditor();
  73.   if (!gEditor)
  74.   {
  75.     window.close();
  76.     return;
  77.   }
  78.  
  79.   // Get the xul <editor> element:
  80.   var editorXUL = window.opener.document.getElementById("content-frame");
  81.  
  82.   // Get the nsIWebBrowserFind service:
  83.   gFindInst = editorXUL.webBrowserFind;
  84.  
  85.   try {
  86.   // get the find service, which stores global find state
  87.     gFindService = Components.classes["@mozilla.org/find/find_service;1"]
  88.                          .getService(Components.interfaces.nsIFindService);
  89.   } catch(e) { dump("No find service!\n"); gFindService = 0; }
  90.  
  91.   // Init gReplaceDialog.
  92.   initDialogObject();
  93.  
  94.   // Change "OK" to "Find".
  95.   //dialog.find.label = document.getElementById("fBLT").getAttribute("label");
  96.  
  97.   // Fill dialog.
  98.   loadDialog();
  99.  
  100.   if (gReplaceDialog.findInput.value)
  101.     gReplaceDialog.findInput.select();
  102.   else
  103.     gReplaceDialog.findInput.focus();
  104. }
  105.  
  106. function onUnload() {
  107.   // Disconnect context from this dialog.
  108.   gFindReplaceData.replaceDialog = null;
  109. }
  110.  
  111. function saveFindData()
  112. {
  113.   // Set data attributes per user input.
  114.   if (gFindService)
  115.   {
  116.     gFindService.searchString  = gReplaceDialog.findInput.value;
  117.     gFindService.matchCase     = gReplaceDialog.caseSensitive.checked;
  118.     gFindService.wrapFind      = gReplaceDialog.wrap.checked;
  119.     gFindService.findBackwards = gReplaceDialog.searchBackwards.checked;
  120.   }
  121. }
  122.  
  123. function setUpFindInst()
  124. {
  125.   gFindInst.searchString  = gReplaceDialog.findInput.value;
  126.   gFindInst.matchCase     = gReplaceDialog.caseSensitive.checked;
  127.   gFindInst.wrapFind      = gReplaceDialog.wrap.checked;
  128.   gFindInst.findBackwards = gReplaceDialog.searchBackwards.checked;
  129. }
  130.  
  131. function onFindNext()
  132. {
  133.   // Transfer dialog contents to the find service.
  134.   saveFindData();
  135.   // set up the find instance
  136.   setUpFindInst();
  137.  
  138.   // Search.
  139.   var result = gFindInst.findNext();
  140.  
  141.   if (!result)
  142.   {
  143.     var bundle = document.getElementById("findBundle");
  144.     AlertWithTitle(null, bundle.getString("notFoundWarning"));
  145.     SetTextboxFocus(gReplaceDialog.findInput);
  146.     gReplaceDialog.findInput.select();
  147.     gReplaceDialog.findInput.focus();
  148.     return false;
  149.   } 
  150.   return true;
  151. }
  152.  
  153. function onReplace()
  154. {
  155.   if (!gEditor)
  156.     return false;
  157.  
  158.   // Does the current selection match the find string?
  159.   var selection = gEditor.selection;
  160.  
  161.   var selStr = selection.toString();
  162.   var specStr = gReplaceDialog.findInput.value;
  163.   if (!gReplaceDialog.caseSensitive.checked)
  164.   {
  165.     selStr = selStr.toLowerCase();
  166.     specStr = specStr.toLowerCase();
  167.   }
  168.   // Unfortunately, because of whitespace we can't just check
  169.   // whether (selStr == specStr), but have to loop ourselves.
  170.   // N chars of whitespace in specStr can match any M >= N in selStr.
  171.   var matches = true;
  172.   var specLen = specStr.length;
  173.   var selLen = selStr.length;
  174.   if (selLen < specLen)
  175.     matches = false;
  176.   else
  177.   {
  178.     var specArray = specStr.match(/\S+|\s+/g);
  179.     var selArray = selStr.match(/\S+|\s+/g);
  180.     if ( specArray.length != selArray.length)
  181.       matches = false;
  182.     else
  183.     {
  184.       for (var i=0; i<selArray.length; i++)
  185.       {
  186.         if (selArray[i] != specArray[i])
  187.         {
  188.           if ( /\S/.test(selArray[i][0]) || /\S/.test(specArray[i][0]) )
  189.           {
  190.             // not a space chunk -- match fails
  191.             matches = false;
  192.             break;
  193.           }
  194.           else if ( selArray[i].length < specArray[i].length )
  195.           {
  196.             // if it's a space chunk then we only care that sel be
  197.             // at least as long as spec
  198.             matches = false;
  199.             break;
  200.           }
  201.         }
  202.       }
  203.     }
  204.   }
  205.  
  206.   // If the current selection doesn't match the pattern,
  207.   // then we want to find the next match, but not do the replace.
  208.   // That's what most other apps seem to do.
  209.   // So here, just return.
  210.   if (!matches)
  211.     return false;
  212.  
  213.   // Transfer dialog contents to the find service.
  214.   saveFindData();
  215.  
  216.   // For reverse finds, need to remember the caret position
  217.   // before current selection
  218.   var newRange;
  219.   if (gReplaceDialog.searchBackwards.checked && selection.rangeCount > 0)
  220.   {
  221.     newRange = selection.getRangeAt(0).cloneRange();
  222.     newRange.collapse(true);
  223.   }
  224.  
  225.   // nsPlaintextEditor::InsertText fails if the string is empty,
  226.   // so make that a special case:
  227.   var replStr = gReplaceDialog.replaceInput.value;
  228.   if (replStr == "")
  229.     gEditor.deleteSelection(0);
  230.   else
  231.     gEditor.insertText(replStr);
  232.  
  233.   // For reverse finds, need to move caret just before the replaced text
  234.   if (gReplaceDialog.searchBackwards.checked && newRange)
  235.   {
  236.     gEditor.selection.removeAllRanges();
  237.     gEditor.selection.addRange(newRange);
  238.   }
  239.  
  240.   return true;
  241. }
  242.  
  243. function onReplaceAll()
  244. {
  245.   if (!gEditor)
  246.     return;
  247.  
  248.   var findStr = gReplaceDialog.findInput.value;
  249.   var repStr = gReplaceDialog.replaceInput.value;
  250.  
  251.   // Transfer dialog contents to the find service.
  252.   saveFindData();
  253.  
  254.   var finder = Components.classes["@mozilla.org/embedcomp/rangefind;1"].createInstance().QueryInterface(Components.interfaces.nsIFind);
  255.  
  256.   finder.caseSensitive = gReplaceDialog.caseSensitive.checked;
  257.   finder.findBackwards = gReplaceDialog.searchBackwards.checked;
  258.  
  259.   // We want the whole operation to be undoable in one swell foop,
  260.   // so start a transaction:
  261.   gEditor.beginTransaction();
  262.  
  263.   // and to make sure we close the transaction, guard against exceptions:
  264.   try {
  265.     // Make a range containing the current selection, 
  266.     // so we don't go past it when we wrap.
  267.     var selection = gEditor.selection;
  268.     var selecRange;
  269.     if (selection.rangeCount > 0)
  270.       selecRange = selection.getRangeAt(0);
  271.     var origRange = selecRange.cloneRange();
  272.  
  273.     // We'll need a range for the whole document:
  274.     var wholeDocRange = gEditor.document.createRange();
  275.     var rootNode = gEditor.rootElement.QueryInterface(Components.interfaces.nsIDOMNode);
  276.     wholeDocRange.selectNodeContents(rootNode);
  277.  
  278.     // And start and end points:
  279.     var endPt = gEditor.document.createRange();
  280.  
  281.     if (gReplaceDialog.searchBackwards.checked)
  282.     {
  283.       endPt.setStart(wholeDocRange.startContainer, wholeDocRange.startOffset);
  284.       endPt.setEnd(wholeDocRange.startContainer, wholeDocRange.startOffset);
  285.     }
  286.     else
  287.     {
  288.       endPt.setStart(wholeDocRange.endContainer, wholeDocRange.endOffset);
  289.       endPt.setEnd(wholeDocRange.endContainer, wholeDocRange.endOffset);
  290.     }
  291.  
  292.     // Find and replace from here to end (start) of document:
  293.     var foundRange;
  294.     var searchRange = wholeDocRange.cloneRange();
  295.     while ((foundRange = finder.Find(findStr, searchRange,
  296.                                      selecRange, endPt)) != null)
  297.     {
  298.       gEditor.selection.removeAllRanges();
  299.       gEditor.selection.addRange(foundRange);
  300.  
  301.       // The editor will leave the caret at the end of the replaced text.
  302.       // For reverse finds, we need it at the beginning,
  303.       // so save the next position now.
  304.       if (gReplaceDialog.searchBackwards.checked)
  305.       {
  306.         selecRange = foundRange.cloneRange();
  307.         selecRange.setEnd(selecRange.startContainer, selecRange.startOffset);
  308.       }
  309.  
  310.       // nsPlaintextEditor::InsertText fails if the string is empty,
  311.       // so make that a special case:
  312.       if (repStr == "")
  313.         gEditor.deleteSelection(0);
  314.       else
  315.         gEditor.insertText(repStr);
  316.  
  317.       // If we're going forward, we didn't save selecRange before, so do it now:
  318.       if (!gReplaceDialog.searchBackwards.checked)
  319.       {
  320.         selection = gEditor.selection;
  321.         if (selection.rangeCount <= 0) {
  322.           gEditor.endTransaction();
  323.           return;
  324.         }
  325.         selecRange = selection.getRangeAt(0).cloneRange();
  326.       }
  327.     }
  328.  
  329.     // If no wrapping, then we're done
  330.     if (!gReplaceDialog.wrap.checked) {
  331.       gEditor.endTransaction();
  332.       return;
  333.     }
  334.  
  335.     // If wrapping, find from start/end of document back to start point.
  336.     if (gReplaceDialog.searchBackwards.checked)
  337.     {
  338.       // Collapse origRange to end
  339.       origRange.setStart(origRange.endContainer, origRange.endOffset);
  340.       // Set current position to document end
  341.       selecRange.setEnd(wholeDocRange.endContainer, wholeDocRange.endOffset);
  342.       selecRange.setStart(wholeDocRange.endContainer, wholeDocRange.endOffset);
  343.     }
  344.     else
  345.     {
  346.       // Collapse origRange to start
  347.       origRange.setEnd(origRange.startContainer, origRange.startOffset);
  348.       // Set current position to document start
  349.       selecRange.setStart(wholeDocRange.startContainer,
  350.                           wholeDocRange.startOffset);
  351.       selecRange.setEnd(wholeDocRange.startContainer, wholeDocRange.startOffset);
  352.     }
  353.  
  354.     while ((foundRange = finder.Find(findStr, wholeDocRange,
  355.                                      selecRange, origRange)) != null)
  356.     {
  357.       gEditor.selection.removeAllRanges();
  358.       gEditor.selection.addRange(foundRange);
  359.  
  360.       // Save insert point for backward case
  361.       if (gReplaceDialog.searchBackwards.checked)
  362.       {
  363.         selecRange = foundRange.cloneRange();
  364.         selecRange.setEnd(selecRange.startContainer, selecRange.startOffset);
  365.       }
  366.  
  367.       // nsPlaintextEditor::InsertText fails if the string is empty,
  368.       // so make that a special case:
  369.       if (repStr == "")
  370.         gEditor.deleteSelection(0);
  371.       else
  372.         gEditor.insertText(repStr);
  373.  
  374.       // Get insert point for forward case
  375.       if (!gReplaceDialog.searchBackwards.checked)
  376.       {
  377.         selection = gEditor.selection;
  378.         if (selection.rangeCount <= 0) {
  379.           gEditor.endTransaction();
  380.           return;
  381.         }
  382.         selecRange = selection.getRangeAt(0);
  383.       }
  384.     }
  385.   } // end try
  386.   catch (e) { }
  387.  
  388.   gEditor.endTransaction();
  389. }
  390.  
  391. function doEnabling()
  392. {
  393.   var findStr = gReplaceDialog.findInput.value;
  394.   var repStr = gReplaceDialog.replaceInput.value;
  395.   gReplaceDialog.enabled = findStr;
  396.   gReplaceDialog.findNext.disabled = !findStr;
  397.   gReplaceDialog.replace.disabled = !findStr;
  398.   gReplaceDialog.replaceAndFind.disabled = !findStr;
  399.   gReplaceDialog.replaceAll.disabled = !findStr;
  400. }
  401.