Subversion Repositories SvarDOS

Rev

Rev 1721 | Rev 1725 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1721 Rev 1724
Line 192... Line 192...
192
} glob_sortcmp_dat;
192
} glob_sortcmp_dat;
193
 
193
 
194
 
194
 
195
/* translates an order string like "GNE-S" into values fed into the order[]
195
/* translates an order string like "GNE-S" into values fed into the order[]
196
 * table of glob_sortcmp_dat. returns 0 on success, non-zero otherwise. */
196
 * table of glob_sortcmp_dat. returns 0 on success, non-zero otherwise. */
197
static int process_order_directive(const char *ordstring) {
197
static int dir_process_order_directive(const char *ordstring) {
198
  const char *gnesd = "gnesd"; /* must be lower case */
198
  const char *gnesd = "gnesd"; /* must be lower case */
199
  int ordi, orderi = 0, i;
199
  int ordi, orderi = 0, i;
200
 
200
 
201
  /* tabula rasa */
201
  /* tabula rasa */
202
  glob_sortcmp_dat.order[0] = 0;
202
  glob_sortcmp_dat.order[0] = 0;
Line 311... Line 311...
311
}
311
}
312
 
312
 
313
 
313
 
314
#define DIR_ATTR_DEFAULT (DOS_ATTR_RO | DOS_ATTR_DIR | DOS_ATTR_ARC)
314
#define DIR_ATTR_DEFAULT (DOS_ATTR_RO | DOS_ATTR_DIR | DOS_ATTR_ARC)
315
 
315
 
