// Copyright 1999 Macromedia, Inc. All rights reserved.

// This file contains functions for inserting Fireworks HTML
//
// dependencies:
// $Dreamweaver/Configuration/Shared/MM/Scripts/Class/FileClass.js
//
// errors:
/*
var MSG_copyFilesToSite =
      "Some referenced files are outside of the root folder of site '%s'\n" +
      "and may not be accessible when you publish the site.\n\n" +
      "The referenced files are:\n%s\n\n" +
      "Your root folder is:\n%s\n\n" +
      "Continue copying these files into your site?";
var MSG_folderNotUnderSite =
      "The folder you have selected is not under the site root.\n\n" +
      "Your root folder is:\n%s\n\n" +
      "Please select a folder within the site.";
var MSG_overwriteFiles =
      "Some files being copied already exist in the selected folder.\n\n" +
      "The existing files are:\n%s\n\n" +
      "Do you want to replace the existing files?";
var MSG_copyFailed =
      "Some files could not be copied to the selected folder.\n\n" +
      "The files not copied are:\n%s";
*/


//*************** GLOBALS  *****************

//List of unsupported Fireworks JavaScript functions
var LIST_fwSpecificFns = new Array("GrpRestore", "GrpSwap", "GrpDown");
var FW4_MENU_FCN = "fwLoadMenus";
var FW4_MENU_FILE = "fw_menu.js"


//***************** LOCAL FUNCTIONS  ******************

//Returns true if the given document is a Fireworks HTML file.
// Find the Fireworks comment
//
function isFireworksHTML(theHTML) {
  var start, stop, target, retVal = false;
  start = theHTML.indexOf("<!-- Fireworks ");
  if (start != -1) {
    stop = theHTML.indexOf("-->", start);
    if (stop != -1) {
      target = theHTML.indexOf("target.", start);
      retVal = (target >= 0) && (target < stop);
  } }
  return retVal;
}


//Returns true if the given document is a Fireworks HTML file targeted
// at Dreamweaver.  Find the Dreamweaver string within the Fireworks
// comment.
//
function isDWStyle(theHTML) {
  var start, stop, target, retVal = false;
  start = theHTML.indexOf("<!-- Fireworks ");
  if (start != -1) {
    stop = theHTML.indexOf("-->", start);
    if (stop != -1) {
      target = theHTML.indexOf("Dreamweaver", start);
      retVal = (target >= 0) && (target < stop);
  } }
  return retVal;
}


//Returns true if the given document contains only supported DW
// behavior functions.  (This should only be an issue for FW1 and FW2)
//
function usesDWBehaviors(theHTML) {
  var fw1or2, searchPatt, retVal = true;
  fw1or2 = (theHTML.indexOf("<!-- Fireworks 1") != -1) ||
           (theHTML.indexOf("<!-- Fireworks 2") != -1);
  if (fw1or2) {
    for (var i=0; retVal && i < LIST_fwSpecificFns.length; i++) {
      searchPatt = new RegExp("function\\s+" + LIST_fwSpecificFns[i] + "\\s*\\(");
      if (theHTML.search(searchPatt) != -1) retVal = false;
  } }
  return retVal;
}


