Mercurial > hg > xemacs-beta
annotate src/dired-msw.c @ 5658:289cf21be887
Don't augment ENVIRONMENT when that's not indicated, #'macroexpand.
This reflects better understanding on my part of the &environment macro
keyword, and I've expanded the Lisp manual and docstrings to reflect that.
lisp/ChangeLog addition:
2012-05-06 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (block): Comment on why we can't use &environment
here.
* cl-macs.el (defmacro*): Document &environment in more detail.
* cl-macs.el (macrolet): Use &environment, instead of referencing
byte-compile-macro-environment directly.
* cl-macs.el (symbol-macrolet): Ditto.
* cl-macs.el (lexical-let): Ditto.
* cl-macs.el (labels): Ditto.
man/ChangeLog addition:
2012-05-06 Aidan Kehoe <kehoea@parhasard.net>
* lispref/macros.texi (Expansion):
Cross-reference to documentation of #'cl-prettyexpand, #'defmacro*
when talking about #'macroexpand.
tests/ChangeLog addition:
2012-05-06 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Use &environment appropriately in #'macrolet, instead of relying
on #'macroexpand to guess what we mean.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sun, 06 May 2012 15:29:59 +0100 |
parents | 2aa9cd456ae7 |
children |
rev | line source |
---|---|
428 | 1 /* fast dired replacement routines for mswindows. |
2 Copyright (C) 1998 Darryl Okahata | |
3 Portions Copyright (C) 1992, 1994 by Sebastian Kremer <sk@thp.uni-koeln.de> | |
800 | 4 Copyright (C) 2000, 2001, 2002 Ben Wing. |
428 | 5 |
6 This file is part of XEmacs. | |
7 | |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
4976
diff
changeset
|
8 XEmacs is free software: you can redistribute it and/or modify it |
428 | 9 under the terms of the GNU General Public License as published by the |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
4976
diff
changeset
|
10 Free Software Foundation, either version 3 of the License, or (at your |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
4976
diff
changeset
|
11 option) any later version. |
428 | 12 |
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
4976
diff
changeset
|
19 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
428 | 20 |
21 /* Synched up with: Not in FSF. */ | |
22 | |
771 | 23 |
428 | 24 /* |
25 * Parts of this code (& comments) were taken from ls-lisp.el | |
26 * Author: Sebastian Kremer <sk@thp.uni-koeln.de> | |
27 */ | |
28 | |
29 /* | |
30 * insert-directory | |
31 * - must insert _exactly_one_line_ describing FILE if WILDCARD and | |
32 * FULL-DIRECTORY-P is nil. | |
33 * The single line of output must display FILE's name as it was | |
34 * given, namely, an absolute path name. | |
35 * - must insert exactly one line for each file if WILDCARD or | |
36 * FULL-DIRECTORY-P is t, plus one optional "total" line | |
37 * before the file lines, plus optional text after the file lines. | |
38 * Lines are delimited by "\n", so filenames containing "\n" are not | |
39 * allowed. | |
40 * File lines should display the basename. | |
41 * - must be consistent with | |
42 * - functions dired-move-to-filename, (these two define what a file line is) | |
43 * dired-move-to-end-of-filename, | |
44 * dired-between-files, (shortcut for (not (dired-move-to-filename))) | |
45 * dired-insert-headerline | |
46 * dired-after-subdir-garbage (defines what a "total" line is) | |
47 * - variable dired-subdir-regexp | |
48 */ | |
49 | |
50 /* | |
51 * Insert directory listing for FILE, formatted according to SWITCHES. | |
52 * Leaves point after the inserted text. | |
53 * SWITCHES may be a string of options, or a list of strings. | |
54 * Optional third arg WILDCARD means treat FILE as shell wildcard. | |
55 * Optional fourth arg FULL-DIRECTORY-P means file is a directory and | |
56 * switches do not contain `d', so that a full listing is expected. | |
57 * | |
58 * This works by running a directory listing program | |
59 * whose name is in the variable `insert-directory-program'. | |
60 * If WILDCARD, it also runs the shell specified by `shell-file-name'." | |
61 */ | |
62 | |
63 /* | |
64 * Set INDENT_LISTING to non-zero if the inserted text should be shifted | |
65 * over by two spaces. | |
66 */ | |
771 | 67 #define INDENT_LISTING 0 |
428 | 68 |
771 | 69 #define ROUND_FILE_SIZES 4096 |
428 | 70 |
71 | |
72 #include <config.h> | |
73 #include "lisp.h" | |
74 | |
75 #include "buffer.h" | |
76 #include "regex.h" | |
826 | 77 #include "syntax.h" |
428 | 78 |
872 | 79 #include "console-msw.h" |
80 | |
428 | 81 #include "sysdir.h" |
442 | 82 #include "sysfile.h" |
558 | 83 #include "sysfloat.h" |
771 | 84 #include "sysproc.h" |
85 #include "syspwd.h" | |
86 #include "systime.h" | |
872 | 87 |
428 | 88 |
89 static int mswindows_ls_sort_case_insensitive; | |
458 | 90 static Fixnum mswindows_ls_round_file_size; |
428 | 91 |
771 | 92 Lisp_Object Qmswindows_insert_directory; |
93 Lisp_Object Qwildcard_to_regexp; | |
428 | 94 |
771 | 95 extern Lisp_Object Vmswindows_downcase_file_names; /* in device-msw.c */ |
428 | 96 |
558 | 97 enum mswindows_sortby |
98 { | |
428 | 99 MSWINDOWS_SORT_BY_NAME, |
100 MSWINDOWS_SORT_BY_NAME_NOCASE, | |
101 MSWINDOWS_SORT_BY_MOD_DATE, | |
102 MSWINDOWS_SORT_BY_SIZE | |
103 }; | |
104 | |
105 | |
771 | 106 static enum mswindows_sortby mswindows_sort_method; |
107 static int mswindows_reverse_sort; | |
108 | |
109 /* We create our own structure because the cFileName field in | |
110 WIN32_FIND_DATA is in external format and of fixed size, which we | |
111 may exceed when translating. */ | |
112 | |
113 typedef struct | |
114 { | |
115 DWORD dwFileAttributes; | |
116 FILETIME ftCreationTime; | |
117 FILETIME ftLastAccessTime; | |
118 FILETIME ftLastWriteTime; | |
119 DWORD nFileSizeHigh; | |
120 DWORD nFileSizeLow; | |
867 | 121 Ibyte *cFileName; |
771 | 122 } Win32_file; |
123 | |
124 typedef struct | |
125 { | |
126 Dynarr_declare (Win32_file); | |
127 } Win32_file_dynarr; | |
128 | |
428 | 129 |
130 | |
131 #define CMPDWORDS(t1a, t1b, t2a, t2b) \ | |
132 (((t1a) == (t2a)) ? (((t1b) == (t2b)) ? 0 : (((t1b) < (t2b)) ? -1 : 1)) \ | |
133 : (((t1a) < (t2a)) ? -1 : 1)) | |
134 | |
135 | |
136 static int | |
137 mswindows_ls_sort_fcn (const void *elem1, const void *elem2) | |
138 { | |
771 | 139 Win32_file *e1, *e2; |
140 int status; | |
428 | 141 |
771 | 142 e1 = (Win32_file *) elem1; |
143 e2 = (Win32_file *) elem2; | |
144 | |
428 | 145 switch (mswindows_sort_method) |
146 { | |
147 case MSWINDOWS_SORT_BY_NAME: | |
1204 | 148 status = qxestrcmp (e1->cFileName, e2->cFileName); |
428 | 149 break; |
150 case MSWINDOWS_SORT_BY_NAME_NOCASE: | |
771 | 151 status = qxestrcasecmp (e1->cFileName, e2->cFileName); |
428 | 152 break; |
153 case MSWINDOWS_SORT_BY_MOD_DATE: | |
771 | 154 status = CMPDWORDS (e1->ftLastWriteTime.dwHighDateTime, |
155 e1->ftLastWriteTime.dwLowDateTime, | |
156 e2->ftLastWriteTime.dwHighDateTime, | |
157 e2->ftLastWriteTime.dwLowDateTime); | |
428 | 158 break; |
159 case MSWINDOWS_SORT_BY_SIZE: | |
771 | 160 status = CMPDWORDS (e1->nFileSizeHigh, e1->nFileSizeLow, |
161 e2->nFileSizeHigh, e2->nFileSizeLow); | |
428 | 162 break; |
163 default: | |
164 status = 0; | |
165 break; | |
166 } | |
167 if (mswindows_reverse_sort) | |
168 { | |
169 status = -status; | |
170 } | |
171 return (status); | |
172 } | |
173 | |
174 static void | |
771 | 175 mswindows_sort_files (Win32_file_dynarr *files, |
428 | 176 enum mswindows_sortby sort_by, int reverse) |
177 { | |
178 mswindows_sort_method = sort_by; | |
179 mswindows_reverse_sort = reverse; | |
4967 | 180 qsort (Dynarr_begin (files), Dynarr_length (files), |
771 | 181 sizeof (Win32_file), mswindows_ls_sort_fcn); |
428 | 182 } |
183 | |
771 | 184 static Win32_file_dynarr * |
185 mswindows_get_files (Lisp_Object dirfile, int nowild, Lisp_Object pattern, | |
186 int hide_dot, int hide_system) | |
428 | 187 { |
771 | 188 Win32_file_dynarr *files = Dynarr_new (Win32_file); |
189 struct re_pattern_buffer *bufp = NULL; | |
190 int findex; | |
191 DECLARE_EISTRING (win32pattern); | |
192 HANDLE fh; | |
2526 | 193 int errm; |
428 | 194 |
195 while (1) | |
196 { | |
771 | 197 if (!NILP (pattern)) |
428 | 198 { |
199 /* PATTERN might be a flawed regular expression. Rather than | |
200 catching and signalling our own errors, we just call | |
201 compile_pattern to do the work for us. */ | |
826 | 202 bufp = compile_pattern (pattern, 0, Qnil, Qnil, 0, 0, ERROR_ME); |
428 | 203 } |
204 /* Now *bufp is the compiled form of PATTERN; don't call anything | |
205 which might compile a new regexp until we're done with the loop! */ | |
206 | |
2526 | 207 { |
208 Ibyte *dir2; | |
209 LISP_PATHNAME_RESOLVE_LINKS (dirfile, dir2); | |
210 eicpy_rawz (win32pattern, dir2); | |
211 } | |
212 | |
428 | 213 /* for Win32, we need to insure that the pathname ends with "\*". */ |
214 if (!nowild) | |
215 { | |
771 | 216 Charcount len = eicharlen (win32pattern) - 1; |
217 if (!IS_DIRECTORY_SEP (eigetch_char (win32pattern, len))) | |
2421 | 218 eicat_ascii (win32pattern, "\\"); |
219 eicat_ascii (win32pattern, "*"); | |
428 | 220 } |
771 | 221 eito_external (win32pattern, Qmswindows_tstr); |
428 | 222 |
223 /* | |
224 * Here, we use FindFirstFile()/FindNextFile() instead of opendir(), | |
771 | 225 * qxe_stat(), & friends, because qxe_stat() is VERY expensive in |
442 | 226 * terms of time. Hence, we take the time to write complicated |
227 * Win32-specific code, instead of simple Unix-style stuff. | |
428 | 228 */ |
229 findex = 0; | |
230 fh = INVALID_HANDLE_VALUE; | |
819 | 231 errm = SetErrorMode (SEM_FAILCRITICALERRORS |
232 | SEM_NOOPENFILEERRORBOX); | |
428 | 233 |
234 while (1) | |
235 { | |
771 | 236 Bytecount len; |
237 DECLARE_EISTRING (filename); | |
238 int result; | |
239 WIN32_FIND_DATAW finddat; | |
240 Win32_file file; | |
826 | 241 struct syntax_cache scache_struct; |
242 struct syntax_cache *scache = &scache_struct; | |
428 | 243 |
244 if (fh == INVALID_HANDLE_VALUE) | |
245 { | |
771 | 246 fh = qxeFindFirstFile (eiextdata (win32pattern), &finddat); |
428 | 247 if (fh == INVALID_HANDLE_VALUE) |
819 | 248 { |
249 SetErrorMode (errm); | |
250 report_file_error ("Opening directory", dirfile); | |
251 } | |
428 | 252 } |
253 else | |
254 { | |
771 | 255 if (! qxeFindNextFile (fh, &finddat)) |
428 | 256 { |
819 | 257 if (GetLastError() == ERROR_NO_MORE_FILES) |
258 { | |
259 break; | |
260 } | |
261 FindClose(fh); | |
262 SetErrorMode (errm); | |
771 | 263 report_file_error ("Reading directory", dirfile); |
428 | 264 } |
265 } | |
266 | |
771 | 267 file.dwFileAttributes = finddat.dwFileAttributes; |
268 file.ftCreationTime = finddat.ftCreationTime; | |
269 file.ftLastAccessTime = finddat.ftLastAccessTime; | |
270 file.ftLastWriteTime = finddat.ftLastWriteTime; | |
271 file.nFileSizeHigh = finddat.nFileSizeHigh; | |
272 file.nFileSizeLow = finddat.nFileSizeLow; | |
273 eicpy_ext (filename, (Extbyte *) finddat.cFileName, | |
274 Qmswindows_tstr); | |
275 | |
276 if (!NILP (Vmswindows_downcase_file_names)) | |
277 eilwr (filename); | |
278 len = eilen (filename); | |
279 result = (NILP (pattern) | |
1204 | 280 || (0 <= re_search (bufp, (char *) eidata (filename), |
826 | 281 len, 0, len, 0, Qnil, 0, scache))); |
428 | 282 if (result) |
283 { | |
771 | 284 if ( ! (eigetch_char (filename, 0) == '.' && |
285 ((hide_system && | |
286 (eigetch_char (filename, 1) == '\0' || | |
287 (eigetch_char (filename, 1) == '.' && | |
288 eigetch_char (filename, 2) == '\0'))) || | |
428 | 289 hide_dot))) |
290 { | |
2367 | 291 file.cFileName = xnew_ibytes (len + ITEXT_ZTERM_SIZE); |
771 | 292 memcpy (file.cFileName, eidata (filename), len); |
293 file.cFileName[len] = '\0'; | |
294 Dynarr_add (files, file); | |
428 | 295 } |
296 } | |
297 } | |
298 if (fh != INVALID_HANDLE_VALUE) | |
771 | 299 FindClose (fh); |
428 | 300 break; |
301 } | |
819 | 302 |
303 SetErrorMode (errm); | |
428 | 304 return (files); |
305 } | |
306 | |
771 | 307 static Lisp_Object |
308 mswindows_format_file (Win32_file *file, int display_size, int add_newline) | |
428 | 309 { |
771 | 310 Lisp_Object luser; |
311 double file_size; | |
312 DECLARE_EISTRING (puta); | |
867 | 313 CIbyte buf[666]; |
428 | 314 |
315 file_size = | |
316 file->nFileSizeHigh * (double)UINT_MAX + file->nFileSizeLow; | |
317 #if INDENT_LISTING | |
2421 | 318 eicat_ascii (puta, " "); |
428 | 319 #endif |
320 if (display_size) | |
321 { | |
771 | 322 sprintf (buf, "%6d ", (int)((file_size + 1023.) / 1024.)); |
2421 | 323 eicat_ascii (puta, buf); |
428 | 324 } |
325 if (file->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | |
2421 | 326 eicat_ascii (puta, "d"); |
771 | 327 else |
2421 | 328 eicat_ascii (puta, "-"); |
771 | 329 buf[0] = buf[3] = buf[6] = 'r'; |
428 | 330 if (file->dwFileAttributes & FILE_ATTRIBUTE_READONLY) |
771 | 331 buf[1] = buf[4] = buf[7] = '-'; |
332 else | |
333 buf[1] = buf[4] = buf[7] = 'w'; | |
334 { | |
335 int is_executable = 0; | |
428 | 336 |
771 | 337 if (file->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
338 is_executable = 1; | |
339 else if (qxestrcharlen (file->cFileName) > 4) | |
340 { | |
867 | 341 Ibyte *end = file->cFileName + qxestrlen (file->cFileName); |
342 DEC_IBYTEPTR (end); | |
343 DEC_IBYTEPTR (end); | |
344 DEC_IBYTEPTR (end); | |
345 DEC_IBYTEPTR (end); | |
2367 | 346 if (qxestrcasecmp_ascii (end, ".exe") == 0 |
347 || qxestrcasecmp_ascii (end, ".com") == 0 | |
348 || qxestrcasecmp_ascii (end, ".bat") == 0 | |
428 | 349 #if 0 |
2367 | 350 || qxestrcasecmp_ascii (end, ".pif") == 0 |
428 | 351 #endif |
771 | 352 ) |
353 is_executable = 1; | |
428 | 354 } |
771 | 355 if (is_executable) |
356 buf[2] = buf[5] = buf[8] = 'x'; | |
357 else | |
358 buf[2] = buf[5] = buf[8] = '-'; | |
428 | 359 } |
771 | 360 buf[9] = '\0'; |
2421 | 361 eicat_ascii (puta, buf); |
771 | 362 if (file->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
2421 | 363 eicat_ascii (puta, " 2 "); |
771 | 364 else |
2421 | 365 eicat_ascii (puta, " 1 "); |
771 | 366 luser = Fuser_login_name (Qnil); |
367 if (!STRINGP (luser)) | |
368 sprintf (buf, "%-9d", 0); | |
428 | 369 else |
370 { | |
867 | 371 Ibyte *str; |
771 | 372 |
373 str = XSTRING_DATA (luser); | |
374 sprintf (buf, "%-8s ", str); | |
428 | 375 } |
867 | 376 eicat_raw (puta, (Ibyte *) buf, strlen (buf)); |
771 | 377 { |
867 | 378 CIbyte *cptr = buf; |
771 | 379 sprintf (buf, "%-8d ", getgid ()); |
380 cptr += 9; | |
381 if (file_size > 99999999.0) | |
382 { | |
383 file_size = (file_size + 1023.0) / 1024.; | |
384 if (file_size > 999999.0) | |
385 sprintf (cptr, "%6.0fMB ", (file_size + 1023.0) / 1024.); | |
386 else | |
387 sprintf (cptr, "%6.0fKB ", file_size); | |
388 } | |
389 else | |
390 sprintf (cptr, "%8.0f ", file_size); | |
391 while (*cptr) | |
392 ++cptr; | |
393 { | |
394 time_t t, now; | |
867 | 395 Ibyte *ctimebuf; |
771 | 396 |
397 if ( | |
398 #if 0 | |
399 /* | |
400 * This doesn't work. | |
401 * This code should be correct ... | |
402 */ | |
403 FileTimeToLocalFileTime (&file->ftLastWriteTime, &localtime) && | |
404 ((t = mswindows_convert_time (localtime)) != 0) && | |
405 #else | |
406 /* | |
407 * But this code "works" ... | |
408 */ | |
409 ((t = mswindows_convert_time (file->ftLastWriteTime)) != 0) && | |
410 #endif | |
411 ((ctimebuf = qxe_ctime (&t)) != NULL)) | |
412 { | |
413 memcpy (cptr, &ctimebuf[4], 7); | |
414 now = time (NULL); | |
415 if (now - t > (365. / 2.0) * 86400.) | |
416 { | |
417 /* more than 6 months */ | |
418 cptr[7] = ' '; | |
419 memcpy (&cptr[8], &ctimebuf[20], 4); | |
420 } | |
421 else | |
422 { | |
423 /* less than 6 months */ | |
424 memcpy (&cptr[7], &ctimebuf[11], 5); | |
425 } | |
426 cptr += 12; | |
427 *cptr++ = ' '; | |
428 *cptr++ = '\0'; | |
429 } | |
430 } | |
431 } | |
432 | |
2421 | 433 eicat_ascii (puta, buf); |
771 | 434 eicat_raw (puta, file->cFileName, qxestrlen (file->cFileName)); |
435 if (add_newline) | |
2421 | 436 eicat_ascii (puta, "\n"); |
771 | 437 |
438 return eimake_string (puta); | |
428 | 439 } |
440 | |
441 | |
442 DEFUN ("mswindows-insert-directory", Fmswindows_insert_directory, 2, 4, 0, /* | |
443 Insert directory listing for FILE, formatted according to SWITCHES. | |
444 Leaves point after the inserted text. | |
445 SWITCHES may be a string of options, or a list of strings. | |
446 Optional third arg WILDCARD means treat FILE as shell wildcard. | |
447 Optional fourth arg FULL-DIRECTORY-P means file is a directory and | |
448 switches do not contain `d', so that a full listing is expected. | |
449 */ | |
450 (file, switches, wildcard, full_directory_p)) | |
451 { | |
771 | 452 Lisp_Object handler, wildpat = Qnil, basename = Qnil; |
453 int nfiles = 0, i; | |
454 int hide_system = 1, hide_dot = 1, reverse = 0, display_size = 0; | |
455 Win32_file_dynarr *files; | |
456 enum mswindows_sortby sort_by = | |
457 (mswindows_ls_sort_case_insensitive ? MSWINDOWS_SORT_BY_NAME_NOCASE | |
458 : MSWINDOWS_SORT_BY_NAME); | |
459 struct gcpro gcpro1, gcpro2, gcpro3; | |
460 | |
461 GCPRO3 (file, wildpat, basename); | |
462 | |
463 CHECK_STRING (file); | |
464 if (!NILP (wildpat)) | |
465 CHECK_STRING (wildpat); | |
428 | 466 |
771 | 467 handler = Ffind_file_name_handler (file, Qmswindows_insert_directory); |
468 if (!NILP (handler)) | |
469 { | |
470 UNGCPRO; | |
471 return call5 (handler, Qmswindows_insert_directory, file, switches, | |
472 wildcard, full_directory_p); | |
473 } | |
474 | |
475 if (!NILP (switches)) | |
428 | 476 { |
867 | 477 Ibyte *cptr, *cptr_end; |
771 | 478 |
479 CHECK_STRING (switches); | |
480 cptr = XSTRING_DATA (switches); | |
481 cptr_end = cptr + XSTRING_LENGTH (switches); | |
482 while (cptr < cptr_end) | |
428 | 483 { |
867 | 484 Ichar ch = itext_ichar (cptr); |
771 | 485 switch (ch) |
428 | 486 { |
771 | 487 case 'A': |
488 hide_dot = 0; | |
489 break; | |
490 case 'a': | |
491 hide_system = 0; | |
492 hide_dot = 0; | |
493 break; | |
494 case 'r': | |
495 reverse = 1; | |
496 break; | |
497 case 's': | |
498 display_size = 1; | |
499 break; | |
500 case 'S': | |
501 sort_by = MSWINDOWS_SORT_BY_SIZE; | |
502 break; | |
503 case 't': | |
504 sort_by = MSWINDOWS_SORT_BY_MOD_DATE; | |
428 | 505 break; |
506 } | |
867 | 507 INC_IBYTEPTR (cptr); |
428 | 508 } |
771 | 509 } |
510 | |
511 if (!NILP (wildcard)) | |
512 { | |
513 Lisp_Object newfile; | |
514 | |
515 file = Fdirectory_file_name (file); | |
516 basename = Ffile_name_nondirectory (file); | |
517 wildpat = call1 (Qwildcard_to_regexp, basename); | |
518 newfile = Ffile_name_directory (file); | |
519 if (NILP (newfile)) | |
520 newfile = Ffile_name_directory (Fexpand_file_name (file, Qnil)); | |
521 file = newfile; | |
522 } | |
523 | |
524 files = mswindows_get_files (file, | |
525 NILP (wildcard) && NILP (full_directory_p), | |
526 wildpat, hide_dot, hide_system); | |
527 | |
528 if (Dynarr_length (files) > 1) | |
529 mswindows_sort_files (files, sort_by, reverse); | |
530 if (!NILP (wildcard) || !NILP (full_directory_p)) | |
531 { | |
532 /* | |
533 * By using doubles, we can handle files up to 2^53 bytes in | |
534 * size (IEEE doubles have 53 bits of resolution). However, | |
535 * as we divide by 1024 (or 2^10), the total size is | |
536 * accurate up to 2^(53+10) --> 2^63 bytes. | |
537 * | |
538 * Hopefully, we won't have to handle these file sizes anytime | |
539 * soon. | |
540 */ | |
541 double total_size, file_size, block_size; | |
428 | 542 |
771 | 543 if ((block_size = mswindows_ls_round_file_size) <= 0) |
544 { | |
545 block_size = 0; | |
546 } | |
547 total_size = 0; | |
548 for (i = 0; i < Dynarr_length (files); ++i) | |
549 { | |
550 Win32_file *file = Dynarr_atp (files, i); | |
551 file_size = | |
552 file->nFileSizeHigh * (double)UINT_MAX + | |
553 file->nFileSizeLow; | |
554 if (block_size > 0) | |
428 | 555 { |
771 | 556 /* |
557 * Round file_size up to the next nearest block size. | |
558 */ | |
428 | 559 file_size = |
771 | 560 floor ((file_size + block_size - 1) / block_size) |
561 * block_size; | |
428 | 562 } |
771 | 563 /* Here, we round to the nearest 1K */ |
564 total_size += floor ((file_size + 512.) / 1024.); | |
428 | 565 } |
771 | 566 { |
800 | 567 write_fmt_string (wrap_buffer (current_buffer), |
771 | 568 #if INDENT_LISTING |
800 | 569 /* ANSI C compilers auto-concatenate adjacent |
570 strings */ | |
571 " " | |
771 | 572 #endif |
800 | 573 "total %.0f\n", total_size); |
771 | 574 } |
428 | 575 } |
771 | 576 for (i = 0; i < Dynarr_length (files); ++i) |
428 | 577 { |
771 | 578 struct gcpro ngcpro1; |
579 Lisp_Object fmtfile = | |
580 mswindows_format_file (Dynarr_atp (files, i), display_size, TRUE); | |
581 NGCPRO1 (fmtfile); | |
582 buffer_insert1 (current_buffer, fmtfile); | |
583 NUNGCPRO; | |
428 | 584 } |
771 | 585 for (i = 0; i < Dynarr_length (files); ++i) |
586 { | |
587 Win32_file *file = Dynarr_atp (files, i); | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
588 xfree (file->cFileName); |
771 | 589 } |
590 Dynarr_free (files); | |
591 | |
428 | 592 UNGCPRO; |
771 | 593 return Qnil; |
428 | 594 } |
595 | |
596 | |
597 | |
598 /************************************************************************/ | |
599 /* initialization */ | |
600 /************************************************************************/ | |
601 | |
602 void | |
603 syms_of_dired_mswindows (void) | |
604 { | |
563 | 605 DEFSYMBOL (Qmswindows_insert_directory); |
771 | 606 DEFSYMBOL (Qwildcard_to_regexp); |
428 | 607 |
608 DEFSUBR (Fmswindows_insert_directory); | |
609 } | |
610 | |
611 | |
612 void | |
613 vars_of_dired_mswindows (void) | |
614 { | |
771 | 615 DEFVAR_BOOL ("mswindows-ls-sort-case-insensitive", |
616 &mswindows_ls_sort_case_insensitive /* | |
428 | 617 *Non-nil means filenames are sorted in a case-insensitive fashion. |
618 Nil means filenames are sorted in a case-sensitive fashion, just like Unix. | |
619 */ ); | |
620 mswindows_ls_sort_case_insensitive = 1; | |
621 | |
622 DEFVAR_INT ("mswindows-ls-round-file-size", &mswindows_ls_round_file_size /* | |
623 *If non-zero, file sizes are rounded in terms of this block size when | |
624 the file totals are being calculated. This is useful for getting a more | |
625 accurate estimate of allocated disk space. Note that this only affects | |
626 the total size calculation; the individual displayed file sizes are not | |
627 changed. This block size should also be a power of 2 (but this is not | |
628 enforced), as filesystem block (cluster) sizes are typically powers-of-2. | |
629 */ ); | |
630 /* | |
631 * Here, we choose 4096 because it's the cluster size for both FAT32 | |
632 * and NTFS (?). This is probably much too small for people using | |
633 * plain FAT, but, hopefully, plain FAT will go away someday. | |
634 * | |
635 * We should allow something like a alist here, to make the size | |
636 * dependent on the drive letter, etc.. | |
637 */ | |
638 mswindows_ls_round_file_size = 4096; | |
639 } |