| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
|
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 |
|
|---|
| 59 |
|
|---|
| 60 |
|
|---|
| 61 |
|
|---|
| 62 |
|
|---|
| 63 |
|
|---|
| 64 |
|
|---|
| 65 |
|
|---|
| 66 |
|
|---|
| 67 |
|
|---|
| 68 |
|
|---|
| 69 |
|
|---|
| 70 |
|
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
|
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 |
|
|---|
| 90 |
|
|---|
| 91 |
|
|---|
| 92 |
|
|---|
| 93 |
|
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 98 |
|
|---|
| 99 |
|
|---|
| 100 |
|
|---|
| 101 |
|
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
|
|---|
| 105 |
|
|---|
| 106 |
|
|---|
| 107 |
|
|---|
| 108 |
|
|---|
| 109 |
(defgroup archive nil |
|---|
| 110 |
"Simple editing of archives." |
|---|
| 111 |
:group 'data) |
|---|
| 112 |
|
|---|
| 113 |
(defgroup archive-arc nil |
|---|
| 114 |
"ARC-specific options to archive." |
|---|
| 115 |
:group 'archive) |
|---|
| 116 |
|
|---|
| 117 |
(defgroup archive-lzh nil |
|---|
| 118 |
"LZH-specific options to archive." |
|---|
| 119 |
:group 'archive) |
|---|
| 120 |
|
|---|
| 121 |
(defgroup archive-zip nil |
|---|
| 122 |
"ZIP-specific options to archive." |
|---|
| 123 |
:group 'archive) |
|---|
| 124 |
|
|---|
| 125 |
(defgroup archive-zoo nil |
|---|
| 126 |
"ZOO-specific options to archive." |
|---|
| 127 |
:group 'archive) |
|---|
| 128 |
|
|---|
| 129 |
(defcustom archive-tmpdir |
|---|
| 130 |
|
|---|
| 131 |
|
|---|
| 132 |
(make-temp-name |
|---|
| 133 |
(expand-file-name (if (eq system-type 'ms-dos) "ar" "archive.tmp") |
|---|
| 134 |
temporary-file-directory)) |
|---|
| 135 |
"Directory for temporary files made by `arc-mode.el'." |
|---|
| 136 |
:type 'directory |
|---|
| 137 |
:group 'archive) |
|---|
| 138 |
|
|---|
| 139 |
(defcustom archive-remote-regexp "^/[^/:]*[^/:.]:" |
|---|
| 140 |
"*Regexp recognizing archive files names that are not local. |
|---|
| 141 |
A non-local file is one whose file name is not proper outside Emacs. |
|---|
| 142 |
A local copy of the archive will be used when updating." |
|---|
| 143 |
:type 'regexp |
|---|
| 144 |
:group 'archive) |
|---|
| 145 |
|
|---|
| 146 |
(defcustom archive-extract-hooks nil |
|---|
| 147 |
"*Hooks to run when an archive member has been extracted." |
|---|
| 148 |
:type 'hook |
|---|
| 149 |
:group 'archive) |
|---|
| 150 |
|
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 |
|
|---|
| 154 |
|
|---|
| 155 |
(defcustom archive-arc-extract |
|---|
| 156 |
'("arc" "x") |
|---|
| 157 |
"*Program and its options to run in order to extract an arc file member. |
|---|
| 158 |
Extraction should happen to the current directory. Archive and member |
|---|
| 159 |
name will be added." |
|---|
| 160 |
:type '(list (string :tag "Program") |
|---|
| 161 |
(repeat :tag "Options" |
|---|
| 162 |
:inline t |
|---|
| 163 |
(string :format "%v"))) |
|---|
| 164 |
:group 'archive-arc) |
|---|
| 165 |
|
|---|
| 166 |
(defcustom archive-arc-expunge |
|---|
| 167 |
'("arc" "d") |
|---|
| 168 |
"*Program and its options to run in order to delete arc file members. |
|---|
| 169 |
Archive and member names will be added." |
|---|
| 170 |
:type '(list (string :tag "Program") |
|---|
| 171 |
(repeat :tag "Options" |
|---|
| 172 |
:inline t |
|---|
| 173 |
(string :format "%v"))) |
|---|
| 174 |
:group 'archive-arc) |
|---|
| 175 |
|
|---|
| 176 |
(defcustom archive-arc-write-file-member |
|---|
| 177 |
'("arc" "u") |
|---|
| 178 |
"*Program and its options to run in order to update an arc file member. |
|---|
| 179 |
Archive and member name will be added." |
|---|
| 180 |
:type '(list (string :tag "Program") |
|---|
| 181 |
(repeat :tag "Options" |
|---|
| 182 |
:inline t |
|---|
| 183 |
(string :format "%v"))) |
|---|
| 184 |
:group 'archive-arc) |
|---|
| 185 |
|
|---|
| 186 |
|
|---|
| 187 |
|
|---|
| 188 |
(defcustom archive-lzh-extract |
|---|
| 189 |
'("lha" "pq") |
|---|
| 190 |
"*Program and its options to run in order to extract an lzh file member. |
|---|
| 191 |
Extraction should happen to standard output. Archive and member name will |
|---|
| 192 |
be added." |
|---|
| 193 |
:type '(list (string :tag "Program") |
|---|
| 194 |
(repeat :tag "Options" |
|---|
| 195 |
:inline t |
|---|
| 196 |
(string :format "%v"))) |
|---|
| 197 |
:group 'archive-lzh) |
|---|
| 198 |
|
|---|
| 199 |
(defcustom archive-lzh-expunge |
|---|
| 200 |
'("lha" "d") |
|---|
| 201 |
"*Program and its options to run in order to delete lzh file members. |
|---|
| 202 |
Archive and member names will be added." |
|---|
| 203 |
:type '(list (string :tag "Program") |
|---|
| 204 |
(repeat :tag "Options" |
|---|
| 205 |
:inline t |
|---|
| 206 |
(string :format "%v"))) |
|---|
| 207 |
:group 'archive-lzh) |
|---|
| 208 |
|
|---|
| 209 |
(defcustom archive-lzh-write-file-member |
|---|
| 210 |
'("lha" "a") |
|---|
| 211 |
"*Program and its options to run in order to update an lzh file member. |
|---|
| 212 |
Archive and member name will be added." |
|---|
| 213 |
:type '(list (string :tag "Program") |
|---|
| 214 |
(repeat :tag "Options" |
|---|
| 215 |
:inline t |
|---|
| 216 |
(string :format "%v"))) |
|---|
| 217 |
:group 'archive-lzh) |
|---|
| 218 |
|
|---|
| 219 |
|
|---|
| 220 |
|
|---|
| 221 |
(defcustom archive-zip-extract |
|---|
| 222 |
(if (and (not (executable-find "unzip")) |
|---|
| 223 |
(executable-find "pkunzip")) |
|---|
| 224 |
'("pkunzip" "-e" "-o-") |
|---|
| 225 |
'("unzip" "-qq" "-c")) |
|---|
| 226 |
"*Program and its options to run in order to extract a zip file member. |
|---|
| 227 |
Extraction should happen to standard output. Archive and member name will |
|---|
| 228 |
be added." |
|---|
| 229 |
:type '(list (string :tag "Program") |
|---|
| 230 |
(repeat :tag "Options" |
|---|
| 231 |
:inline t |
|---|
| 232 |
(string :format "%v"))) |
|---|
| 233 |
:group 'archive-zip) |
|---|
| 234 |
|
|---|
| 235 |
|
|---|
| 236 |
|
|---|
| 237 |
|
|---|
| 238 |
|
|---|
| 239 |
|
|---|
| 240 |
(defcustom archive-zip-expunge |
|---|
| 241 |
(if (and (not (executable-find "zip")) |
|---|
| 242 |
(executable-find "pkzip")) |
|---|
| 243 |
'("pkzip" "-d") |
|---|
| 244 |
'("zip" "-d" "-q")) |
|---|
| 245 |
"*Program and its options to run in order to delete zip file members. |
|---|
| 246 |
Archive and member names will be added." |
|---|
| 247 |
:type '(list (string :tag "Program") |
|---|
| 248 |
(repeat :tag "Options" |
|---|
| 249 |
:inline t |
|---|
| 250 |
(string :format "%v"))) |
|---|
| 251 |
:group 'archive-zip) |
|---|
| 252 |
|
|---|
| 253 |
(defcustom archive-zip-update |
|---|
| 254 |
(if (and (not (executable-find "zip")) |
|---|
| 255 |
(executable-find "pkzip")) |
|---|
| 256 |
'("pkzip" "-u" "-P") |
|---|
| 257 |
'("zip" "-q")) |
|---|
| 258 |
"*Program and its options to run in order to update a zip file member. |
|---|
| 259 |
Options should ensure that specified directory will be put into the zip |
|---|
| 260 |
file. Archive and member name will be added." |
|---|
| 261 |
:type '(list (string :tag "Program") |
|---|
| 262 |
(repeat :tag "Options" |
|---|
| 263 |
:inline t |
|---|
| 264 |
(string :format "%v"))) |
|---|
| 265 |
:group 'archive-zip) |
|---|
| 266 |
|
|---|
| 267 |
(defcustom archive-zip-update-case |
|---|
| 268 |
(if (and (not (executable-find "zip")) |
|---|
| 269 |
(executable-find "pkzip")) |
|---|
| 270 |
'("pkzip" "-u" "-P") |
|---|
| 271 |
'("zip" "-q" "-k")) |
|---|
| 272 |
"*Program and its options to run in order to update a case fiddled zip member. |
|---|
| 273 |
Options should ensure that specified directory will be put into the zip file. |
|---|
| 274 |
Archive and member name will be added." |
|---|
| 275 |
:type '(list (string :tag "Program") |
|---|
| 276 |
(repeat :tag "Options" |
|---|
| 277 |
:inline t |
|---|
| 278 |
(string :format "%v"))) |
|---|
| 279 |
:group 'archive-zip) |
|---|
| 280 |
|
|---|
| 281 |
(defcustom archive-zip-case-fiddle t |
|---|
| 282 |
"*If non-nil then zip file members may be down-cased. |
|---|
| 283 |
This case fiddling will only happen for members created by a system |
|---|
| 284 |
that uses caseless file names." |
|---|
| 285 |
:type 'boolean |
|---|
| 286 |
:group 'archive-zip) |
|---|
| 287 |
|
|---|
| 288 |
|
|---|
| 289 |
|
|---|
| 290 |
(defcustom archive-zoo-extract |
|---|
| 291 |
'("zoo" "xpq") |
|---|
| 292 |
"*Program and its options to run in order to extract a zoo file member. |
|---|
| 293 |
Extraction should happen to standard output. Archive and member name will |
|---|
| 294 |
be added." |
|---|
| 295 |
:type '(list (string :tag "Program") |
|---|
| 296 |
(repeat :tag "Options" |
|---|
| 297 |
:inline t |
|---|
| 298 |
(string :format "%v"))) |
|---|
| 299 |
:group 'archive-zoo) |
|---|
| 300 |
|
|---|
| 301 |
(defcustom archive-zoo-expunge |
|---|
| 302 |
'("zoo" "DqPP") |
|---|
| 303 |
"*Program and its options to run in order to delete zoo file members. |
|---|
| 304 |
Archive and member names will be added." |
|---|
| 305 |
:type '(list (string :tag "Program") |
|---|
| 306 |
(repeat :tag "Options" |
|---|
| 307 |
:inline t |
|---|
| 308 |
(string :format "%v"))) |
|---|
| 309 |
:group 'archive-zoo) |
|---|
| 310 |
|
|---|
| 311 |
(defcustom archive-zoo-write-file-member |
|---|
| 312 |
'("zoo" "a") |
|---|
| 313 |
"*Program and its options to run in order to update a zoo file member. |
|---|
| 314 |
Archive and member name will be added." |
|---|
| 315 |
:type '(list (string :tag "Program") |
|---|
| 316 |
(repeat :tag "Options" |
|---|
| 317 |
:inline t |
|---|
| 318 |
(string :format "%v"))) |
|---|
| 319 |
:group 'archive-zoo) |
|---|
| 320 |
|
|---|
| 321 |
|
|---|
| 322 |
|
|---|
| 323 |
(defvar archive-subtype nil "Symbol describing archive type.") |
|---|
| 324 |
(defvar archive-file-list-start nil "Position of first contents line.") |
|---|
| 325 |
(defvar archive-file-list-end nil "Position just after last contents line.") |
|---|
| 326 |
(defvar archive-proper-file-start nil "Position of real archive's start.") |
|---|
| 327 |
(defvar archive-read-only nil "Non-nil if the archive is read-only on disk.") |
|---|
| 328 |
(defvar archive-local-name nil "Name of local copy of remote archive.") |
|---|
| 329 |
(defvar archive-mode-map |
|---|
| 330 |
(let ((map (make-keymap))) |
|---|
| 331 |
(suppress-keymap map) |
|---|
| 332 |
(define-key map " " 'archive-next-line) |
|---|
| 333 |
(define-key map "a" 'archive-alternate-display) |
|---|
| 334 |
|
|---|
| 335 |
(define-key map "d" 'archive-flag-deleted) |
|---|
| 336 |
(define-key map "\C-d" 'archive-flag-deleted) |
|---|
| 337 |
(define-key map "e" 'archive-extract) |
|---|
| 338 |
(define-key map "f" 'archive-extract) |
|---|
| 339 |
(define-key map "\C-m" 'archive-extract) |
|---|
| 340 |
(define-key map "g" 'revert-buffer) |
|---|
| 341 |
(define-key map "h" 'describe-mode) |
|---|
| 342 |
(define-key map "m" 'archive-mark) |
|---|
| 343 |
(define-key map "n" 'archive-next-line) |
|---|
| 344 |
(define-key map "\C-n" 'archive-next-line) |
|---|
| 345 |
(define-key map [down] 'archive-next-line) |
|---|
| 346 |
(define-key map "o" 'archive-extract-other-window) |
|---|
| 347 |
(define-key map "p" 'archive-previous-line) |
|---|
| 348 |
(define-key map "q" 'quit-window) |
|---|
| 349 |
(define-key map "\C-p" 'archive-previous-line) |
|---|
| 350 |
(define-key map [up] 'archive-previous-line) |
|---|
| 351 |
(define-key map "r" 'archive-rename-entry) |
|---|
| 352 |
(define-key map "u" 'archive-unflag) |
|---|
| 353 |
(define-key map "\M-\C-?" 'archive-unmark-all-files) |
|---|
| 354 |
(define-key map "v" 'archive-view) |
|---|
| 355 |
(define-key map "x" 'archive-expunge) |
|---|
| 356 |
(define-key map "\177" 'archive-unflag-backwards) |
|---|
| 357 |
(define-key map "E" 'archive-extract-other-window) |
|---|
| 358 |
(define-key map "M" 'archive-chmod-entry) |
|---|
| 359 |
(define-key map "G" 'archive-chgrp-entry) |
|---|
| 360 |
(define-key map "O" 'archive-chown-entry) |
|---|
| 361 |
|
|---|
| 362 |
(if (fboundp 'command-remapping) |
|---|
| 363 |
(progn |
|---|
| 364 |
(define-key map [remap advertised-undo] 'archive-undo) |
|---|
| 365 |
(define-key map [remap undo] 'archive-undo)) |
|---|
| 366 |
(substitute-key-definition 'advertised-undo 'archive-undo map global-map) |
|---|
| 367 |
(substitute-key-definition 'undo 'archive-undo map global-map)) |
|---|
| 368 |
|
|---|
| 369 |
(define-key map |
|---|
| 370 |
(if (featurep 'xemacs) 'button2 [mouse-2]) 'archive-extract) |
|---|
| 371 |
|
|---|
| 372 |
(if (featurep 'xemacs) |
|---|
| 373 |
() |
|---|
| 374 |
|
|---|
| 375 |
(define-key map [menu-bar immediate] |
|---|
| 376 |
(cons "Immediate" (make-sparse-keymap "Immediate"))) |
|---|
| 377 |
(define-key map [menu-bar immediate alternate] |
|---|
| 378 |
'(menu-item "Alternate Display" archive-alternate-display |
|---|
| 379 |
:enable (boundp (archive-name "alternate-display")) |
|---|
| 380 |
:help "Toggle alternate file info display")) |
|---|
| 381 |
(define-key map [menu-bar immediate view] |
|---|
| 382 |
'(menu-item "View This File" archive-view |
|---|
| 383 |
:help "Display file at cursor in View Mode")) |
|---|
| 384 |
(define-key map [menu-bar immediate display] |
|---|
| 385 |
'(menu-item "Display in Other Window" archive-display-other-window |
|---|
| 386 |
:help "Display file at cursor in another window")) |
|---|
| 387 |
(define-key map [menu-bar immediate find-file-other-window] |
|---|
| 388 |
'(menu-item "Find in Other Window" archive-extract-other-window |
|---|
| 389 |
:help "Edit file at cursor in another window")) |
|---|
| 390 |
(define-key map [menu-bar immediate find-file] |
|---|
| 391 |
'(menu-item "Find This File" archive-extract |
|---|
| 392 |
:help "Extract file at cursor and edit it")) |
|---|
| 393 |
|
|---|
| 394 |
(define-key map [menu-bar mark] |
|---|
| 395 |
(cons "Mark" (make-sparse-keymap "Mark"))) |
|---|
| 396 |
(define-key map [menu-bar mark unmark-all] |
|---|
| 397 |
'(menu-item "Unmark All" archive-unmark-all-files |
|---|
| 398 |
:help "Unmark all marked files")) |
|---|
| 399 |
(define-key map [menu-bar mark deletion] |
|---|
| 400 |
'(menu-item "Flag" archive-flag-deleted |
|---|
| 401 |
:help "Flag file at cursor for deletion")) |
|---|
| 402 |
(define-key map [menu-bar mark unmark] |
|---|
| 403 |
'(menu-item "Unflag" archive-unflag |
|---|
| 404 |
:help "Unmark file at cursor")) |
|---|
| 405 |
(define-key map [menu-bar mark mark] |
|---|
| 406 |
'(menu-item "Mark" archive-mark |
|---|
| 407 |
:help "Mark file at cursor")) |
|---|
| 408 |
|
|---|
| 409 |
(define-key map [menu-bar operate] |
|---|
| 410 |
(cons "Operate" (make-sparse-keymap "Operate"))) |
|---|
| 411 |
(define-key map [menu-bar operate chown] |
|---|
| 412 |
'(menu-item "Change Owner..." archive-chown-entry |
|---|
| 413 |
:enable (fboundp (archive-name "chown-entry")) |
|---|
| 414 |
:help "Change owner of marked files")) |
|---|
| 415 |
(define-key map [menu-bar operate chgrp] |
|---|
| 416 |
'(menu-item "Change Group..." archive-chgrp-entry |
|---|
| 417 |
:enable (fboundp (archive-name "chgrp-entry")) |
|---|
| 418 |
:help "Change group ownership of marked files")) |
|---|
| 419 |
(define-key map [menu-bar operate chmod] |
|---|
| 420 |
'(menu-item "Change Mode..." archive-chmod-entry |
|---|
| 421 |
:enable (fboundp (archive-name "chmod-entry")) |
|---|
| 422 |
:help "Change mode (permissions) of marked files")) |
|---|
| 423 |
(define-key map [menu-bar operate rename] |
|---|
| 424 |
'(menu-item "Rename to..." archive-rename-entry |
|---|
| 425 |
:enable (fboundp (archive-name "rename-entry")) |
|---|
| 426 |
:help "Rename marked files")) |
|---|
| 427 |
|
|---|
| 428 |
|
|---|
| 429 |
(define-key map [menu-bar operate expunge] |
|---|
| 430 |
'(menu-item "Expunge Marked Files" archive-expunge |
|---|
| 431 |
:help "Delete all flagged files from archive")) |
|---|
| 432 |
map)) |
|---|
| 433 |
"Local keymap for archive mode listings.") |
|---|
| 434 |
(defvar archive-file-name-indent nil "Column where file names start.") |
|---|
| 435 |
|
|---|
| 436 |
(defvar archive-remote nil "Non-nil if the archive is outside file system.") |
|---|
| 437 |
(make-variable-buffer-local 'archive-remote) |
|---|
| 438 |
(put 'archive-remote 'permanent-local t) |
|---|
| 439 |
|
|---|
| 440 |
(defvar archive-member-coding-system nil "Coding-system of archive member.") |
|---|
| 441 |
(make-variable-buffer-local 'archive-member-coding-system) |
|---|
| 442 |
|
|---|
| 443 |
(defvar archive-alternate-display nil |
|---|
| 444 |
"Non-nil when alternate information is shown.") |
|---|
| 445 |
(make-variable-buffer-local 'archive-alternate-display) |
|---|
| 446 |
(put 'archive-alternate-display 'permanent-local t) |
|---|
| 447 |
|
|---|
| 448 |
(defvar archive-superior-buffer nil "In archive members, points to archive.") |
|---|
| 449 |
(put 'archive-superior-buffer 'permanent-local t) |
|---|
| 450 |
|
|---|
| 451 |
(defvar archive-subfile-mode nil "Non-nil in archive member buffers.") |
|---|
| 452 |
(make-variable-buffer-local 'archive-subfile-mode) |
|---|
| 453 |
(put 'archive-subfile-mode 'permanent-local t) |
|---|
| 454 |
|
|---|
| 455 |
(defvar archive-files nil |
|---|
| 456 |
"Vector of file descriptors. |
|---|
| 457 |
Each descriptor is a vector of the form |
|---|
| 458 |
[EXT-FILE-NAME INT-FILE-NAME CASE-FIDDLED MODE ...]") |
|---|
| 459 |
(make-variable-buffer-local 'archive-files) |
|---|
| 460 |
|
|---|
| 461 |
|
|---|
| 462 |
|
|---|
| 463 |
|
|---|
| 464 |
(defsubst archive-name (suffix) |
|---|
| 465 |
(intern (concat "archive-" (symbol-name archive-subtype) "-" suffix))) |
|---|
| 466 |
|
|---|
| 467 |
(defun archive-l-e (str &optional len float) |
|---|
| 468 |
"Convert little endian string/vector STR to integer. |
|---|
| 469 |
Alternatively, STR may be a buffer position in the current buffer |
|---|
| 470 |
in which case a second argument, length LEN, should be supplied. |
|---|
| 471 |
FLOAT, if non-nil, means generate and return a float instead of an integer |
|---|
| 472 |
\(use this for numbers that can overflow the Emacs integer)." |
|---|
| 473 |
(if (stringp str) |
|---|
| 474 |
(setq len (length str)) |
|---|
| 475 |
(setq str (buffer-substring str (+ str len)))) |
|---|
| 476 |
(let ((result 0) |
|---|
| 477 |
(i 0)) |
|---|
| 478 |
(while (< i len) |
|---|
| 479 |
(setq i (1+ i) |
|---|
| 480 |
result (+ (if float (* result 256.0) (ash result 8)) |
|---|
| 481 |
(aref str (- len i))))) |
|---|
| 482 |
result)) |
|---|
| 483 |
|
|---|
| 484 |
(defun archive-int-to-mode (mode) |
|---|
| 485 |
"Turn an integer like 0700 (i.e., 448) into a mode string like -rwx------." |
|---|
| 486 |
|
|---|
| 487 |
(string |
|---|
| 488 |
(if (zerop (logand 8192 mode)) |
|---|
| 489 |
(if (zerop (logand 16384 mode)) ?- ?d) |
|---|
| 490 |
?c) |
|---|
| 491 |
(if (zerop (logand 256 mode)) ?- ?r) |
|---|
| 492 |
(if (zerop (logand 128 mode)) ?- ?w) |
|---|
| 493 |
(if (zerop (logand 64 mode)) |
|---|
| 494 |
(if (zerop (logand 1024 mode)) ?- ?S) |
|---|
| 495 |
(if (zerop (logand 1024 mode)) ?x ?s)) |
|---|
| 496 |
(if (zerop (logand 32 mode)) ?- ?r) |
|---|
| 497 |
(if (zerop (logand 16 mode)) ?- ?w) |
|---|
| 498 |
(if (zerop (logand 8 mode)) |
|---|
| 499 |
(if (zerop (logand 2048 mode)) ?- ?S) |
|---|
| 500 |
(if (zerop (logand 2048 mode)) ?x ?s)) |
|---|
| 501 |
(if (zerop (logand 4 mode)) ?- ?r) |
|---|
| 502 |
(if (zerop (logand 2 mode)) ?- ?w) |
|---|
| 503 |
(if (zerop (logand 1 mode)) ?- ?x))) |
|---|
| 504 |
|
|---|
| 505 |
(defun archive-calc-mode (oldmode newmode &optional error) |
|---|
| 506 |
"From the integer OLDMODE and the string NEWMODE calculate a new file mode. |
|---|
| 507 |
NEWMODE may be an octal number including a leading zero in which case it |
|---|
| 508 |
will become the new mode.\n |
|---|
| 509 |
NEWMODE may also be a relative specification like \"og-rwx\" in which case |
|---|
| 510 |
OLDMODE will be modified accordingly just like chmod(2) would have done.\n |
|---|
| 511 |
If optional third argument ERROR is non-nil an error will be signaled if |
|---|
| 512 |
the mode is invalid. If ERROR is nil then nil will be returned." |
|---|
| 513 |
(cond ((string-match "^0[0-7]*$" newmode) |
|---|
| 514 |
(let ((result 0) |
|---|
| 515 |
(len (length newmode)) |
|---|
| 516 |
(i 1)) |
|---|
| 517 |
(while (< i len) |
|---|
| 518 |
(setq result (+ (lsh result 3) (aref newmode i) (- ?0)) |
|---|
| 519 |
i (1+ i))) |
|---|
| 520 |
(logior (logand oldmode 65024) result))) |
|---|
| 521 |
((string-match "^\\([agou]+\\)\\([---+=]\\)\\([rwxst]+\\)$" newmode) |
|---|
| 522 |
(let ((who 0) |
|---|
| 523 |
(result oldmode) |
|---|
| 524 |
(op (aref newmode (match-beginning 2))) |
|---|
| 525 |
(bits 0) |
|---|
| 526 |
(i (match-beginning 3))) |
|---|
| 527 |
(while (< i (match-end 3)) |
|---|
| 528 |
(let ((rwx (aref newmode i))) |
|---|
| 529 |
(setq bits (logior bits (cond ((= rwx ?r) 292) |
|---|
| 530 |
((= rwx ?w) 146) |
|---|
| 531 |
((= rwx ?x) 73) |
|---|
| 532 |
((= rwx ?s) 3072) |
|---|
| 533 |
((= rwx ?t) 512))) |
|---|
| 534 |
i (1+ i)))) |
|---|
| 535 |
(while (< who (match-end 1)) |
|---|
| 536 |
(let* ((whoc (aref newmode who)) |
|---|
| 537 |
(whomask (cond ((= whoc ?a) 4095) |
|---|
| 538 |
((= whoc ?u) 1472) |
|---|
| 539 |
((= whoc ?g) 2104) |
|---|
| 540 |
((= whoc ?o) 7)))) |
|---|
| 541 |
(if (= op ?=) |
|---|
| 542 |
(setq result (logand result (lognot whomask)))) |
|---|
| 543 |
(if (= op ?-) |
|---|
| 544 |
(setq result (logand result (lognot (logand whomask bits)))) |
|---|
| 545 |
(setq result (logior result (logand whomask bits))))) |
|---|
| 546 |
(setq who (1+ who))) |
|---|
| 547 |
result)) |
|---|
| 548 |
(t |
|---|
| 549 |
(if error |
|---|
| 550 |
(error "Invalid mode specification: %s" newmode))))) |
|---|
| 551 |
|
|---|
| 552 |
(defun archive-dosdate (date) |
|---|
| 553 |
"Stringify dos packed DATE record." |
|---|
| 554 |
(let ((year (+ 1980 (logand (ash date -9) 127))) |
|---|
| 555 |
(month (logand (ash date -5) 15)) |
|---|
| 556 |
(day (logand date 31))) |
|---|
| 557 |
(if (or (> month 12) (< month 1)) |
|---|
| 558 |
"" |
|---|
| 559 |
(format "%2d-%s-%d" |
|---|
| 560 |
day |
|---|
| 561 |
(aref ["Jan" "Feb" "Mar" "Apr" "May" "Jun" |
|---|
| 562 |
"Jul" "Aug" "Sep" "Oct" "Nov" "Dec"] (1- month)) |
|---|
| 563 |
year)))) |
|---|
| 564 |
|
|---|
| 565 |
(defun archive-dostime (time) |
|---|
| 566 |
"Stringify dos packed TIME record." |
|---|
| 567 |
(let ((hour (logand (ash time -11) 31)) |
|---|
| 568 |
(minute (logand (ash time -5) 63)) |
|---|
| 569 |
(second (* 2 (logand time 31)))) |
|---|
| 570 |
(format "%02d:%02d:%02d" hour minute second))) |
|---|
| 571 |
|
|---|
| 572 |
(defun archive-unixdate (low high) |
|---|
| 573 |
"Stringify Unix (LOW HIGH) date." |
|---|
| 574 |
(let ((str (current-time-string (cons high low)))) |
|---|
| 575 |
(format "%s-%s-%s" |
|---|
| 576 |
(substring str 8 10) |
|---|
| 577 |
(substring str 4 7) |
|---|
| 578 |
(substring str 20 24)))) |
|---|
| 579 |
|
|---|
| 580 |
(defun archive-unixtime (low high) |
|---|
| 581 |
"Stringify Unix (LOW HIGH) time." |
|---|
| 582 |
(let ((str (current-time-string (cons high low)))) |
|---|
| 583 |
(substring str 11 19))) |
|---|
| 584 |
|
|---|
| 585 |
(defun archive-get-lineno () |
|---|
| 586 |
(if (>= (point) archive-file-list-start) |
|---|
| 587 |
(count-lines archive-file-list-start |
|---|
| 588 |
(save-excursion (beginning-of-line) (point))) |
|---|
| 589 |
0)) |
|---|
| 590 |
|
|---|
| 591 |
(defun archive-get-descr (&optional noerror) |
|---|
| 592 |
"Return the descriptor vector for file at point. |
|---|
| 593 |
Does not signal an error if optional argument NOERROR is non-nil." |
|---|
| 594 |
(let ((no (archive-get-lineno))) |
|---|
| 595 |
(if (and (>= (point) archive-file-list-start) |
|---|
| 596 |
(< no (length archive-files))) |
|---|
| 597 |
(let ((item (aref archive-files no))) |
|---|
| 598 |
(if (vectorp item) |
|---|
| 599 |
item |
|---|
| 600 |
(if (not noerror) |
|---|
| 601 |
(error "Entry is not a regular member of the archive")))) |
|---|
| 602 |
(if (not noerror) |
|---|
| 603 |
(error "Line does not describe a member of the archive"))))) |
|---|
| 604 |
|
|---|
| 605 |
|
|---|
| 606 |
|
|---|
| 607 |
|
|---|
| 608 |
(defun archive-mode (&optional force) |
|---|
| 609 |
"Major mode for viewing an archive file in a dired-like way. |
|---|
| 610 |
You can move around using the usual cursor motion commands. |
|---|
| 611 |
Letters no longer insert themselves. |
|---|
| 612 |
Type `e' to pull a file out of the archive and into its own buffer; |
|---|
| 613 |
or click mouse-2 on the file's line in the archive mode buffer. |
|---|
| 614 |
|
|---|
| 615 |
If you edit a sub-file of this archive (as with the `e' command) and |
|---|
| 616 |
save it, the contents of that buffer will be saved back into the |
|---|
| 617 |
archive. |
|---|
| 618 |
|
|---|
| 619 |
\\{archive-mode-map}" |
|---|
| 620 |
|
|---|
| 621 |
|
|---|
| 622 |
(if (zerop (buffer-size)) |
|---|
| 623 |
|
|---|
| 624 |
(funcall default-major-mode) |
|---|
| 625 |
(if (and (not force) archive-files) nil |
|---|
| 626 |
(let* ((type (archive-find-type)) |
|---|
| 627 |
(typename (capitalize (symbol-name type)))) |
|---|
| 628 |
(kill-all-local-variables) |
|---|
| 629 |
(make-local-variable 'archive-subtype) |
|---|
| 630 |
(setq archive-subtype type) |
|---|
| 631 |
|
|---|
| 632 |
|
|---|
| 633 |
(make-local-variable 'revert-buffer-function) |
|---|
| 634 |
(setq revert-buffer-function 'archive-mode-revert) |
|---|
| 635 |
(auto-save-mode 0) |
|---|
| 636 |
|
|---|
| 637 |
|
|---|
| 638 |
(if archive-remote nil |
|---|
| 639 |
(add-hook 'write-contents-functions 'archive-write-file nil t)) |
|---|
| 640 |
|
|---|
| 641 |
(make-local-variable 'require-final-newline) |
|---|
| 642 |
(setq require-final-newline nil) |
|---|
| 643 |
(make-local-variable 'local-enable-local-variables) |
|---|
| 644 |
(setq local-enable-local-variables nil) |
|---|
| 645 |
|
|---|
| 646 |
|
|---|
| 647 |
(make-local-variable 'file-precious-flag) |
|---|
| 648 |
(setq file-precious-flag t) |
|---|
| 649 |
|
|---|
| 650 |
(make-local-variable 'archive-read-only) |
|---|
| 651 |
|
|---|
| 652 |
|
|---|
| 653 |
(setq archive-read-only |
|---|
| 654 |
(or (not (file-writable-p (buffer-file-name))) |
|---|
| 655 |
(and archive-subfile-mode |
|---|
| 656 |
(string-match file-name-invalid-regexp |
|---|
| 657 |
(aref archive-subfile-mode 0))))) |
|---|
| 658 |
|
|---|
| 659 |
|
|---|
| 660 |
(make-local-variable 'archive-local-name) |
|---|
| 661 |
|
|---|
| 662 |
|
|---|
| 663 |
|
|---|
| 664 |
(or archive-remote |
|---|
| 665 |
(setq archive-remote |
|---|
| 666 |
(or (string-match archive-remote-regexp (buffer-file-name)) |
|---|
| 667 |
(string-match file-name-invalid-regexp |
|---|
| 668 |
(buffer-file-name))))) |
|---|
| 669 |
|
|---|
| 670 |
(setq major-mode 'archive-mode) |
|---|
| 671 |
(setq mode-name (concat typename "-Archive")) |
|---|
| 672 |
|
|---|
| 673 |
(run-mode-hooks (archive-name "mode-hook") 'archive-mode-hook) |
|---|
| 674 |
(use-local-map archive-mode-map)) |
|---|
| 675 |
|
|---|
| 676 |
(make-local-variable 'archive-proper-file-start) |
|---|
| 677 |
(make-local-variable 'archive-file-list-start) |
|---|
| 678 |
(make-local-variable 'archive-file-list-end) |
|---|
| 679 |
(make-local-variable 'archive-file-name-indent) |
|---|
| 680 |
(archive-summarize nil) |
|---|
| 681 |
(setq buffer-read-only t)))) |
|---|
| 682 |
|
|---|
| 683 |
|
|---|
| 684 |
(put 'archive-mode 'mode-class 'special) |
|---|
| 685 |
|
|---|
| 686 |
(let ((item1 '(archive-subfile-mode " Archive"))) |
|---|
| 687 |
(or (member item1 minor-mode-alist) |
|---|
| 688 |
(setq minor-mode-alist (cons item1 minor-mode-alist)))) |
|---|
| 689 |
|
|---|
| 690 |
(defun archive-find-type () |
|---|
| 691 |
(widen) |
|---|
| 692 |
(goto-char (point-min)) |
|---|
| 693 |
|
|---|
| 694 |
|
|---|
| 695 |
(let (case-fold-search) |
|---|
| 696 |
(cond ((looking-at "[P]K\003\004") 'zip) |
|---|
| 697 |
((looking-at "..-l[hz][0-9ds]-") 'lzh) |
|---|
| 698 |
((looking-at "....................[\334]\247\304\375") 'zoo) |
|---|
| 699 |
((and (looking-at "\C-z") |
|---|
| 700 |
(string-match "\\.[aA][rR][cC]$" |
|---|
| 701 |
(or buffer-file-name (buffer-name)))) |
|---|
| 702 |
'arc) |
|---|
| 703 |
|
|---|
| 704 |
|
|---|
| 705 |
|
|---|
| 706 |
((looking-at "MZ\\(.\\|\n\\)\\{34\\}LH[aA]'s SFX ") 'lzh-exe) |
|---|
| 707 |
(t (error "Buffer format not recognized"))))) |
|---|
| 708 |
|
|---|
| 709 |
(defun archive-summarize (&optional shut-up) |
|---|
| 710 |
"Parse the contents of the archive file in the current buffer. |
|---|
| 711 |
Place a dired-like listing on the front; |
|---|
| 712 |
then narrow to it, so that only that listing |
|---|
| 713 |
is visible (and the real data of the buffer is hidden). |
|---|
| 714 |
Optional argument SHUT-UP, if non-nil, means don't print messages |
|---|
| 715 |
when parsing the archive." |
|---|
| 716 |
(widen) |
|---|
| 717 |
(set-buffer-multibyte nil) |
|---|
| 718 |
(let ((inhibit-read-only t)) |
|---|
| 719 |
(or shut-up |
|---|
| 720 |
(message "Parsing archive file...")) |
|---|
| 721 |
(buffer-disable-undo (current-buffer)) |
|---|
| 722 |
(setq archive-files (funcall (archive-name "summarize"))) |
|---|
| 723 |
(or shut-up |
|---|
| 724 |
(message "Parsing archive file...done.")) |
|---|
| 725 |
(setq archive-proper-file-start (point-marker)) |
|---|
| 726 |
(narrow-to-region (point-min) (point)) |
|---|
| 727 |
(set-buffer-modified-p nil) |
|---|
| 728 |
(buffer-enable-undo)) |
|---|
| 729 |
(goto-char archive-file-list-start) |
|---|
| 730 |
(archive-next-line 0)) |
|---|
| 731 |
|
|---|
| 732 |
(defun archive-resummarize () |
|---|
| 733 |
"Recreate the contents listing of an archive." |
|---|
| 734 |
(let ((modified (buffer-modified-p)) |
|---|
| 735 |
(no (archive-get-lineno)) |
|---|
| 736 |
(inhibit-read-only t)) |
|---|
| 737 |
(widen) |
|---|
| 738 |
(delete-region (point-min) archive-proper-file-start) |
|---|
| 739 |
(archive-summarize t) |
|---|
| 740 |
(restore-buffer-modified-p modified) |
|---|
| 741 |
(goto-char archive-file-list-start) |
|---|
| 742 |
(archive-next-line no))) |
|---|
| 743 |
|
|---|
| 744 |
(defun archive-summarize-files (files) |
|---|
| 745 |
"Insert a description of a list of files annotated with proper mouse face." |
|---|
| 746 |
(setq archive-file-list-start (point-marker)) |
|---|
| 747 |
(setq archive-file-name-indent (if files (aref (car files) 1) 0)) |
|---|
| 748 |
|
|---|
| 749 |
|
|---|
| 750 |
(insert |
|---|
| 751 |
(apply |
|---|
| 752 |
(function concat) |
|---|
| 753 |
(mapcar |
|---|
| 754 |
(lambda (fil) |
|---|
| 755 |
|
|---|
| 756 |
|
|---|
| 757 |
(let ((text (concat (aref fil 0) "\n"))) |
|---|
| 758 |
(if (featurep 'xemacs) |
|---|
| 759 |
() |
|---|
| 760 |
|
|---|