//Return the HTML that should be inserted at the IP
//
function insertFireworksHTML(fwDOM, fwURL, docRootURL, siteRootURL) {
  var fileList, tagList, jsList;
  var siteURL, sitePath, copyList, folderURL, folder;
  var existsList, failedList, overwrite;
  var targetDOM;
  var scriptList,arrowFile, theHead, relPath;

  fileList = new FileRefList(fwURL);
  tagList = new TagList(fwDOM, fileList);
  jsList = new JsRefList(fwDOM, fileList, tagList);
  scriptList = new ScriptTagList(fwDOM, fileList);

  siteURL = dreamweaver.getSiteRoot();

  if (docRootURL && siteURL) {
    sitePath = MMNotes.localURLToFilePath(siteURL);
    siteName = site.getCurrentSite();
    copyList = fileList.getOutsideOfSite(siteURL);

    if (copyList.length > 0) {
      while (true) {
        copy = confirm(printf(MSG_copyFilesToSite,
                              siteName, displayArray(copyList, 5, '\n'), sitePath));

        // copy files to the site.
        if (copy) {
          while (true) {
            folderURL =  dw.browseForFolderURL(LABEL_selectFolder, siteURL);
            folder = new File(folderURL);
            inSite = (folderURL.indexOf(siteURL) == 0)
            if (!folderURL || (folder.exists() && inSite)) break;
            alert(printf(MSG_folderNotUnderSite, sitePath));
          }

          if (!folderURL) continue;
          else if (folder.exists()) {
            existsList = fileList.getTargetExists(folder.getAbsolutePath(), siteURL);
            if (existsList.length > 0)
              overwrite = confirm(printf(MSG_overwriteFiles, displayArray(existsList, 5, '\n')));
            failedList = fileList.copyToFolder(folder.getAbsolutePath(), siteURL, overwrite);
            if (failedList.length >0)
              alert(printf(MSG_copyFailed, displayArray(failedList, 10, '\n')));
        } }
        break;
  } } }

  // update the URLs
  fileList.updateURLs(docRootURL, siteRootURL);

  // make the tag names unique
  targetDOM = dreamweaver.getDocumentDOM('document');
  tagList.makeNamesUnique(targetDOM);

	//  search for fwLoadMenu script and copy it it exists
  if (scriptList.list.length > 0){
    replaceHeadFcns(targetDOM,scriptList);
    arrowFile = new File("arrows.gif", fwURL);
    if (arrowFile.exists()){
	  if (folder){
        if (arrowFile.copyTo(folder.fullUrl+"/arrows.gif")){
          arrowFile.setPath(folder.fullUrl+"/arrows.gif");
	    }
      }
      relPath = absoluteToRelativeURL(arrowFile.fullUrl,docRootURL,true);
      theHead = targetDOM.getElementsByTagName("HEAD")[0];
      theHead.outerHTML = theHead.outerHTML.replace(/childMenuIcon="arrows\.gif"/g,'childMenuIcon="'+relPath+'"')
    }
  }
  retVal = getInsertedHTML(fwDOM);

  return retVal;
}


//Returns the HTML that should be inserted into the current document.
//
function getInsertedHTML(sourceDOM) {
  var retVal = sourceDOM.body.innerHTML;
  var start = '', stop = '', item;
  var startExp = /<!-+\s*BEGIN COPYING[\w\s]*-+>\s*/;
  var stopExp  = /\s*<!-+\s*STOP COPYING[\w\s]*-+>/;
  item = retVal.match(startExp);
  if (item != null) start = item.index + item[0].length;
  item = retVal.match(stopExp);
  if (item != null) stop = item.index;
  if (start && stop)
    retVal = retVal.substring(start,stop);

  return retVal;
}


function replaceHeadFcns(sourceDOM,scriptList){
  var headChildren, scriptHTML, searchPatt,srcStr,fwHTML;
  var replacedArr = new Array(false,false);
  var sourceHead = sourceDOM.getElementsByTagName("HEAD")[0]
  fwHTML = scriptList.findFunction(FW4_MENU_FCN);
  if(!fwHTML)
    return;
  searchPatt = new RegExp("function\\s+" + FW4_MENU_FCN + "\(.*\\n\)*.*\\\/\\\/\\s*" + FW4_MENU_FCN+"\\s*\\\(\\)");
  replaceStr = fwHTML.match(searchPatt);
  headChildren = sourceHead.childNodes;
  for (var i=0; i< headChildren.length; i++){
	if (headChildren[i].nodeType==Node.ELEMENT_NODE && headChildren[i].tagName == "SCRIPT"){
	  scriptHTML = headChildren[i].innerHTML;
	  if (replaceStr && scriptHTML.search(searchPatt) != -1){
	    replaceStr = replaceStr[0]
	    headChildren[i].innerHTML = scriptHTML.replace(searchPatt,replaceStr);
	    replacedArr[0]=true;
	  }
	  srcStr = headChildren[i].getAttribute("SRC");
	  if (replaceStr && srcStr && srcStr.toLowerCase().search(FW4_MENU_FILE+'"') != -1){
	    headChildren[i].outerHTML = scriptList.findFile(FW4_MENU_FILE);
	    replacedArr[1] = true;
      }
	}
  }
  if (!replacedArr[0] && fwHTML){
    sourceHead.innerHTML += "\n"+fwHTML+"\n";
    if (!replacedArr[1])
      sourceHead.innerHTML += "\n"+scriptList.findFile(FW4_MENU_FILE)+"\n";
  }
}
//******************* GENERAL CLASSES **********************

