home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 May / PCWorld_2003-05_cd.bin / Komunik / phoenix / chrome / toolkit.jar / content / global / filepicker.js < prev    next >
Text File  |  2002-11-21  |  22KB  |  738 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 Mozilla 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/MPL/
  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.org code.
  14.  *
  15.  * The Initial Developer of the Original Code is Netscape Communications
  16.  * Corporation.  Portions created by Netscape are
  17.  * Copyright (C) 2000 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributor(s): 
  21.  *  Stuart Parmenter <pavlov@netscape.com>
  22.  *  Brian Ryner <bryner@netscape.com>
  23.  *  Jan Varga <varga@utcru.sk>
  24.  *  Peter Annema <disttsc@bart.nl>
  25.  *  Johann Petrak <johann@ai.univie.ac.at>
  26.  *  Akkana Peck <akkana@netscape.com>
  27.  */
  28.  
  29. const nsIFilePicker       = Components.interfaces.nsIFilePicker;
  30. const nsIDirectoryServiceProvider = Components.interfaces.nsIDirectoryServiceProvider;
  31. const nsIDirectoryServiceProvider_CONTRACTID = "@mozilla.org/file/directory_service;1";
  32. const nsITreeBoxObject = Components.interfaces.nsITreeBoxObject;
  33. const nsIFileView = Components.interfaces.nsIFileView;
  34. const nsFileView_CONTRACTID = "@mozilla.org/filepicker/fileview;1";
  35. const nsITreeView = Components.interfaces.nsITreeView;
  36. const nsILocalFile = Components.interfaces.nsILocalFile;
  37. const nsLocalFile_CONTRACTID = "@mozilla.org/file/local;1";
  38. const nsIPromptService_CONTRACTID = "@mozilla.org/embedcomp/prompt-service;1";
  39.  
  40. var sfile = Components.classes[nsLocalFile_CONTRACTID].createInstance(nsILocalFile);
  41. var retvals;
  42. var filePickerMode;
  43. var homeDir;
  44. var treeView;
  45.  
  46. var textInput;
  47. var okButton;
  48.  
  49. var gFilePickerBundle;
  50.  
  51. // name of new directory entered by the user to be remembered
  52. // for next call of newDir() in case something goes wrong with creation
  53. var gNewDirName = { value: "" };
  54.  
  55. function filepickerLoad() {
  56.   gFilePickerBundle = document.getElementById("bundle_filepicker");
  57.  
  58.   textInput = document.getElementById("textInput");
  59.   okButton = document.documentElement.getButton("accept");
  60.   treeView = Components.classes[nsFileView_CONTRACTID].createInstance(nsIFileView);
  61.  
  62.   if (window.arguments) {
  63.     var o = window.arguments[0];
  64.     retvals = o.retvals; /* set this to a global var so we can set return values */
  65.     const title = o.title;
  66.     filePickerMode = o.mode;
  67.     if (o.displayDirectory) {
  68.       const directory = o.displayDirectory.path;
  69.     }
  70.     const initialText = o.defaultString;
  71.     const filterTitles = o.filters.titles;
  72.     const filterTypes = o.filters.types;
  73.     const numFilters = filterTitles.length;
  74.  
  75.     window.title = title;
  76.  
  77.     if (initialText) {
  78.       textInput.value = initialText;
  79.     }
  80.   }
  81.  
  82.   if (filePickerMode != nsIFilePicker.modeOpen && filePickerMode != nsIFilePicker.modeOpenMultiple) {
  83.     var newDirButton = document.getElementById("newDirButton");
  84.     newDirButton.removeAttribute("hidden");
  85.   }
  86.  
  87.   if (filePickerMode == nsIFilePicker.modeGetFolder) {
  88.     var textInputLabel = document.getElementById("textInputLabel");
  89.     textInputLabel.value = gFilePickerBundle.getString("dirTextInputLabel");
  90.   }
  91.   
  92.   if ((filePickerMode == nsIFilePicker.modeOpen) ||
  93.       (filePickerMode == nsIFilePicker.modeOpenMultiple) ||
  94.       (filePickerMode == nsIFilePicker.modeSave)) {
  95.  
  96.     treeView.setFilter(filterTypes[0]);
  97.  
  98.     /* build filter popup */
  99.     var filterPopup = document.createElement("menupopup");
  100.  
  101.     for (var i = 0; i < numFilters; i++) {
  102.       var menuItem = document.createElement("menuitem");
  103.       if (filterTypes[i] == "..apps")
  104.         menuItem.setAttribute("label", filterTitles[i]);
  105.       else
  106.         menuItem.setAttribute("label", filterTitles[i] + " (" + filterTypes[i] + ")");
  107.       menuItem.setAttribute("filters", filterTypes[i]);
  108.       filterPopup.appendChild(menuItem);
  109.     }
  110.  
  111.     var filterMenuList = document.getElementById("filterMenuList");
  112.     filterMenuList.appendChild(filterPopup);
  113.     if (numFilters > 0)
  114.       filterMenuList.selectedIndex = 0;
  115.     var filterBox = document.getElementById("filterBox");
  116.     filterBox.removeAttribute("hidden");
  117.  
  118.     filterMenuList.selectedIndex = o.filterIndex;
  119.   } else if (filePickerMode == nsIFilePicker.modeGetFolder) {
  120.     treeView.showOnlyDirectories = true;
  121.   }
  122.  
  123.   // start out with a filename sort
  124.   handleColumnClick("FilenameColumn");
  125.  
  126.   document.documentElement.setAttribute("ondialogcancel", "return onCancel();");
  127.   try {
  128.     var buttonLabel = getOKAction();
  129.     okButton.setAttribute("label", buttonLabel);
  130.   } catch (exception) {
  131.     // keep it set to "OK"
  132.   }
  133.  
  134.   // setup the dialogOverlay.xul button handlers
  135.   retvals.buttonStatus = nsIFilePicker.returnCancel;
  136.  
  137.   var tree = document.getElementById("directoryTree");
  138.   tree.treeBoxObject.view = treeView;
  139.  
  140.   // Start out with the ok button disabled since nothing will be
  141.   // selected and nothing will be in the text field.
  142.   okButton.disabled = true;
  143.   textInput.focus();
  144.  
  145.   // This allows the window to show onscreen before we begin
  146.   // loading the file list
  147.  
  148.   setTimeout(setInitialDirectory, 0, directory);
  149. }
  150.  
  151. function setInitialDirectory(directory)
  152. {
  153.   // get the home dir
  154.   var dirServiceProvider = Components.classes[nsIDirectoryServiceProvider_CONTRACTID]
  155.                                      .getService(nsIDirectoryServiceProvider);
  156.   var persistent = new Object();
  157.   homeDir = dirServiceProvider.getFile("Home", persistent);
  158.  
  159.   if (directory) {
  160.     sfile.initWithPath(directory);
  161.   }
  162.   if (!directory || !(sfile.exists() && sfile.isDirectory())) {
  163.     // Start in the user's home directory
  164.     sfile.initWithPath(homeDir.path);
  165.   }
  166.  
  167.   gotoDirectory(sfile);
  168. }
  169.  
  170. function onFilterChanged(target)
  171. {
  172.   // Do this on a timeout callback so the filter list can roll up
  173.   // and we don't keep the mouse grabbed while we are refiltering.
  174.  
  175.   setTimeout(changeFilter, 0, target.getAttribute("filters"));
  176. }
  177.  
  178. function changeFilter(filterTypes)
  179. {
  180.   window.setCursor("wait");
  181.   treeView.setFilter(filterTypes);
  182.   window.setCursor("auto");
  183. }
  184.  
  185. function showErrorDialog(titleStrName, messageStrName, file)
  186. {
  187.   var errorTitle =
  188.     gFilePickerBundle.getFormattedString(titleStrName, [file.path]);
  189.   var errorMessage =
  190.     gFilePickerBundle.getFormattedString(messageStrName, [file.path]);
  191.   var promptService =
  192.     Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
  193.  
  194.   promptService.alert(window, errorTitle, errorMessage);
  195. }
  196.  
  197. function openOnOK()
  198. {
  199.   var dir = treeView.getSelectedFile();
  200.   if (!dir.isReadable()) {
  201.     showErrorDialog("errorOpenFileDoesntExistTitle",
  202.                     "errorDirNotReadableMessage",
  203.                     dir);
  204.     return false;
  205.   }
  206.  
  207.   if (dir)
  208.     gotoDirectory(dir);
  209.  
  210.   retvals.file = dir;
  211.  
  212.   retvals.buttonStatus = nsIFilePicker.returnCancel;
  213.   
  214.   var filterMenuList = document.getElementById("filterMenuList");
  215.   retvals.filterIndex = filterMenuList.selectedIndex;
  216.   
  217.   return false;
  218. }
  219.  
  220. function selectOnOK()
  221. {
  222.   var errorTitle, errorMessage, promptService;
  223.   var ret = nsIFilePicker.returnCancel;
  224.  
  225.   var isDir = false;
  226.   var isFile = false;
  227.  
  228.   var file = processPath(textInput.value);
  229.  
  230.   if (!file) { // generic error message, should probably never happen
  231.     showErrorDialog("errorPathProblemTitle",
  232.                     "errorPathProblemMessage",
  233.                     textInput.value);
  234.     return false;
  235.   }
  236.  
  237.   // try to normalize - if this fails we will ignore the error
  238.   // because we will notice the
  239.   // error later and show a fitting error alert.
  240.   try{
  241.     file.normalize();
  242.   } catch(e) {
  243.     //promptService.alert(window, "Problem", "normalize failed, continuing");
  244.   }
  245.  
  246.   var fileExists = file.exists();
  247.   
  248.   if (!fileExists && (filePickerMode == nsIFilePicker.modeOpen ||
  249.                       filePickerMode == nsIFilePicker.modeOpenMultiple)) {
  250.     showErrorDialog("errorOpenFileDoesntExistTitle",
  251.                     "errorOpenFileDoesntExistMessage",
  252.                     file);
  253.     return false;
  254.   }
  255.  
  256.   if (!fileExists && filePickerMode == nsIFilePicker.modeGetFolder) {
  257.     showErrorDialog("errorDirDoesntExistTitle",
  258.                     "errorDirDoesntExistMessage",
  259.                     file);
  260.     return false;
  261.   }
  262.  
  263.   if (fileExists) {
  264.     isDir = file.isDirectory();
  265.     isFile = file.isFile();
  266.   }
  267.  
  268.   switch(filePickerMode) {
  269.   case nsIFilePicker.modeOpen:
  270.   case nsIFilePicker.modeOpenMultiple:
  271.     if (isFile) {
  272.       if (file.isReadable()) {
  273.         retvals.directory = file.parent.path;
  274.         ret = nsIFilePicker.returnOK;
  275.       } else {
  276.         showErrorDialog("errorOpeningFileTitle",
  277.                         "openWithoutPermissionMessage_file",
  278.                         file);
  279.         ret = nsIFilePicker.returnCancel;
  280.       }
  281.     } else if (isDir) {
  282.       if (!sfile.equals(file)) {
  283.         gotoDirectory(file);
  284.       }
  285.       textInput.value = "";
  286.       doEnabling();
  287.       ret = nsIFilePicker.returnCancel;
  288.     }
  289.     break;
  290.   case nsIFilePicker.modeSave:
  291.     if (isFile) { // can only be true if file.exists()
  292.       if (!file.isWritable()) {
  293.         showErrorDialog("errorSavingFileTitle",
  294.                         "saveWithoutPermissionMessage_file",
  295.                         file);
  296.         ret = nsIFilePicker.returnCancel;
  297.       } else {
  298.         // we need to pop up a dialog asking if you want to save
  299.         var confirmTitle = gFilePickerBundle.getString("confirmTitle");
  300.         var message =
  301.           gFilePickerBundle.getFormattedString("confirmFileReplacing",
  302.                                                [file.path]);
  303.  
  304.         promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
  305.         var rv = promptService.confirm(window, title, message)
  306.         if (rv) {
  307.           ret = nsIFilePicker.returnReplace;
  308.           retvals.directory = file.parent.path;
  309.         } else {
  310.           ret = nsIFilePicker.returnCancel;
  311.         }
  312.       }
  313.     } else if (isDir) {
  314.       if (!sfile.equals(file)) {
  315.         gotoDirectory(file);
  316.       }
  317.       textInput.value = "";
  318.       doEnabling();
  319.       ret = nsIFilePicker.returnCancel;
  320.     } else {
  321.       var parent = file.parent;
  322.       if (parent.exists() && parent.isDirectory() && parent.isWritable()) {
  323.         ret = nsIFilePicker.returnOK;
  324.         retvals.directory = parent.path;
  325.       } else {
  326.         var oldParent = parent;
  327.         while (!parent.exists()) {
  328.           oldParent = parent;
  329.           parent = parent.parent;
  330.         }
  331.         errorTitle =
  332.           gFilePickerBundle.getFormattedString("errorSavingFileTitle",
  333.                                                [file.path]);
  334.         if (parent.isFile()) {
  335.           errorMessage =
  336.             gFilePickerBundle.getFormattedString("saveParentIsFileMessage",
  337.                                                  [parent.path, file.path]);
  338.         } else {
  339.           errorMessage =
  340.             gFilePickerBundle.getFormattedString("saveParentDoesntExistMessage",
  341.                                                  [oldParent.path, file.path]);
  342.         }
  343.         if (!parent.isWritable()) {
  344.           errorMessage =
  345.             gFilePickerBundle.getFormattedString("saveWithoutPermissionMessage_dir", [parent.path]);
  346.         }
  347.         promptService = Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
  348.         promptService.alert(window, errorTitle, errorMessage);
  349.         ret = nsIFilePicker.returnCancel;
  350.       }
  351.     }
  352.     break;
  353.   case nsIFilePicker.modeGetFolder:
  354.     if (isDir) {
  355.       retvals.directory = file.parent.path;
  356.     } else { // if nothing selected, the current directory will be fine
  357.       retvals.directory = sfile.path;
  358.     }
  359.     ret = nsIFilePicker.returnOK;
  360.     break;
  361.   }
  362.  
  363.   retvals.file = file;
  364.  
  365.   gFilesEnumerator.mFile = file;
  366.   gFilesEnumerator.mHasMore = true;
  367.  
  368.   retvals.files = gFilesEnumerator;
  369.   retvals.buttonStatus = ret;
  370.  
  371.   var filterMenuList = document.getElementById("filterMenuList");
  372.   retvals.filterIndex = filterMenuList.selectedIndex;
  373.   
  374.   return (ret != nsIFilePicker.returnCancel);
  375. }
  376.  
  377. var gFilesEnumerator = {
  378.   mHasMore: false,
  379.   mFile: null,
  380.  
  381.   hasMoreElements: function()
  382.   {
  383.     return this.mHasMore;
  384.   },
  385.   getNext: function()
  386.   {
  387.     this.mHasMore = false;
  388.     return this.mFile;
  389.   }
  390. };
  391.  
  392. function onCancel()
  393. {
  394.   // Close the window.
  395.   retvals.buttonStatus = nsIFilePicker.returnCancel;
  396.   retvals.file = null;
  397.   retvals.files = null;
  398.   return true;
  399. }
  400.  
  401. function onDblClick(e) {
  402.   var t = e.originalTarget;
  403.   if (t.localName != "treechildren")
  404.     return;
  405.  
  406.   openSelectedFile();
  407. }
  408.  
  409. function openSelectedFile() {
  410.   var file = treeView.getSelectedFile();
  411.   if (!file)
  412.     return;
  413.  
  414.   if (file.isDirectory())
  415.     gotoDirectory(file);
  416.   else if (file.isFile())
  417.     document.documentElement.acceptDialog();
  418. }
  419.  
  420. function onClick(e) {
  421.   var t = e.originalTarget;
  422.   if (t.localName == "treecol")
  423.     handleColumnClick(t.id);
  424. }
  425.  
  426. function convertColumnIDtoSortType(columnID) {
  427.   var sortKey;
  428.   
  429.   switch (columnID) {
  430.   case "FilenameColumn":
  431.     sortKey = nsIFileView.sortName;
  432.     break;
  433.   case "FileSizeColumn":
  434.     sortKey = nsIFileView.sortSize;
  435.     break;
  436.   case "LastModifiedColumn":
  437.     sortKey = nsIFileView.sortDate;
  438.     break;
  439.   default:
  440.     dump("unsupported sort column: " + columnID + "\n");
  441.     sortKey = 0;
  442.     break;
  443.   }
  444.   
  445.   return sortKey;
  446. }
  447.  
  448. function handleColumnClick(columnID) {
  449.   var sortType = convertColumnIDtoSortType(columnID);
  450.   var sortOrder = (treeView.sortType == sortType) ? !treeView.reverseSort : false;
  451.   treeView.sort(sortType, sortOrder);
  452.   
  453.   // set the sort indicator on the column we are sorted by
  454.   var sortedColumn = document.getElementById(columnID);
  455.   if (treeView.reverseSort) {
  456.     sortedColumn.setAttribute("sortDirection", "descending");
  457.   } else {
  458.     sortedColumn.setAttribute("sortDirection", "ascending");
  459.   }
  460.   
  461.   // remove the sort indicator from the rest of the columns
  462.   var currCol = sortedColumn.parentNode.firstChild;
  463.   while (currCol) {
  464.     if (currCol != sortedColumn && currCol.localName == "treecol")
  465.       currCol.removeAttribute("sortDirection");
  466.     currCol = currCol.nextSibling;
  467.   }
  468. }
  469.  
  470. function onKeypress(e) {
  471.   if (e.keyCode == 8) /* backspace */
  472.     goUp();
  473.   else if (e.keyCode == 13) { /* enter */
  474.     var file = treeView.getSelectedFile();
  475.     if (file) {
  476.       if (file.isDirectory()) {
  477.         gotoDirectory(file);
  478.         e.preventDefault();
  479.       }
  480.     }
  481.   }
  482. }
  483.  
  484. function doEnabling() {
  485.   // Maybe add check if textInput.value would resolve to an existing
  486.   // file or directory in .modeOpen. Too costly I think.
  487.   var enable = (textInput.value != "");
  488.  
  489.   okButton.disabled = !enable;
  490. }
  491.  
  492. function onTreeFocus(event) {
  493.   // Reset the button label and enabled/disabled state.
  494.   onFileSelected(treeView.getSelectedFile());
  495. }
  496.  
  497. function getOKAction(file) {
  498.   var buttonLabel;
  499.  
  500.   if (file && file.isDirectory() && filePickerMode != nsIFilePicker.modeGetFolder) {
  501.     document.documentElement.setAttribute("ondialogaccept", "return openOnOK();");
  502.     buttonLabel = gFilePickerBundle.getString("openButtonLabel");
  503.   }
  504.   else {
  505.     document.documentElement.setAttribute("ondialogaccept", "return selectOnOK();");
  506.     switch(filePickerMode) {
  507.     case nsIFilePicker.modeGetFolder:
  508.       buttonLabel = gFilePickerBundle.getString("selectFolderButtonLabel");
  509.       break;
  510.     case nsIFilePicker.modeOpen:
  511.     case nsIFilePicker.modeOpenMultiple:
  512.       buttonLabel = gFilePickerBundle.getString("openButtonLabel");
  513.       break;
  514.     case nsIFilePicker.modeSave:
  515.       buttonLabel = gFilePickerBundle.getString("saveButtonLabel");
  516.       break;
  517.     }
  518.   }
  519.  
  520.   return buttonLabel;
  521. }
  522.  
  523. function onSelect(event) {
  524.   onFileSelected(treeView.getSelectedFile());
  525. }
  526.  
  527. function onFileSelected(file) {
  528.   if (file) {
  529.     var path = file.leafName;
  530.     
  531.     if (path) {
  532.       if ((filePickerMode == nsIFilePicker.modeGetFolder) || !file.isDirectory())
  533.         textInput.value = path;
  534.       
  535.       var buttonLabel = getOKAction(file);
  536.       okButton.setAttribute("label", buttonLabel);
  537.       okButton.disabled = false;
  538.       return;
  539.     }
  540.   }
  541.   okButton.disabled = (textInput.value == "");
  542. }
  543.  
  544. function onTextFieldFocus() {
  545.   var buttonLabel = getOKAction(null);
  546.   okButton.setAttribute("label", buttonLabel);
  547.   doEnabling();
  548. }
  549.  
  550. function onDirectoryChanged(target)
  551. {
  552.   var path = target.getAttribute("label");
  553.  
  554.   var file = Components.classes[nsLocalFile_CONTRACTID].createInstance(nsILocalFile);
  555.   file.initWithPath(path);
  556.  
  557.   if (!sfile.equals(file)) {
  558.     // Do this on a timeout callback so the directory list can roll up
  559.     // and we don't keep the mouse grabbed while we are loading.
  560.  
  561.     setTimeout(gotoDirectory, 0, file);
  562.   }
  563. }
  564.  
  565. function populateAncestorList(directory) {
  566.   var menu = document.getElementById("lookInMenu");
  567.  
  568.   while (menu.hasChildNodes()) {
  569.     menu.removeChild(menu.firstChild);
  570.   }
  571.   
  572.   var menuItem = document.createElement("menuitem");
  573.   menuItem.setAttribute("label", directory.path);
  574.   menuItem.setAttribute("crop", "start");
  575.   menu.appendChild(menuItem);
  576.  
  577.   // .parent is _sometimes_ null, see bug 121489.  Do a dance around that.
  578.   var parent = directory.parent;
  579.   while (parent && !parent.equals(directory)) {
  580.     menuItem = document.createElement("menuitem");
  581.     menuItem.setAttribute("label", parent.path);
  582.     menuItem.setAttribute("crop", "start");
  583.     menu.appendChild(menuItem);
  584.     directory = parent;
  585.     parent = directory.parent;
  586.   }
  587.   
  588.   var menuList = document.getElementById("lookInMenuList");
  589.   menuList.selectedIndex = 0;
  590. }
  591.  
  592. function goUp() {
  593.   try {
  594.     var parent = sfile.parent;
  595.   } catch(ex) { dump("can't get parent directory\n"); }
  596.  
  597.   if (parent) {
  598.     gotoDirectory(parent);
  599.   }
  600. }
  601.  
  602. function goHome() {
  603.   gotoDirectory(homeDir);
  604. }
  605.  
  606. function newDir() {
  607.   var file;
  608.   var promptService =
  609.     Components.classes[nsIPromptService_CONTRACTID].getService(Components.interfaces.nsIPromptService);
  610.   var dialogTitle =
  611.     gFilePickerBundle.getString("promptNewDirTitle");
  612.   var dialogMsg =
  613.     gFilePickerBundle.getString("promptNewDirMessage");
  614.   var ret = promptService.prompt(window, dialogTitle, dialogMsg, gNewDirName, null, {value:0});
  615.  
  616.   if (ret) {
  617.     file = processPath(gNewDirName.value);
  618.     if (!file) {
  619.       showErrorDialog("errorCreateNewDirTitle",
  620.                       "errorCreateNewDirMessage",
  621.                       file);
  622.       return false;
  623.     }
  624.     
  625.     if (file.exists()) {
  626.       showErrorDialog("errorNewDirDoesExistTitle",
  627.                       "errorNewDirDoesExistMessage",
  628.                       file);
  629.       return false;
  630.     }
  631.  
  632.     var parent = file.parent;
  633.     if (!(parent.exists() && parent.isDirectory() && parent.isWritable())) {
  634.       var oldParent = parent;
  635.       while (!parent.exists()) {
  636.         oldParent = parent;
  637.         parent = parent.parent;
  638.       }
  639.       if (parent.isFile()) {
  640.         showErrorDialog("errorCreateNewDirTitle",
  641.                         "errorCreateNewDirIsFileMessage",
  642.                         parent);
  643.         return false;
  644.       }
  645.       if (!parent.isWritable()) {
  646.         showErrorDialog("errorCreateNewDirTitle",
  647.                         "errorCreateNewDirPermissionMessage",
  648.                         parent);
  649.         return false;
  650.       }
  651.     }
  652.  
  653.     try {
  654.       file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); 
  655.     } catch (e) {
  656.       showErrorDialog("errorCreateNewDirTitle",
  657.                       "errorCreateNewDirMessage",
  658.                       file);
  659.       return false;
  660.     }
  661.     file.normalize(); // ... in case ".." was used in the path
  662.     gotoDirectory(file);
  663.     // we remember and reshow a dirname if something goes wrong
  664.     // so that errors can be corrected more easily. If all went well,
  665.     // reset the default value to blank
  666.     gNewDirName = { value: "" }; 
  667.   }
  668.   return true;
  669. }
  670.  
  671. function gotoDirectory(directory) {
  672.   window.setCursor("wait");
  673.   try {
  674.     populateAncestorList(directory);
  675.     treeView.setDirectory(directory);
  676.     document.getElementById("errorShower").selectedIndex = 0;
  677.   } catch(ex) {
  678.     document.getElementById("errorShower").selectedIndex = 1;
  679.   }
  680.  
  681.   window.setCursor("auto");
  682.  
  683.   treeView.QueryInterface(nsITreeView).selection.clearSelection();
  684.   if (filePickerMode == nsIFilePicker.modeGetFolder) {
  685.     textInput.value = "";
  686.   }
  687.   textInput.focus();
  688.   sfile = directory;
  689. }
  690.  
  691. function toggleShowHidden(event) {
  692.   treeView.showHiddenFiles = !treeView.showHiddenFiles;
  693. }
  694.  
  695. // from the current directory and whatever was entered
  696. // in the entry field, try to make a new path. This
  697. // uses "/" as the directory seperator, "~" as a shortcut
  698. // for the home directory (but only when seen at the start
  699. // of a path), and ".." to denote the parent directory.
  700. // returns the path or false if an error occurred.
  701. function processPath(path)
  702. {
  703.   var file;
  704.   if (path[0] == '~') 
  705.     path  = homeDir.path + path.substring(1);
  706.  
  707.   try{
  708.     file = sfile.clone().QueryInterface(nsILocalFile);
  709.   } catch(e) {
  710.     dump("Couldn't clone\n"+e);
  711.     return false;
  712.   }
  713.  
  714.   if (path[0] == '/')   /* an absolute path was entered */
  715.     file.initWithPath(path);
  716.   else if ((path.indexOf("/../") > 0) ||
  717.            (path.substr(-3) == "/..") ||
  718.            (path.substr(0,3) == "../") ||
  719.            (path == "..")) {
  720.     /* appendRelativePath doesn't allow .. */
  721.     try{
  722.       file.initWithPath(file.path + "/" + path);
  723.     } catch (e) {
  724.       dump("Couldn't init path\n"+e);
  725.       return false;
  726.     }
  727.   }
  728.   else {
  729.     try {
  730.       file.appendRelativePath(path);
  731.     } catch (e) {
  732.       dump("Couldn't append path\n"+e);
  733.       return false;
  734.     }
  735.   }
  736.   return file;
  737. }
  738.