home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 November / CPNL0711.ISO / beeld / teken / scribus-1.3.3.9-win32-install.exe / tcl / tix8.1 / fs.tcl < prev    next >
Text File  |  2001-11-03  |  13KB  |  654 lines

  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. #    $Id: fs.tcl,v 1.4.2.1 2001/11/03 07:26:10 idiscovery Exp $
  4. #
  5. # tixAssert --
  6. #
  7. #    Debugging routine. Evaluates the test script in the context of the
  8. #    caller. The test script is responsible for generating the error.
  9. #    
  10. proc tixAssert {script} {
  11.     uplevel $script
  12. }
  13.  
  14. proc tixAssertNorm {path} {
  15.     if {![tixFSIsNorm $path]} {
  16.     error "\"$path\" is not a normalized path"
  17.     }
  18. }
  19.  
  20. proc tixAssertVPath {vpath} {
  21.     if {![tixFSIsVPath $vpath]} {
  22.     error "\"$vpath\" is not a VPATH"
  23.     }
  24. }
  25.  
  26. # tixFSAbsPath --
  27. #
  28. #    Converts $path into an normalized absolute path
  29. #
  30. proc tixFSAbsPath {path} {
  31.     return [lindex [tixFSNorm [tixFSVPWD] $path] 0]
  32. }
  33.  
  34. # tixFSVPWD --
  35. #
  36. #    Returns the VPATH of the current directory.
  37. #
  38. proc tixFSVPWD {} {
  39.     return [tixFSVPath [tixFSPWD]]
  40. }
  41.  
  42. if {![info exists tcl_platform] || $tcl_platform(platform) == "unix"} {
  43.  
  44. # tixFSPWD --
  45. #
  46. #    Return the current directory
  47. #
  48. proc tixFSPWD {} {
  49.     return [pwd]
  50. }
  51.  
  52. # tixFSDisplayName --
  53. #
  54. #    Returns the name of a normalized path which is usually displayed by
  55. #    the OS
  56. #
  57. proc tixFSDisplayName {normpath} {
  58.     tixAssert {
  59.     tixAssertNorm $normpath
  60.     }
  61.     return $normpath
  62. }
  63.  
  64. proc tixFSIsAbsPath {path} {
  65.     return [tixStrEq [string index $path 0] /]
  66. }
  67.  
  68. # tixFSIsNorm_os --
  69. #
  70. #    Returns true iff this pathname is normalized, in the OS native name
  71. #    format
  72. #
  73. proc tixFSIsNorm_os {path} {
  74.     return [tixFSIsNorm $path]
  75. }
  76.  
  77. proc tixFSIsNorm {path} {
  78.     if {[tixStrEq $path /]} {
  79.     return 1
  80.     }
  81.  
  82.     # relative path
  83.     #
  84.     if {![regexp -- {^/} $path]} {
  85.     return 0
  86.     }
  87.  
  88.     if {[regexp -- {/[.]$} $path]} {
  89.     return 0
  90.     }
  91.     if {[regexp -- {/[.][.]$} $path]} {
  92.     return 0
  93.     }
  94.     if {[regexp -- {/[.]/} $path]} {
  95.     return 0
  96.     }
  97.     if {[regexp -- {/[.][.]/} $path]} {
  98.     return 0
  99.     }
  100.     if {[tixStrEq $path .]} {
  101.     return 0
  102.     }
  103.     if {[tixStrEq $path ..]} {
  104.     return 0
  105.     }
  106.  
  107.     # Tilde
  108.     #
  109.     if {[regexp -- {^~} $path]} {
  110.     return 0
  111.     }
  112.  
  113.     # Double slashes
  114.     #
  115.     if {[regexp -- {//} $path]} {
  116.     return 0
  117.     }
  118.  
  119.     # Trailing slashes
  120.     #
  121.     if {[regexp -- {/$} $path]} {
  122.     return 0
  123.     }
  124.  
  125.     return 1
  126. }
  127.  
  128. # tixFSIsValid --
  129. #
  130. #    Checks whether a native pathname contains invalid characters.
  131. #
  132. proc tixFSIsValid {path} {
  133.     return 1
  134. }
  135.  
  136. proc tixFSIsVPath {vpath} {
  137.     return [tixFSIsNorm $vpath]
  138. }
  139.  
  140. # tixFSVPath --
  141. #
  142. #    Converts a native pathname to its VPATH
  143. #
  144. proc tixFSVPath {path} {
  145.     tixAssert {
  146.     tixAssertNorm $path
  147.     }
  148.     return $path
  149. }
  150.  
  151. # tixFSPath --
  152. #
  153. #    Converts a vpath to a native pathname
  154. proc tixFSPath {vpath} {
  155.     tixAssert {
  156.     tixAssertVPath $vpath
  157.     }
  158.     return $vpath
  159. }
  160.  
  161. # tixFSTildeSubst -- [Unix only]
  162. #
  163. #    Substitutes any leading tilde characters if possible. No error is
  164. #    generated if the user doesn't exist.
  165. #
  166. proc tixFSTildeSubst {text} {
  167.     if {[tixStrEq [string index $text 0] ~]} {
  168.     # The following will report if the user doesn't exist
  169.     if {[catch {
  170.         file isdir $text
  171.     }]} {
  172.         return ./$text
  173.     }
  174.     return [tixFile tilde $text]
  175.     } else {
  176.     return $text
  177.     }
  178. }
  179.  
  180. # tixFSNorm --
  181. #
  182. #    Interprets the user's input and return file information about this
  183. #    input.
  184. #
  185. # Arguments:
  186. #    See documentation (docs/Files.txt)
  187. #
  188. proc tixFSNorm {context text {defFile ""} {flagsVar ""} {errorMsgVar ""}} {
  189.     tixAssert {
  190.     tixAssertVPath $context
  191.     }
  192.  
  193.     if {![tixStrEq $errorMsgVar ""]} {
  194.     upvar $errorMsgVar errorMsg
  195.     }
  196.     if {![tixStrEq $flagsVar ""]} {
  197.     upvar $flagsVar flags
  198.     }
  199.  
  200.     set hasDirSuffix [regexp -- {/$} $text]
  201.     set text [tixFSTildeSubst $text]
  202.     set text [_tixJoin $context $text]
  203.  
  204.     if {$hasDirSuffix || [file isdir $text]} {
  205.     set dir $text
  206.     set tail $defFile
  207.     } else {
  208.     set dir [file dirname $text]
  209.     set tail [file tail $text]
  210.     }
  211.  
  212.     set norm $dir/$tail
  213.     regsub -all -- /+ $norm / norm
  214.     if {![tixStrEq $norm /]} {
  215.     regsub -- {/$} $norm "" norm
  216.     }
  217.  
  218.     if {![info exists flag(noPattern)]} {
  219.     set isPat 0
  220.     foreach char [split $tail ""] {
  221.         if {$char == "*" || $char == "?"} {
  222.         set isPat 1
  223.         break
  224.         }
  225.     }
  226.     if {$isPat} {
  227.         return [list $norm $dir "" $tail]
  228.     }
  229.     }
  230.  
  231.     return [list $norm $dir $tail ""]
  232. }
  233.  
  234. # _tixJoin -- [Internal]
  235. #    Joins two native pathnames.
  236. #
  237. proc _tixJoin {p1 p2} {
  238.     if {[tixStrEq [string index $p2 0] /]} {
  239.     return [_tixNormalize $p2]
  240.     } else {
  241.     return [_tixNormalize $p1/$p2]
  242.     }
  243. }
  244.  
  245. # tixFSNormDir --
  246. #
  247. #    Normalizes an absolute path.
  248. #
  249. proc tixFSNormDir {dir} {
  250.     set dir [tixFile tilde $dir]
  251.     if {![tixStrEq [string index $dir 0] /]} {
  252.     error "\"$dir\" must be an absolute pathname"
  253.     }
  254.     if {![file isdir $dir]} {
  255.     error "\"$dir\" is not a directory"
  256.     }
  257.     return [_tixNormalize $dir]
  258. }
  259.  
  260. # _tixNormalize --
  261. #
  262. #    Normalizes an absolute pathname.
  263. #
  264. #     $dir must be an absolute pathname
  265. #
  266. proc _tixNormalize {path} {
  267.     tixAssert {
  268.     if {![tixStrEq [string index $path 0] /]} {
  269.         error "\"$path\" must be an absolute pathname"
  270.     }
  271.     }
  272.  
  273.     # Don't be fooled: $path doesn't need to be a directory. The following
  274.     # code just makes it easy to get rid of trailing . and ..
  275.     #
  276.     set path $path/
  277.     regsub -all -- /+ $path / path
  278.     while {1} {
  279.     if {![regsub -- {/\./} $path "/" path]} {break}
  280.     }
  281.     while {1} {
  282.     if {![regsub -- {/\.$} $path "" path]} {break}
  283.     }
  284.  
  285.     while {1} {
  286.     if {![regsub -- {/[^/]+/\.\./} $path "/" path]} {break}
  287.     while {1} {
  288.         if {![regsub -- {^/\.\./} $path "/" path]} {break}
  289.     }
  290.     }
  291.     while {1} {
  292.     if {![regsub -- {^/\.\./} $path "/" path]} {break}
  293.     }
  294.  
  295.     regsub -- {/$} $path "" path
  296.     if {[tixStrEq $path ""]} {
  297.     return /
  298.     } else {
  299.     return $path
  300.     }
  301. }
  302.  
  303. # tixFSCreateDirs
  304. #
  305. #
  306. proc tixFSCreateDirs {path} {
  307.     tixAssert {
  308.     error "Procedure tixFSCreateDirs not implemented on all platforms"
  309.     }
  310.     if {[tixStrEq $path /]} {
  311.     return 1
  312.     }
  313.     if {[file exists $path]} {
  314.     return 1
  315.     }
  316.     if {![tixFSCreateDirs [file dirname $path]]} {
  317.     return 0
  318.     }
  319.     if {[catch {exec mkdir $path}]} {
  320.     return 0
  321.     }
  322.     return 1
  323. }
  324.  
  325. } else {
  326.  
  327. #-Win--------------------------------------------------------------------
  328.  
  329. # (Win) tixFSPWD --
  330. #
  331. #    Return the current directory
  332. #
  333. proc tixFSPWD {} {
  334.     set p [pwd]
  335.     regsub -all -- / $p \\ p
  336.     return $p
  337. }
  338. # Win
  339. #
  340. proc tixFSIsNorm {path} {
  341.  
  342.     # Drive root directory
  343.     # CYGNUS: drive can be immediately followed by directory separator.
  344.     #
  345.     if {[regexp -- {^[A-z]:\\?$} $path]} {
  346.     return 1
  347.     }
  348.  
  349.     # If it is not a drive root directory, it must
  350.     # have a leading [drive letter:]\\[non empty string]
  351.     # CYGNUS: A UNC path (\\host\dir) is also OK.
  352.     if {![regexp -- {^[A-z]:\\.} $path]} {
  353.     if {![regexp -- {^\\\\.*\\.} $path]} {
  354.     return 0
  355.     }
  356.     }
  357.  
  358.     # relative path
  359.     #
  360.     if {[regexp -- {\\[.]$} $path]} {
  361.     return 0
  362.     }
  363.     if {[regexp -- {\\[.][.]$} $path]} {
  364.     return 0
  365.     }
  366.     if {[regexp -- {\\[.]\\} $path]} {
  367.     return 0
  368.     }
  369.     if {[regexp -- {\\[.][.]\\} $path]} {
  370.     return 0
  371.     }
  372.     if {[tixStrEq $path .]} {
  373.     return 0
  374.     }
  375.     if {[tixStrEq $path ..]} {
  376.     return 0
  377.     }
  378.  
  379.     # Double slashes
  380.     # CYGNUS: Double slashes at the front are OK.
  381.     #
  382.     if {[regexp -- {.\\\\} $path]} {
  383.     return 0
  384.     }
  385.  
  386.     # Trailing slashes
  387.     #
  388.     if {[regexp -- {[\\]$} $path]} {
  389.     return 0
  390.     }
  391.  
  392.     return 1
  393. }
  394.  
  395. # (Win) tixFSNorm --
  396. #
  397. #    Interprets the user's input and return file information about this
  398. #    input.
  399. #
  400. # Arguments:
  401. #    See documentation (docs/Files.txt)
  402. #
  403. proc tixFSNorm {context text {defFile ""} {flagsVar ""} {errorMsgVar ""}} {
  404.     tixAssert {
  405.     tixAssertVPath $context
  406.     }
  407.  
  408.     if {![tixStrEq $errorMsgVar ""]} {
  409.     upvar $errorMsgVar errorMsg
  410.     }
  411.     if {![tixStrEq $flagsVar ""]} {
  412.     upvar $flagsVar flags
  413.     }
  414.  
  415.     set isDir [regexp -- {[\\]$} $text]
  416.     set text [_tixJoin $context $text]
  417.     set path [tixFSPath $text]
  418.  
  419.     if {$isDir || [file isdir $path]} {
  420.     set vpath $text
  421.     set tail $defFile
  422.     } else {
  423.     set list [split $text \\]
  424.     set tail [lindex $list end]
  425.     set len [string length $tail]
  426.     set vpath [string range $text 0 [expr [string len $text]-$len-1]]
  427.     regsub -- {[\\]$} $vpath "" vpath
  428.     }
  429.  
  430.     set path [tixFSPath $vpath]
  431.  
  432.     if {![info exists flag(noPattern)]} {
  433.     set isPat 0
  434.     foreach char [split $tail ""] {
  435.         if {$char == "*" || $char == "?"} {
  436.         set isPat 1
  437.         break
  438.         }
  439.     }
  440.     if {$isPat} {
  441.         return [list $path $vpath "" $tail]
  442.     }
  443.     }
  444.  
  445.     return [list $path $vpath $tail ""]
  446. }
  447.  
  448. # Win
  449. #
  450. # _tixJoin -- [internal]
  451. #
  452. #    Joins a pathname to a VPATH
  453. #
  454. proc _tixJoin {vp1 p2} {
  455.     if {[tixFSIsAbsPath $p2]} {
  456.     return [tixFSVPath [_tixNormalize $p2]]
  457.     } else {
  458.     return [tixFSVPath [_tixNormalize [tixFSPath $vp1]\\$p2]]
  459.     }
  460. }
  461.  
  462. # (Win) tixFSIsAbsPath
  463. #
  464. #    The Tcl "file pathtype" is buggy. E.g. C:\.\..\. is absolute, but
  465. #    "file pathtype" thinks that it isn't
  466. #
  467.  
  468. proc tixFSIsAbsPath {path} {
  469.     # CYGNUS: Handle a UNC path (\\host\dir)
  470.     if {[regexp -- {^\\\\.*\\.} $path]} {
  471.     return 1
  472.     }
  473.     return [regexp -- {^[A-z]:\\} $path]
  474. }
  475.  
  476. # (Win) tixFSIsNorm_os
  477. #
  478. #    Returns true iff this pathname is normalized, in the OS native name
  479. #    format
  480. #
  481. proc tixFSIsNorm_os {path} {
  482.     if {[regexp -- {^[A-z]:[\\]$} $path]} {
  483.     return 1
  484.     }
  485.     if {[regexp -- {^[A-z]:$} $path]} {
  486.     return 0
  487.     }
  488.  
  489.     return [tixFSIsNorm $path]
  490.  
  491. }
  492.  
  493. # Win
  494. #
  495. # _tixNormalize --
  496. #
  497. #    Normalizes an absolute pathname.
  498. #
  499. #     $dir must be an absolute native pathname
  500. #
  501. proc _tixNormalize {abpath} {
  502.     tixAssert {
  503.     if {![tixFSIsAbsPath $abpath]} {
  504.         error "\"$abpath\" must be an absolute pathname"
  505.     }
  506.     }
  507.  
  508.     if {![regexp -- {^[A-z]:} $abpath drive]} {
  509.     tixPanic "\"$abpath\" does not contain a drive letter"
  510.     }
  511.     set drive [string toupper $drive]
  512.  
  513.     # CYGNUS: Handle UNC paths (\\host\dir)
  514.     if {[regexp -- {^\\\\.*\\.} $abpath]} {
  515.     set drive "\\"
  516.     regsub -- {^\\} $abpath "" path
  517.     } else {
  518.     if {![regexp -- {^[A-z]:} $abpath drive]} {
  519.         tixPanic "\"$abpath\" does not contain a drive letter"
  520.     }
  521.     set drive [string toupper $drive]
  522.  
  523.     regsub -- {^[A-z]:} $abpath "" path
  524.     }
  525.  
  526.     # Don't be fooled: $path doesn't need to be a directory. The following
  527.     # code "set path $path\\" just makes it easy to get rid of trailing
  528.     # . and ..
  529.     #
  530.     set path $path\\
  531.     regsub -all -- {[\\]+} $path \\ path
  532.     while {1} {
  533.     if {![regsub -- {\\[.]\\} $path "\\" path]} {break}
  534.     }
  535.     while {1} {
  536.     if {![regsub -- {\\[.]$} $path "" path]} {break}
  537.     }
  538.  
  539.     while {1} {
  540.     if {![regsub -- {\\[^\\]+\\[.][.]\\} $path "\\" path]} {break}
  541.     while {1} {
  542.         if {![regsub -- {^\\[.][.]\\} $path "\\" path]} {break}
  543.     }
  544.     }
  545.     while {1} {
  546.     if {![regsub -- {^\\[.][.]\\} $path "\\" path]} {break}
  547.     }
  548.  
  549.     regsub -- {[\\]+$} $path "" path
  550.     return $drive$path
  551. }
  552.  
  553. # Win
  554. #
  555. # tixFSNormDir --
  556. #
  557. #    Normalizes a directory
  558. #
  559. proc tixFSNormDir {dir} {
  560.     if {![tixFSIsAbsPath $dir]} {
  561.     error "\"$dir\" must be an absolute pathname"
  562.     }
  563.     if {![file isdir $dir]} {
  564.     error "\"$dir\" is not a directory"
  565.     }
  566.     return [_tixNormalize $dir]
  567. }
  568.  
  569.  
  570. proc tixPanic {message} {
  571.     error $message
  572. }
  573.  
  574. # tixFSIsValid --
  575. #
  576. #    Checks whether a native pathname contains invalid characters.
  577. #
  578. proc tixFSIsValid {path} {
  579.     return 1
  580. }
  581.  
  582. # Win
  583. #
  584. #
  585. proc tixFSIsVPath {vpath} {
  586.     global tixPriv
  587.     if {$tixPriv(isWin95)} {
  588.     # CYGNUS: Accept UNC path (\\host\dir)
  589.     if {[string match {xx\\xx\\\\\\*\\*} $vpath]} {
  590.         return 1
  591.     }
  592.     return [string match {xx\\xx\\[A-z]:*} $vpath]
  593.     } else {
  594.     return [string match {xx\\[A-z]:*} $vpath]
  595.     }
  596. }
  597.  
  598. # Win
  599. #
  600. # tixFSVPath --
  601. #
  602. #    Converts a normalized native pathname to its VPATH
  603. #
  604. proc tixFSVPath {path} {
  605.     global tixPriv
  606.  
  607.     tixAssert {
  608.     tixAssertNorm $path
  609.     }
  610.     return $tixPriv(WinPrefix)\\$path
  611. }
  612.  
  613. # tixFSPath --
  614. #
  615. #    Converts a vpath to a native pathname
  616. proc tixFSPath {vpath} {
  617.     global tixPriv
  618.     tixAssert {
  619.     tixAssertVPath $vpath
  620.     }
  621.     if {$tixPriv(isWin95)} {
  622.     set path [string range $vpath 6 end]
  623.     } else {
  624.     set path [string range $vpath 3 end]
  625.     }
  626.     regsub -- {:$} $path :\\ path
  627.  
  628.     return $path
  629. }
  630.  
  631. # tixFSDisplayName --
  632. #
  633. #    Returns the name of a normalized path which is usually displayed by
  634. #    the OS
  635. #
  636. proc tixFSDisplayName {normpath} {
  637.     tixAssert {
  638.     tixAssertNorm $normpath
  639.     }
  640.  
  641.     if {[regexp -- {^[A-z]:$} $normpath]} {
  642.     return $normpath\\
  643.     } else {
  644.     return $normpath
  645.     }
  646. }
  647.  
  648.  
  649. tixInitFileCmpt:Win 
  650.  
  651. }
  652.