//*************************************

//File reference node
//
function FileRef(fileURL, docURL) {
  this.file = new File(fileURL, docURL);
  this.refs = new Array();
}


//List of referenced files
//
function FileRefList(theDocURL) {
  this.docURL = theDocURL;
  this.list = new Array();
}
FileRefList.prototype.add = FileRefList_add;
FileRefList.prototype.getOutsideOfSite = FileRefList_getOutsideOfSite;
FileRefList.prototype.getTargetExists = FileRefList_getTargetExists;
FileRefList.prototype.copyToFolder = FileRefList_copyToFolder;
FileRefList.prototype.updateURLs = FileRefList_updateURLs;

function FileRefList_add(fileURL, refObj) {
  var node;
  for (var i=0; !node && i < this.list.length; i++)
    if (this.list[i].file.getPath() == fileURL) node = this.list[i];
  if (!node) {
    node = new FileRef(fileURL, this.docURL);
    this.list.push(node);
  }
  node.refs.push(refObj);
}

//Returns the list of files which are outside of the current site root
function FileRefList_getOutsideOfSite(theSiteURL) {
  var file, retList = new Array();
  for (var i=0; i < this.list.length; i++) {
    file = this.list[i].file;
    if (file.exists() && file.getAbsolutePath().indexOf(theSiteURL) != 0)
      retList.push(MMNotes.localURLToFilePath(file.getAbsolutePath()));
  }
  return retList;
}

//Returns the list of files which already exist in the target folder
function FileRefList_getTargetExists(theFolderURL, theSiteURL) {
  var file, newFile, retList = new Array();
  for (var i=0; i < this.list.length; i++) {
    file = this.list[i].file;
    if (file.exists() && file.getAbsolutePath().indexOf(theSiteURL) != 0) {
      newFile = new File(theFolderURL + File.separator + file.getName());
      if (newFile.exists())
        retList.push(MMNotes.localURLToFilePath(newFile.getAbsolutePath()));
  } }
  return retList;
}

//Returns the list of files that could not be copied
function FileRefList_copyToFolder(theFolderURL, theSiteURL, overwrite) {
  var file, newFile, retList = new Array();
  for (var i=0; i < this.list.length; i++) {
    file = this.list[i].file;
    if (file.exists() && file.getAbsolutePath().indexOf(theSiteURL) != 0) {
      newFile = new File(theFolderURL + File.separator + file.getName());
      if (newFile.exists() && !overwrite) {
        file.setPath(newFile.getPath());
      } else {
        result = file.copyTo(newFile.getPath());
        if (!result)
          retList.push(MMNotes.localURLToFilePath(newFile.getAbsolutePath()));
        file.setPath(newFile.getPath());
  } } }
  return retList;
}

function FileRefList_updateURLs(newDocURL, newSiteURL) {
  var newRef, fullURL, index, filePath, docPath;
  for (var i=0; i < this.list.length; i++) with (this) {
    if (list[i].file.exists()) {
      newRef = '';
      fullURL = list[i].file.getAbsolutePath();
      if (newSiteURL && fullURL.indexOf(newSiteURL) == 0)
        newRef = fullURL.substring(newSiteURL.length); // site relative
      else if (newDocURL && fullURL.indexOf(newDocURL) == 0)
        newRef = fullURL.substring(newDocURL.length); // doc relative, below doc
      else if (newDocURL) {  // doc relative, above doc
        for (index=0; index < fullURL.length && index < newDocURL.length; index++)
          if (fullURL.charAt(index) != newDocURL.charAt(index)) break;
        index = fullURL.substring(0, index).lastIndexOf(File.separator)+1; // backup to last directory
        filePath = fullURL.substring(index);
        docPath = newDocURL.substring(index);
        if (docPath && docPath.indexOf('|') == -1) {  // image on a separate drive
          for (var j=0; j < docPath.length; j++)
            if (docPath.charAt(j) == File.separator) newRef += "../";
          newRef += filePath;
      } }
      if (!newRef) newRef = fullURL;  // local file ref

      for (var j=0; j < list[i].refs.length; j++)
        list[i].refs[j].setURL(newRef);
  } }
}