316
static enum cmd_result cmd_dir(struct cmd_funcparam *p) {
-
 
317
  const char *filespecptr = NULL;
-
 
318
  struct DTA *dta = (void *)0x80; /* set DTA to its default location at 80h in PSP */
-
 
319
  struct TINYDTA far *dtabuf = NULL; /* used to buffer results when sorting is enabled */
-
 
320
  unsigned short dtabufcount = 0;
-
 
321
  unsigned short i;
-
 
322
  unsigned short availrows;  /* counter of available rows on display (used for /P) */
-
 
323
  unsigned short screenw = screen_getwidth();
-
 
324
  unsigned short wcols = screenw / WCOLWIDTH; /* number of columns in wide mode */
-
 
325
  unsigned char wcolcount;
-
 
326
  struct {
-
 
327
    struct nls_patterns nls;
316
struct dirrequest {
328
    char buff64[64];
-
 
329
    char path[128];
-
 
330
    unsigned short orderidx[65535 / sizeof(struct TINYDTA)];
-
 
331
  } *buf = (void *)(p->BUFFER);
-
 
332
  unsigned long summary_fcount = 0;
-
 
333
  unsigned long summary_totsz = 0;
-
 
334
  unsigned char drv = 0;
317
  unsigned char attrfilter_may;
335
  unsigned char attrfilter_may = DIR_ATTR_DEFAULT;
318
  unsigned char attrfilter_must;
336
  unsigned char attrfilter_must = 0;
319
  const char *filespecptr;
337
 
320
 
338
  #define DIR_FLAG_PAUSE  1
321
  #define DIR_FLAG_PAUSE  1
339
  #define DIR_FLAG_RECUR  4
322
  #define DIR_FLAG_RECUR  4
340
  #define DIR_FLAG_LCASE  8
323
  #define DIR_FLAG_LCASE  8
341
  #define DIR_FLAG_SORT  16
324
  #define DIR_FLAG_SORT  16
342
  unsigned char flags = 0;
325
  unsigned char flags;
343
 
326
 
344
  #define DIR_OUTPUT_NORM 1
327
  #define DIR_OUTPUT_NORM 1
345
  #define DIR_OUTPUT_WIDE 2
328
  #define DIR_OUTPUT_WIDE 2
346
  #define DIR_OUTPUT_BARE 3
329
  #define DIR_OUTPUT_BARE 3
347
  unsigned char format = DIR_OUTPUT_NORM;
330
  unsigned char format;
348
 
-
 
349
  /* make sure there's no risk of buffer overflow */
-
 
350
  if (sizeof(buf) > p->BUFFERSZ) {
-
 
351
    outputnl("INTERNAL MEM ERROR IN " __FILE__);
-
 
352
    return(CMD_FAIL);
-
 
353
  }
-
 
354
 
-
 
355
  bzero(&glob_sortcmp_dat, sizeof(glob_sortcmp_dat));
-
 
356
 
-
 
357
  if (cmd_ishlp(p)) {
-
 
358
    nls_outputnl(37,0); /* "Displays a list of files and subdirectories in a directory" */
-
 
359
    outputnl("");
-
 
360
    nls_outputnl(37,1); /* "DIR [drive:][path][filename] [/P] [/W] [/A[:]attributes] [/O[[:]sortorder]] [/S] [/B] [/L]" */
-
 
361
    outputnl("");
-
 
362
    nls_outputnl(37,2); /* "/P Pauses after each screenful of information" */
-
 
363
    nls_outputnl(37,3); /* "/W Uses wide list format" */
-
 
364
    outputnl("");
-
 
365
    nls_outputnl(37,4); /* "/A Displays files with specified attributes:" */
-
 
366
    nls_outputnl(37,5); /* "    D Directories            R Read-only files        H Hidden files" */
-
 
367
    nls_outputnl(37,6); /* "    A Ready for archiving    S System files           - prefix meaning "not"" */
-
 
368
    outputnl("");
-
 
369
    nls_outputnl(37,7); /* "/O List files in sorted order:" */
-
 
370
    nls_outputnl(37,8); /* "    N by name                S by size                E by extension" */
-
 
371
    nls_outputnl(37,9); /* "    D by date                G group dirs first       - prefix to reverse order" */
-
 
372
    outputnl("");
-
 
373
    nls_outputnl(37,10); /* "/S Displays files in specified directory and all subdirectories" */
-
 
374
    nls_outputnl(37,11); /* "/B Uses bare format (no heading information or summary)" */
-
 
375
    nls_outputnl(37,12); /* "/L Uses lowercases" */
-
 
376
    return(CMD_OK);
-
 
377
  }
-
 
378
 
331
};
379
  i = nls_getpatterns(&(buf->nls));
-
 
380
  if (i != 0) nls_outputnl_doserr(i);
-
 
381
 
332
 
382
  /* disable usage of thousands separator on narrow screens */
-
 
383
  if (screenw < 80) buf->nls.thousep[0] = 0;
-
 
384
 
333
 
385
  /* parse command line */
334
static int dir_parse_cmdline(struct dirrequest *req, const char **argv) {
386
  for (i = 0; i < p->argc; i++) {
335
  for (; *argv != NULL; argv++) {
387
    if (p->argv[i][0] == '/') {
336
    if (*argv[0] == '/') {
388
      const char *arg = p->argv[i] + 1;
337
      const char *arg = *argv + 1;
389
      char neg = 0;
338
      char neg = 0;
390
      /* detect negations and get actual argument */
339
      /* detect negations and get actual argument */
391
      if (*arg == '-') {
340
      if (*arg == '-') {
392
        neg = 1;
341
        neg = 1;
393
        arg++;
342
        arg++;
Line 396... Line 345...
396
      switch (*arg) {
345
      switch (*arg) {
397
        case 'a':
346
        case 'a':
398
        case 'A':
347
        case 'A':
399
          arg++;
348
          arg++;
400
          /* preset defaults */
349
          /* preset defaults */
401
          attrfilter_may = DIR_ATTR_DEFAULT;
350
          req->attrfilter_may = DIR_ATTR_DEFAULT;
402
          attrfilter_must = 0;
351
          req->attrfilter_must = 0;
403
          /* /-A only allowed without further parameters (used to cancel possible previous /Asmth) */
352
          /* /-A only allowed without further parameters (used to cancel possible previous /Asmth) */
404
          if (neg) {
353
          if (neg) {
405
            if (*arg != 0) {
354
            if (*arg != 0) {
406
              nls_outputnl_err(0, 2); /* invalid switch */
355
              nls_outputnl_err(0, 2); /* invalid switch */
407
              return(CMD_FAIL);
356
              return(-1);
408
            }
357
            }
409
          } else {
358
          } else {
410
            /* skip colon if present */
359
            /* skip colon if present */
411
            if (*arg == ':') arg++;
360
            if (*arg == ':') arg++;
412
            /* start with "allow everything" */
361
            /* start with "allow everything" */
413
            attrfilter_may = (DOS_ATTR_ARC | DOS_ATTR_DIR | DOS_ATTR_HID | DOS_ATTR_SYS | DOS_ATTR_RO);
362
            req->attrfilter_may = (DOS_ATTR_ARC | DOS_ATTR_DIR | DOS_ATTR_HID | DOS_ATTR_SYS | DOS_ATTR_RO);
414
            if (dir_parse_attr_list(arg, &attrfilter_may, &attrfilter_must) != 0) {
363
            if (dir_parse_attr_list(arg, &(req->attrfilter_may), &(req->attrfilter_must)) != 0) {
415
              nls_outputnl_err(0, 3); /* invalid parameter format */
364
              nls_outputnl_err(0, 3); /* invalid parameter format */
416
              return(CMD_FAIL);
365
              return(-1);
417
            }
366
            }
418
          }
367
          }
419
          break;
368
          break;
420
        case 'b':
369
        case 'b':
421
        case 'B':
370
        case 'B':
422
          format = DIR_OUTPUT_BARE;
371
          req->format = DIR_OUTPUT_BARE;
423
          break;
372
          break;
424
        case 'l':
373
        case 'l':
425
        case 'L':
374
        case 'L':
426
          flags |= DIR_FLAG_LCASE;
375
          req->flags |= DIR_FLAG_LCASE;
427
          break;
376
          break;
428
        case 'o':
377
        case 'o':
429
        case 'O':
378
        case 'O':
430
          if (neg) {
379
          if (neg) {
431
            flags &= (0xff ^ DIR_FLAG_SORT);
380
            req->flags &= (0xff ^ DIR_FLAG_SORT);
432
            break;
381
            break;
433
          }
382
          }
434
          if (process_order_directive(arg+1) != 0) {
383
          if (dir_process_order_directive(arg+1) != 0) {
435
            nls_output_err(0, 3); /* invalid parameter format */
384
            nls_output_err(0, 3); /* invalid parameter format */
436
            output(": ");
385
            output(": ");
437
            outputnl(arg);
386
            outputnl(arg);
438
            return(CMD_FAIL);
387
            return(-1);
439
          }
388
          }
440
          flags |= DIR_FLAG_SORT;
389
          req->flags |= DIR_FLAG_SORT;
441
          break;
390
          break;
442
        case 'p':
391
        case 'p':
443
        case 'P':
392
        case 'P':
444
          flags |= DIR_FLAG_PAUSE;
393
          req->flags |= DIR_FLAG_PAUSE;
445
          if (neg) flags &= (0xff ^ DIR_FLAG_PAUSE);
394
          if (neg) req->flags &= (0xff ^ DIR_FLAG_PAUSE);
446
          break;
395
          break;
447
        case 's':
396
        case 's':
448
        case 'S':
397
        case 'S':
449
          /* TODO */
398
          /* TODO */
450
          outputnl("/S NOT IMPLEMENTED YET");
399
          outputnl("/S NOT IMPLEMENTED YET");
451
          return(CMD_FAIL);
400
          return(-1);
452
          break;
401
          break;
453
        case 'w':
402
        case 'w':
454
        case 'W':
403
        case 'W':
455
          format = DIR_OUTPUT_WIDE;
404
          req->format = DIR_OUTPUT_WIDE;
456
          break;
405
          break;
457
        default:
406
        default:
458
          nls_outputnl_err(0, 2); /* invalid switch */
407
          nls_outputnl_err(0, 2); /* invalid switch */
459
          return(CMD_FAIL);
408
          return(-1);
460
      }
409
      }
461
    } else {  /* filespec */
410
    } else {  /* filespec */
462
      if (filespecptr != NULL) {
411
      if (req->filespecptr != NULL) {
463
        nls_outputnl_err(0, 4); /* too many parameters */
412
        nls_outputnl_err(0, 4); /* too many parameters */
464
        return(CMD_FAIL);
413
        return(-1);
465
      }
414
      }
466
      filespecptr = p->argv[i];
415
      req->filespecptr = *argv;
467
    }
416
    }
468
  }
417
  }
469
 
418
 
470
  if (filespecptr == NULL) filespecptr = ".";
419
  if (req->filespecptr == NULL) req->filespecptr = ".";
-
 
420
  return(0);
-
 
421
}
-
 
422
 
-
 
423
 
-
 
424
static enum cmd_result cmd_dir(struct cmd_funcparam *p) {
-
 
425
  struct DTA *dta = (void *)0x80; /* set DTA to its default location at 80h in PSP */
-
 
426
  struct TINYDTA far *dtabuf = NULL; /* used to buffer results when sorting is enabled */
-
 
427
  unsigned short dtabufcount = 0;
-
 
428
  unsigned short i;
-
 
429
  unsigned short availrows;  /* counter of available rows on display (used for /P) */
-
 
430
  unsigned short screenw = screen_getwidth();
-
 
431
  unsigned short wcols = screenw / WCOLWIDTH; /* number of columns in wide mode */
-
 
432
  unsigned char wcolcount;
-
 
433
  struct {
-
 
434
    struct nls_patterns nls;
-
 
435
    char buff64[64];
-
 
436
    char path[128];
-
 
437
    unsigned short orderidx[65535 / sizeof(struct TINYDTA)];
-
 
438
  } *buf = (void *)(p->BUFFER);
-
 
439
  unsigned long summary_fcount = 0;
-
 
440
  unsigned long summary_totsz = 0;
-
 
441
  unsigned char drv = 0;
-
 
442
 
-
 
443
  struct dirrequest req;
-
 
444
 
-
 
445
  /* preload req with default values */
-
 
446
  bzero(&req, sizeof(req));
-
 
447
  req.attrfilter_may = DIR_ATTR_DEFAULT;
-
 
448
  /* req.attrfilter_must = 0;
-
 
449
  req.flags = 0; */
-
 
450
  req.format = DIR_OUTPUT_NORM;
-
 
451
 
-
 
452
  /* make sure there's no risk of buffer overflow */
-
 
453
  if (sizeof(buf) > p->BUFFERSZ) {
-
 
454
    outputnl("INTERNAL MEM ERROR IN " __FILE__);
-
 
455
    return(CMD_FAIL);
-
 
456
  }
-
 
457
 
-
 
458
  bzero(&glob_sortcmp_dat, sizeof(glob_sortcmp_dat));
-
 
459
 
-
 
460
  if (cmd_ishlp(p)) {
-
 
461
    nls_outputnl(37,0); /* "Displays a list of files and subdirectories in a directory" */
-
 
462
    outputnl("");
-
 
463
    nls_outputnl(37,1); /* "DIR [drive:][path][filename] [/P] [/W] [/A[:]attributes] [/O[[:]sortorder]] [/S] [/B] [/L]" */
-
 
464
    outputnl("");
-
 
465
    nls_outputnl(37,2); /* "/P Pauses after each screenful of information" */
-
 
466
    nls_outputnl(37,3); /* "/W Uses wide list format" */
-
 
467
    outputnl("");
-
 
468
    nls_outputnl(37,4); /* "/A Displays files with specified attributes:" */
-
 
469
    nls_outputnl(37,5); /* "    D Directories            R Read-only files        H Hidden files" */
-
 
470
    nls_outputnl(37,6); /* "    A Ready for archiving    S System files           - prefix meaning "not"" */
-
 
471
    outputnl("");
-
 
472
    nls_outputnl(37,7); /* "/O List files in sorted order:" */
-
 
473
    nls_outputnl(37,8); /* "    N by name                S by size                E by extension" */
-
 
474
    nls_outputnl(37,9); /* "    D by date                G group dirs first       - prefix to reverse order" */
-
 
475
    outputnl("");
-
 
476
    nls_outputnl(37,10); /* "/S Displays files in specified directory and all subdirectories" */
-
 
477
    nls_outputnl(37,11); /* "/B Uses bare format (no heading information or summary)" */
-
 
478
    nls_outputnl(37,12); /* "/L Uses lowercases" */
-
 
479
    return(CMD_OK);
-
 
480
  }
-
 
481
 
-
 
482
  i = nls_getpatterns(&(buf->nls));
-
 
483
  if (i != 0) nls_outputnl_doserr(i);
-
 
484
 
-
 
485
  /* disable usage of thousands separator on narrow screens */
-
 
486
  if (screenw < 80) buf->nls.thousep[0] = 0;
-
 
487
 
-
 
488
  /* parse command line */
-
 
489
  if (dir_parse_cmdline(&req, p->argv) != 0) return(CMD_FAIL);
471
 
490
 
472
  availrows = screen_getheight() - 2;
491
  availrows = screen_getheight() - 2;
473
 
492
 
474
  /* special case: "DIR drive:" (truename() fails on "C:" under MS-DOS 6.0) */
493
  /* special case: "DIR drive:" (truename() fails on "C:" under MS-DOS 6.0) */
475
  if ((filespecptr[0] != 0) && (filespecptr[1] == ':') && (filespecptr[2] == 0)) {
494
  if ((req.filespecptr[0] != 0) && (req.filespecptr[1] == ':') && (req.filespecptr[2] == 0)) {
476
    if ((filespecptr[0] >= 'a') && (filespecptr[0] <= 'z')) {
495
    if ((req.filespecptr[0] >= 'a') && (req.filespecptr[0] <= 'z')) {
477
      buf->path[0] = filespecptr[0] - ('a' - 1);
496
      buf->path[0] = req.filespecptr[0] - ('a' - 1);
478
    } else {
497
    } else {
479
      buf->path[0] = filespecptr[0] - ('A' - 1);
498
      buf->path[0] = req.filespecptr[0] - ('A' - 1);
480
    }
499
    }
481
    i = curpathfordrv(buf->path, buf->path[0]);
500
    i = curpathfordrv(buf->path, buf->path[0]);
482
  } else {
501
  } else {
483
    i = file_truename(filespecptr, buf->path);
502
    i = file_truename(req.filespecptr, buf->path);
484
  }
503
  }
485
  if (i != 0) {
504
  if (i != 0) {
486
    nls_outputnl_doserr(i);
505
    nls_outputnl_doserr(i);
487
    return(CMD_FAIL);
506
    return(CMD_FAIL);
488
  }
507
  }
489
 
508
 
490
  if (format != DIR_OUTPUT_BARE) {
509
  if (req.format != DIR_OUTPUT_BARE) {
491
    drv = buf->path[0];
510
    drv = buf->path[0];
492
    if (drv >= 'a') {
511
    if (drv >= 'a') {
493
      drv -= 'a';
512
      drv -= 'a';
494
    } else {
513
    } else {
495
      drv -= 'A';
514
      drv -= 'A';
Line 508... Line 527...
508
 
527
 
509
  /* if ends with a \ then append ????????.??? */
528
  /* if ends with a \ then append ????????.??? */
510
  if (buf->path[i - 1] == '\\') strcat(buf->path, "????????.???");
529
  if (buf->path[i - 1] == '\\') strcat(buf->path, "????????.???");
511
 
530
 
512
  /* ask DOS for list of files, but only with allowed attribs */
531
  /* ask DOS for list of files, but only with allowed attribs */
513
  i = findfirst(dta, buf->path, attrfilter_may);
532
  i = findfirst(dta, buf->path, req.attrfilter_may);
514
  if (i != 0) {
533
  if (i != 0) {
515
    nls_outputnl_doserr(i);
534
    nls_outputnl_doserr(i);
516
    return(CMD_FAIL);
535
    return(CMD_FAIL);
517
  }
536
  }
518
 
537
 
519
  /* if sorting is involved, then let's buffer all results (and sort them) */
538
  /* if sorting is involved, then let's buffer all results (and sort them) */
520
  if (flags & DIR_FLAG_SORT) {
539
  if (req.flags & DIR_FLAG_SORT) {
521
    /* allocate a memory buffer - try several sizes until one succeeds */
540
    /* allocate a memory buffer - try several sizes until one succeeds */
522
    const unsigned short memsz[] = {65500, 32000, 16000, 8000, 4000, 2000, 1000, 0};
541
    const unsigned short memsz[] = {65500, 32000, 16000, 8000, 4000, 2000, 1000, 0};
523
    unsigned short max_dta_bufcount = 0;
542
    unsigned short max_dta_bufcount = 0;
524
    for (i = 0; memsz[i] != 0; i++) {
543
    for (i = 0; memsz[i] != 0; i++) {
525
      dtabuf = _fmalloc(memsz[i]);
544
      dtabuf = _fmalloc(memsz[i]);
Line 538... Line 557...
538
    max_dta_bufcount = memsz[i] / sizeof(struct TINYDTA);
557
    max_dta_bufcount = memsz[i] / sizeof(struct TINYDTA);
539
    /* printf("max_dta_bufcount = %u\n", max_dta_bufcount); */
558
    /* printf("max_dta_bufcount = %u\n", max_dta_bufcount); */
540
 
559
 
541
    do {
560
    do {
542
      /* filter out files with uninteresting attributes */
561
      /* filter out files with uninteresting attributes */
543
      if (filter_attribs(dta, attrfilter_must, attrfilter_may) == 0) continue;
562
      if (filter_attribs(dta, req.attrfilter_must, req.attrfilter_may) == 0) continue;
544
 
563
 
545
      /* normalize "size" of directories to zero because kernel returns garbage
564
      /* normalize "size" of directories to zero because kernel returns garbage
546
       * sizes for directories which might confuse the sorting routine later */
565
       * sizes for directories which might confuse the sorting routine later */
547
      if (dta->attr & DOS_ATTR_DIR) dta->size = 0;
566
      if (dta->attr & DOS_ATTR_DIR) dta->size = 0;
548
 
567
 
Line 576... Line 595...
576
  wcolcount = 0; /* may be used for columns counting with wide mode */
595
  wcolcount = 0; /* may be used for columns counting with wide mode */
577
 
596
 
578
  for (;;) {
597
  for (;;) {
579
 
598
 
580
    /* filter out attributes (skip if entry comes from buffer, then it was already veted) */
599
    /* filter out attributes (skip if entry comes from buffer, then it was already veted) */
581
    if (filter_attribs(dta, attrfilter_must, attrfilter_may) == 0) continue;
600
    if (filter_attribs(dta, req.attrfilter_must, req.attrfilter_may) == 0) continue;
582
 
601
 
583
    /* turn string lcase (/L) */
602
    /* turn string lcase (/L) */
584
    if (flags & DIR_FLAG_LCASE) _strlwr(dta->fname); /* OpenWatcom extension, probably does not care about NLS so results may be odd with non-A-Z characters... */
603
    if (req.flags & DIR_FLAG_LCASE) _strlwr(dta->fname); /* OpenWatcom extension, probably does not care about NLS so results may be odd with non-A-Z characters... */
585
 
604
 
586
    summary_fcount++;
605
    summary_fcount++;
587
    if ((dta->attr & DOS_ATTR_DIR) == 0) summary_totsz += dta->size;
606
    if ((dta->attr & DOS_ATTR_DIR) == 0) summary_totsz += dta->size;
588
 
607
 
589
    switch (format) {
608
    switch (req.format) {
590
      case DIR_OUTPUT_NORM:
609
      case DIR_OUTPUT_NORM:
591
        /* print fname-space-extension (unless it's "." or "..", then print as-is) */
610
        /* print fname-space-extension (unless it's "." or "..", then print as-is) */
592
        if (dta->fname[0] == '.') {
611
        if (dta->fname[0] == '.') {
593
          output(dta->fname);
612
          output(dta->fname);
594
          i = strlen(dta->fname);
613
          i = strlen(dta->fname);
Line 645... Line 664...
645
      case DIR_OUTPUT_BARE:
664
      case DIR_OUTPUT_BARE:
646
        outputnl(dta->fname);
665
        outputnl(dta->fname);
647
        break;
666
        break;
648
    }
667
    }
649
 
668
 
650
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
669
    if (req.flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
651
 
670
 
652
    /* take next entry, either from buf or disk */
671
    /* take next entry, either from buf or disk */
653
    if (dtabufcount > 0) {
672
    if (dtabufcount > 0) {
654
      dtabufcount--;
673
      dtabufcount--;
655
      _fmemcpy(((unsigned char *)dta) + 22, &(dtabuf[buf->orderidx[dtabufcount]]), sizeof(struct TINYDTA));
674
      _fmemcpy(((unsigned char *)dta) + 22, &(dtabuf[buf->orderidx[dtabufcount]]), sizeof(struct TINYDTA));
Line 660... Line 679...
660
 
679
 
661
  }
680
  }
662
 
681
 
663
  if (wcolcount != 0) {
682
  if (wcolcount != 0) {
664
    outputnl(""); /* in wide mode make sure to end on a clear row */
683
    outputnl(""); /* in wide mode make sure to end on a clear row */
665
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
684
    if (req.flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
666
  }
685
  }
667
 
686
 
668
  /* print out summary (unless bare output mode) */
687
  /* print out summary (unless bare output mode) */
669
  if (format != DIR_OUTPUT_BARE) {
688
  if (req.format != DIR_OUTPUT_BARE) {
670
    unsigned short alignpos;
689
    unsigned short alignpos;
671
    unsigned char uint32maxlen = 13; /* 13 is the max len of a 32 bit number with thousand separators (4'000'000'000) */
690
    unsigned char uint32maxlen = 13; /* 13 is the max len of a 32 bit number with thousand separators (4'000'000'000) */
672
    if (screenw < 80) uint32maxlen = 10;
691
    if (screenw < 80) uint32maxlen = 10;
673
    /* x file(s) */
692
    /* x file(s) */
674
    memset(buf->buff64, ' ', uint32maxlen);
693
    memset(buf->buff64, ' ', uint32maxlen);
Line 678... Line 697...
678
    /* xxxx bytes */
697
    /* xxxx bytes */
679
    i = nls_format_number(buf->buff64 + uint32maxlen, summary_totsz, &(buf->nls));
698
    i = nls_format_number(buf->buff64 + uint32maxlen, summary_totsz, &(buf->nls));
680
    output(buf->buff64 + i + 1);
699
    output(buf->buff64 + i + 1);
681
    output(" ");
700
    output(" ");
682
    nls_outputnl(37,23); /* "bytes" */
701
    nls_outputnl(37,23); /* "bytes" */
683
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
702
    if (req.flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
684
    /* xxxx bytes free */
703
    /* xxxx bytes free */
685
    i = cmd_dir_df(&summary_totsz, drv);
704
    i = cmd_dir_df(&summary_totsz, drv);
686
    if (i != 0) nls_outputnl_doserr(i);
705
    if (i != 0) nls_outputnl_doserr(i);
687
    alignpos += uint32maxlen * 2;
706
    alignpos += uint32maxlen * 2;
688
    memset(buf->buff64, ' ', alignpos); /* align the freebytes value to same column as totbytes */
707
    memset(buf->buff64, ' ', alignpos); /* align the freebytes value to same column as totbytes */
689
    i = nls_format_number(buf->buff64 + alignpos, summary_totsz, &(buf->nls));
708
    i = nls_format_number(buf->buff64 + alignpos, summary_totsz, &(buf->nls));
690
    output(buf->buff64 + i + 1);
709
    output(buf->buff64 + i + 1);
691
    output(" ");
710
    output(" ");
692
    nls_outputnl(37,24); /* "bytes free" */
711
    nls_outputnl(37,24); /* "bytes free" */
693
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
712
    if (req.flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
694
  }
713
  }
695
 
714
 
696
  /* free the buffer memory (if used) */
715
  /* free the buffer memory (if used) */
697
  if (glob_sortcmp_dat.dtabuf_root != NULL) _ffree(glob_sortcmp_dat.dtabuf_root);
716
  if (glob_sortcmp_dat.dtabuf_root != NULL) _ffree(glob_sortcmp_dat.dtabuf_root);
698
 
717