//*************************************

//Image Tag
//
function ImageTag(theImgTag) {
  this.imgTag = theImgTag;
  this.name = this.imgTag.name;
  this.jsRefs = new Array();  // list of js references to this tag
}
ImageTag.prototype.getURL = ImageTag_getURL;
ImageTag.prototype.setURL = ImageTag_setURL;
ImageTag.prototype.addJsRef = ImageTag_addJsRef;
ImageTag.prototype.makeNameUnique = ImageTag_makeNameUnique;

function ImageTag_getURL() {
  return this.imgTag.src;
}

function ImageTag_setURL(newURL) {
  this.imgTag.src = newURL;
}

function ImageTag_addJsRef(theJsRef) {
  this.jsRefs.push(theJsRef);
}

function ImageTag_makeNameUnique(theNameList) {
  var index=0, count = 2, newName = this.name;
  while (index < theNameList.length)
    if (theNameList[index] == newName) {
      newName = this.name + "_" + count++; // increment name
      index=0; // re-start search
    } else index++;
  if (newName != this.name) {
    this.imgTag.name = newName;
    for (var i=0; i < this.jsRefs.length; i++)
      this.jsRefs[i].setTagName(newName);
  }
}

//*************************************

//Script Tag
//
function ScriptTag(theScriptTag) {
  this.scriptTag = theScriptTag;
}
ScriptTag.prototype.getURL = ScriptTag_getURL;
ScriptTag.prototype.setURL = ScriptTag_setURL;
ScriptTag.prototype.getHTML = ScriptTag_getHTML;

function ScriptTag_getURL() {
  return this.scriptTag.src;
}

function ScriptTag_setURL(newURL) {
  this.scriptTag.src = newURL;
}

function ScriptTag_getHTML() {
  return this.scriptTag.outerHTML;
}
//*************************************

//List of Script tags
//
function ScriptTagList(sourceDOM, theFileList) {
  this.list = new Array();
  this.init(sourceDOM, theFileList);
}
ScriptTagList.prototype.init = ScriptTagList_init;
ScriptTagList.prototype.findFunction = ScriptTagList_findFunction;
ScriptTagList.prototype.findFile = ScriptTagList_findFile;

function ScriptTagList_init(sourceDOM, theFileList) {
  var tags, node;
  // add image tags
  tags = sourceDOM.getElementsByTagName("SCRIPT");
  for (var i=0; i < tags.size; i++) {
    node = new ScriptTag(tags.item(i));
    this.list.push(node);
    if (node.getURL())
      theFileList.add(node.getURL(), node);
  }
  // add flash, director, etc
}

function ScriptTagList_findFunction(theFunction){
  var theHTML;
  var retVal="";
  var searchPatt = new RegExp("function\\s+" + theFunction + "\(.*\\n\)*.*\\\/\\\/\\s*" + theFunction+"\\s*\\\(\\)");
  for (var i=0; i<this.list.length; i++){
	theHTML = this.list[i].getHTML();
    if (theHTML && theHTML.search(searchPatt)!=-1){
      retVal= theHTML;
      break;
    }
  }
  return retVal;
}

function ScriptTagList_findFile(theFile){
  var theURL;
  var retVal="";
  var searchPatt = new RegExp(theFile);
  for (var i=0; i<this.list.length; i++){
	theURL = this.list[i].getURL();
    if (theURL && theURL.search(searchPatt)!=-1){
      retVal= this.list[i].getHTML();
      break;
    }
  }
  return retVal;
}
//*************************************

//List of HTML tags
//
function TagList(sourceDOM, theFileList) {
  this.list = new Array();
  this.init(sourceDOM, theFileList);
}
TagList.prototype.init = TagList_init;
TagList.prototype.addJsRef = TagList_addJsRef;
TagList.prototype.makeNamesUnique = TagList_makeNamesUnique;
TagList.prototype.fixJsRefs = TagList_fixJsRefs;

function TagList_init(sourceDOM, theFileList) {
  var tags, node;
  // add image tags
  tags = sourceDOM.getElementsByTagName("IMG");
  for (var i=0; i < tags.size; i++) {
    node = new ImageTag(tags.item(i));
    this.list.push(node);
    theFileList.add(node.getURL(), node);
  }
  // add flash, director, etc
}

function TagList_addJsRef(tagName, refObj) {
  var node;
  for (var i=0; !node && i < this.list.length; i++)
    if (this.list[i].name == tagName) node = this.list[i];
  if (node) node.addJsRef(refObj);
}

function TagList_makeNamesUnique(targetDOM) {
  var tags, nameList = new Array();
  // create tag name list
  tags = targetDOM.getElementsByTagName("IMG");
  for (var i=0; i < tags.size; i++)
    nameList.push(tags.item(i).name);
  // make names unique
  for (var i=0; i < this.list.length; i++)
    if (this.list[i].makeNameUnique != null)
      this.list[i].makeNameUnique(nameList);
}

// update the JS references if they are being inserted in layers
function TagList_fixJsRefs(targetDOM, selection) {
}


//*************************************

//JavaScript File reference
//
function JsFileRef(theTag, theAttr, theFileURL) {
  this.tag = theTag;
  this.attr = theAttr;
  this.url = stripSpaces(theFileURL);
}
JsFileRef.prototype.getURL = JsFileRef_getURL;
JsFileRef.prototype.setURL = JsFileRef_setURL;

function JsFileRef_getURL() {
  return stripQuotes(this.url);
}

function JsFileRef_setURL(newURL) {
  var jsCalls, index;
  jsCalls = this.tag.getAttribute(this.attr);
  index = jsCalls.indexOf(this.url);
  if (index >= 0) {
    jsCalls = jsCalls.substring(0,index) +
              "'" + newURL + "'" +
              jsCalls.substring(index + this.url.length);
    this.tag.setAttribute(this.attr, jsCalls);
  }
}


//*************************************

//JavaScript Tag reference
//
function JsTagRef(theTag, theAttr, theTagRef, theRefType) {
  this.tag = theTag;
  this.attr = theAttr;
  this.tagRef = stripSpaces(theTagRef);
  this.refType = theRefType; // NS4.0REF or IE4.0REF or objName

  // Convert to the new find object behavior parameters
  if (this.refType == "NS4.0REF")
    this.setTagRef("'" + getNameFromRef(stripQuotes(this.tagRef)) + "'");
  else if (this.refType == "IE4.0REF")
    this.setTagName('');
}
JsTagRef.prototype.getTagName = JsTagRef_getTagName;
JsTagRef.prototype.setTagName = JsTagRef_setTagName;
JsTagRef.prototype.setTagRef = JsTagRef_setTagRef;

function JsTagRef_getTagName() {
  var retVal, index;
  retVal = stripQuotes(this.tagRef);
  index = retVal.indexOf('?')
  if (index >= 0) retVal = retVal.substring(0, index); // remove frame name
  return retVal;
}

function JsTagRef_setTagName(newName) {
  var index, newRef, tagName;
  if (this.tagRef != "''") with (this) {
    tagName = this.getTagName();
    index = tagRef.indexOf(tagName);
    if (index >= 0) {
      newRef = tagRef.substring(0, index) +
               newName +
               tagRef.substring(index + tagName.length);
      setTagRef(newRef);
  } }
}

function JsTagRef_setTagRef(newRef) {
  var jsCalls, refStart;
  with (this) {
    jsCalls = tag.getAttribute(attr);
    refStart = jsCalls.indexOf(tagRef);
    if (refStart >= 0) {
      jsCalls = jsCalls.substring(0,refStart) +
                newRef +
                jsCalls.substring(refStart + tagRef.length);
      tag.setAttribute(attr, jsCalls);
      this.tagRef = newRef;
  } }
}


//*************************************

//List of JavaScript calls which have file or tag references
//
function JsRefList(sourceDOM, theFileList, theTagList) {
  this.list = new Array();
  this.init(sourceDOM, theFileList, theTagList);
}
JsRefList.prototype.init = JsRefList_init;
JsRefList.prototype.add = JsRefList_add;
JsRefList.prototype.getBehArgs = JsRefList_getBehArgs;

JsRefList.TagList = new Array("A", "AREA", "IMG");
JsRefList.AttrList = new Array("onClick", "onMouseOver", "onMouseOut","onLoad");
JsRefList.swapImageFn  = "MM_swapImage";
JsRefList.nbGroupFn    = "MM_nbGroup";


function JsRefList_init(sourceDOM, theFileList, theTagList) {
  for (var i=0; i < JsRefList.TagList.length; i++) {
    tagList = sourceDOM.getElementsByTagName(JsRefList.TagList[i]);
    for (var j=0; j < tagList.size; j++)
      for (var k=0; k < JsRefList.AttrList.length; k++)
        if (tagList.item(j).getAttribute(JsRefList.AttrList[k]) != null)
          this.add(theFileList, theTagList, tagList.item(j), JsRefList.AttrList[k]);
  }
}

function JsRefList_add(theFileList, theTagList, theTag, theAttr) {
  var callString, jsCalls, fnCall, args, argMask, node, mask;
  callString = theTag.getAttribute(theAttr);
  jsCalls = dreamweaver.getTokens(callString, ";");
  for (var i=0; i < jsCalls.length; i++) {
    fnCall = dreamweaver.getTokens(jsCalls[i], "()");
    if (fnCall.length > 1) {
      args = dreamweaver.getTokens(fnCall[1], ",");
      argMask = this.getBehArgs(fnCall[0], jsCalls[i]);
      for (var j=0; j < argMask.length && j < args.length; j++) {
        mask = argMask[j].toUpperCase();
        if (mask == "DEP" || mask == "URL") {
          node = new JsFileRef(theTag, theAttr, args[j]);
          this.list.push(node);
          theFileList.add(node.getURL(), node);
        } else if (mask == "NS4.0REF" || mask == "IE4.0REF") {
          node = new JsTagRef(theTag, theAttr, args[j], mask);
          this.list.push(node);
          theTagList.addJsRef(node.getTagName(), node);
        } else if (mask == "OBJNAME") {
          node = new JsTagRef(theTag, theAttr, args[j], mask);
          this.list.push(node);
          theTagList.addJsRef(node.getTagName(), node);
  } } } }
}

function JsRefList_getBehArgs(theFn, theFnCall) {
  var retList= '';
  if (stripSpaces(theFn) == JsRefList.swapImageFn)
    retList = SwapImage_identifyBehaviorArguments(theFnCall);
  if (stripSpaces(theFn) == JsRefList.nbGroupFn)
    retList = NavBarGroup_identifyBehaviorArguments(theFnCall);
  if (retList) retList = retList.split(',');
  return retList;
}


//******************* BEHAVIOR FUNCTIONS **********************

function SwapImage_identifyBehaviorArguments(fnCallStr) {
  var argList, argArray, numArgGroups, i;

  argList = "";
  argArray = extractArgs(fnCallStr);
  numArgGroups = Math.floor((argArray.length - 1) / 3); //args come in triplets
  for (i=0; i<numArgGroups; i++) {          //with each NSobj,IEobj,URL triplet
    if (argList) argList += ",";
    //if no dot in the name, return simple name; else, return NS/IE refs
    argList += (argArray[3*i+1].indexOf(".")==-1)? "objName,other,DEP":"NS4.0ref,IE4.0ref,DEP";
  }
  return argList;
}


function NavBarGroup_identifyBehaviorArguments(fnCallStr) {
  var argList = '';
  var args = extractArgs(fnCallStr);
  if (args[1] == 'init' || args[1] == 'down') {
    argList = "other,other";
    for (i=3; i+1 < args.length; i+=2)
      argList += ",objName,DEP";
  } else if (args[1] == 'over') {
    argList = "other";
    for (i=2; i+2 < args.length; i+=3)
      argList += ",objName,DEP,DEP";
  } else if (args[1] == 'out') {
    argList = "other";
  }
  return argList;
}

//******************* GENERAL FUNCTIONS **********************

function displayArray(array, limit, separator, hideElipsis) {
  var retList = array, retVal = '';
  if (array.length > limit) {
    retList = array.slice(0, limit);
    if (!hideElipsis) retList.push('...');
  }
  return retList.join(separator);
}

function extractArgs(behFnCallStr){
  var i, theStr, lastPos, argArray;

  argArray = getTokens(behFnCallStr,"(),");
  for (i=0; i<argArray.length; i++) {
    theStr = unescQuotes(argArray[i]);
    lastPos = theStr.length-1;
    if (theStr.charAt(0) == "'" && lastPos > 0 && theStr.charAt(lastPos) == "'")
      argArray[i] = theStr.substring(1,lastPos);
  }
  return argArray
}

function unescQuotes(theStr){
  var strLen, i, theChar, unescStr = "";
  strLen = theStr.length;
  for(i=0; i<strLen; i++) {
    theChar = theStr.charAt(i);
    if (theChar == "\\" && i < strLen - 1) //if escape char and not end
      theChar = theStr.charAt(++i); //append next char and skip over
    unescStr += theChar;
  }
  return unescStr;
}

//Removes any quotes around the given string
function stripQuotes(theStr) {
  var theQuote;
  if (theStr.length > 1) { //if possibly quoted
    theQuote = theStr.charAt(0);
    if ((theQuote == "'" || theQuote == '"') &&
        theStr.charAt(theStr.length-1) == theQuote)
      theStr = theStr.substring(1,theStr.length-1);
  }
  return theStr
}

//Removes any spaces at the beginning or end of the string
function stripSpaces(theStr) {
  if (!theStr) theStr = "";  //ensure its not null
  theStr = theStr.replace(/^\s*/,""); //strip leading
  theStr = theStr.replace(/\s*$/,""); //strip trailing
  return theStr;
}

function printf() {
var i,numArgs,retStr="",argNum=0,startPos;

  numArgs = arguments.length;
  if (numArgs) {
    theStr = arguments[argNum++];
    startPos = 0;  endPos = theStr.indexOf("%s",startPos);
    if (endPos == -1) endPos = theStr.length;
    while (startPos < theStr.length) {
      retStr += theStr.substring(startPos,endPos);
      if (argNum < numArgs && endPos < theStr.length) retStr += arguments[argNum++];
      startPos = endPos+2;  endPos = theStr.indexOf("%s",startPos);
      if (endPos == -1) endPos = theStr.length;
    }
    if (!retStr) retStr = arguments[0];
  }
  return retStr;
}

function absoluteToRelativeURL(absURL, docURL,check)
{
  var newRef, fullURL, index, filePath, docPath;
    if ((!check || DWfile.exists(absURL)) && absURL)
	{
      newRef = '';
      fullURL = absURL;
      if (docURL && fullURL.indexOf(docURL) == 0)
        newRef = fullURL.substring(docURL.length); // doc relative, below doc
      else if (docURL) {  // doc relative, above doc
        for (index=0; index < fullURL.length && index < docURL.length; index++)
          if (fullURL.charAt(index) != docURL.charAt(index)) break;
        index = fullURL.substring(0, index).lastIndexOf(File.separator)+1; // backup to last directory
        filePath = fullURL.substring(index);
        docPath = docURL.substring(index);
        if (docPath && docPath.indexOf('|') == -1) {  // image on a separate drive
          for (var j=0; j < docPath.length; j++)
            if (docPath.charAt(j) == File.separator) newRef += "../";
          newRef += filePath;
      } }
      if (!newRef) newRef = fullURL;  // local file ref

    }
	return newRef;
}


