Subversion Repositories SvarDOS

Rev

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

Rev 1142 Rev 1716
Line 1... Line 1...
1
/* This file is part of the SvarCOM project and is published under the terms
1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
2
 * of the MIT license.
3
 *
3
 *
4
 * Copyright (C) 2021-2022 Mateusz Viste
4
 * Copyright (C) 2021-2024 Mateusz Viste
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
Line 54... Line 54...
54
 */
54
 */
55
 
55
 
56
#define WCOLWIDTH 15  /* width of a column in wide mode output */
56
#define WCOLWIDTH 15  /* width of a column in wide mode output */
57
 
57
 
58
 
58
 
-
 
59
/* a "tiny" DTA is a DTA that is stripped from bytes that are not needed for
-
 
60
 * DIR operations */
-
 
61
_Packed struct TINYDTA {
-
 
62
/*  char reserved[21];
-
 
63
  unsigned char attr; */
-
 
64
  unsigned short time_sec2:5;
-
 
65
  unsigned short time_min:6;
-
 
66
  unsigned short time_hour:5;
-
 
67
  unsigned short date_dy:5;
-
 
68
  unsigned short date_mo:4;
-
 
69
  unsigned short date_yr:7;
-
 
70
  unsigned long size;
-
 
71
/*  char fname[13]; */
-
 
72
  char fname[12];
-
 
73
};
-
 
74
 
-
 
75
/* max amount of DTAs that can be buffered (not using 65535 because fmalloc a bit of overhead space) */
-
 
76
#define MAX_DTA_BUFCOUNT (65500 / sizeof(struct TINYDTA))
-
 
77
 
-
 
78
 
59
/* fills freebytes with free bytes for drv (A=0, B=1, etc)
79
/* fills freebytes with free bytes for drv (A=0, B=1, etc)
60
 * returns DOS ERR code on failure */
80
 * returns DOS ERR code on failure */
61
static unsigned short cmd_dir_df(unsigned long *freebytes, unsigned char drv) {
81
static unsigned short cmd_dir_df(unsigned long *freebytes, unsigned char drv) {
62
  unsigned short res = 0;
82
  unsigned short res = 0;
63
  unsigned short sects_per_clust = 0, avail_clusts = 0, bytes_per_sect = 0;
83
  unsigned short sects_per_clust = 0, avail_clusts = 0, bytes_per_sect = 0;
Line 155... Line 175...
155
  }
175
  }
156
  return(0);
176
  return(0);
157
}
177
}
158
 
178
 
159
 
179
 
-
 
180
/* compare attributes in a DTA node to mandatory and optional attributes. returns 1 on match, 0 otherwise */
-
 
181
static int filter_attribs(const struct DTA *dta, unsigned char attrfilter_must, unsigned char attrfilter_may) {
-
 
182
  /* if mandatory attribs are requested, filter them now */
-
 
183
  if ((attrfilter_must & dta->attr) != attrfilter_must) return(0);
-
 
184
 
-
 
185
  /* if file contains attributes that are not allowed -> skip */
-
 
186
  if ((~attrfilter_may & dta->attr) != 0) return(0);
-
 
187
 
-
 
188
  return(1);
-
 
189
}
-
 
190
 
-
 
191
 
-
 
192
 
160
#define DIR_ATTR_DEFAULT (DOS_ATTR_RO | DOS_ATTR_DIR | DOS_ATTR_ARC)
193
#define DIR_ATTR_DEFAULT (DOS_ATTR_RO | DOS_ATTR_DIR | DOS_ATTR_ARC)
161
 
194
 
162
static enum cmd_result cmd_dir(struct cmd_funcparam *p) {
195
static enum cmd_result cmd_dir(struct cmd_funcparam *p) {
163
  const char *filespecptr = NULL;
196
  const char *filespecptr = NULL;
164
  struct DTA *dta = (void *)0x80; /* set DTA to its default location at 80h in PSP */
197
  struct DTA *dta = (void *)0x80; /* set DTA to its default location at 80h in PSP */
-
 
198
  struct DTA far *dtabuf = NULL; /* used to buffer results when sorting is enabled */
-
 
199
  struct DTA far *dtabuf_root = NULL;
-
 
200
  unsigned short dtabufcount = 0;
165
  unsigned short i;
201
  unsigned short i;
166
  unsigned short availrows;  /* counter of available rows on display (used for /P) */
202
  unsigned short availrows;  /* counter of available rows on display (used for /P) */
167
  unsigned short screenw = screen_getwidth();
203
  unsigned short screenw = screen_getwidth();
168
  unsigned short wcols = screenw / WCOLWIDTH; /* number of columns in wide mode */
204
  unsigned short wcols = screenw / WCOLWIDTH; /* number of columns in wide mode */
169
  unsigned char wcolcount;
205
  unsigned char wcolcount;
Line 172... Line 208...
172
  unsigned long summary_fcount = 0;
208
  unsigned long summary_fcount = 0;
173
  unsigned long summary_totsz = 0;
209
  unsigned long summary_totsz = 0;
174
  unsigned char drv = 0;
210
  unsigned char drv = 0;
175
  unsigned char attrfilter_may = DIR_ATTR_DEFAULT;
211
  unsigned char attrfilter_may = DIR_ATTR_DEFAULT;
176
  unsigned char attrfilter_must = 0;
212
  unsigned char attrfilter_must = 0;
-
 
213
  const char far *order = NULL; /* order string (like "GNE-SD"), this may come
-
 
214
                                   either from the /O argument or from the
-
 
215
                                   DIRCMD env variable (NULL = "no sort")
-
 
216
                                   note 1: the '-' reverse relates only to
-
 
217
                                   the letter that immediately follows it
-
 
218
                                   note 2: '/O' is a shorthand for '/OGNE' */
177
 
219
 
178
  #define DIR_FLAG_PAUSE  1
220
  #define DIR_FLAG_PAUSE  1
179
  #define DIR_FLAG_RECUR  4
221
  #define DIR_FLAG_RECUR  4
180
  #define DIR_FLAG_LCASE  8
222
  #define DIR_FLAG_LCASE  8
181
  unsigned char flags = 0;
223
  unsigned char flags = 0;
Line 256... Line 298...
256
        case 'L':
298
        case 'L':
257
          flags |= DIR_FLAG_LCASE;
299
          flags |= DIR_FLAG_LCASE;
258
          break;
300
          break;
259
        case 'o':
301
        case 'o':
260
        case 'O':
302
        case 'O':
261
          /* TODO */
303
          order = arg+1;
262
          outputnl("/O NOT IMPLEMENTED YET");
-
 
263
          return(CMD_FAIL);
-
 
264
          break;
304
          break;
265
        case 'p':
305
        case 'p':
266
        case 'P':
306
        case 'P':
267
          flags |= DIR_FLAG_PAUSE;
307
          flags |= DIR_FLAG_PAUSE;
268
          if (neg) flags &= (0xff ^ DIR_FLAG_PAUSE);
308
          if (neg) flags &= (0xff ^ DIR_FLAG_PAUSE);
Line 337... Line 377...
337
  if (i != 0) {
377
  if (i != 0) {
338
    nls_outputnl_doserr(i);
378
    nls_outputnl_doserr(i);
339
    return(CMD_FAIL);
379
    return(CMD_FAIL);
340
  }
380
  }
341
 
381
 
-
 
382
  /* if sorting is involved, then let's buffer all results (and sort them) */
-
 
383
  if (order != NULL) {
-
 
384
    /* allocate a memory buffer - try several sizes until one succeeds */
-
 
385
    unsigned short memsz[] = {65500, 32000, 16000, 8000, 4000, 2000, 0};
-
 
386
    unsigned short max_dta_bufcount = 0;
-
 
387
    for (i = 0; memsz[i] != 0; i++) {
-
 
388
      dtabuf = _fmalloc(memsz[i]);
-
 
389
      if (dtabuf != NULL) break;
-
 
390
    }
-
 
391
 
-
 
392
    if (dtabuf == NULL) {
-
 
393
      nls_outputnl_doserr(8); /* out of memory */
-
 
394
      return(CMD_FAIL);
-
 
395
    }
-
 
396
 
-
 
397
    /* remember the address so I can free it afterwards */
-
 
398
    dtabuf_root = dtabuf;
-
 
399
 
-
 
400
    /* compute the amount of DTAs I can buffer */
-
 
401
    max_dta_bufcount = 1; //memsz[i] / sizeof(struct TINYDTA);
-
 
402
    printf("max_dta_bufcount = %u\n", max_dta_bufcount);
-
 
403
 
-
 
404
    do {
-
 
405
      /* filter out files with uninteresting attributes */
-
 
406
      if (filter_attribs(dta, attrfilter_must, attrfilter_may) == 0) continue;
-
 
407
 
-
 
408
      _fmemcpy(&(dtabuf[dtabufcount]), ((char *)dta) + 22, sizeof(struct TINYDTA));
-
 
409
 
-
 
410
      /* save attribs in sec field, otherwise zero it (this field is not
-
 
411
       * displayed and dropping the attr field saves 2 bytes per entry) */
-
 
412
      dtabuf[dtabufcount++].time_sec2 = (dta->attr & 31);
-
 
413
 
-
 
414
      /* do I have any space left? */
-
 
415
      if (dtabufcount == max_dta_bufcount) {
-
 
416
        //outputnl("TOO MANY ENTRIES FOR SORTING! LIST IS UNSORTED");
-
 
417
        break;
-
 
418
      }
-
 
419
 
-
 
420
    } while (findnext(dta) == 0);
-
 
421
 
-
 
422
    /* sort the list - the tricky part is that my array is a far address while
-
 
423
     * qsort works only with near pointers, so I have to use an ugly auxiliary
-
 
424
     * table */
-
 
425
    // qsort(dt); TODO
-
 
426
 
-
 
427
    /* preload first entry */
-
 
428
    _fmemcpy(((unsigned char *)dta) + 22, dtabuf, sizeof(struct TINYDTA));
-
 
429
    dta->attr = dtabuf->time_sec2;
-
 
430
    dtabuf++;
-
 
431
    dtabufcount--;
-
 
432
  }
-
 
433
 
342
  wcolcount = 0; /* may be used for columns counting with wide mode */
434
  wcolcount = 0; /* may be used for columns counting with wide mode */
343
 
435
 
344
  do {
436
  for (;;) {
345
    /* if mandatory attribs are requested, filter them now */
-
 
346
    if ((attrfilter_must & dta->attr) != attrfilter_must) continue;
-
 
347
 
437
 
348
    /* if file contains attributes that are not allowed -> skip */
438
    /* filter out attributes (skip if entry comes from buffer, then it was already veted) */
349
    if ((~attrfilter_may & dta->attr) != 0) continue;
439
    if (filter_attribs(dta, attrfilter_must, attrfilter_may) == 0) continue;
350
 
440
 
351
    /* turn string lcase (/L) */
441
    /* turn string lcase (/L) */
352
    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... */
442
    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... */
353
 
443
 
354
    summary_fcount++;
444
    summary_fcount++;
Line 415... Line 505...
415
        break;
505
        break;
416
    }
506
    }
417
 
507
 
418
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
508
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
419
 
509
 
-
 
510
    /* take next entry, either from buf or disk */
-
 
511
    if (dtabufcount > 0) {
-
 
512
      /* preload first entry */
-
 
513
      _fmemcpy(((unsigned char *)dta) + 22, dtabuf, sizeof(struct TINYDTA));
-
 
514
      dta->attr = dtabuf->time_sec2;
-
 
515
      dtabuf++;
-
 
516
      dtabufcount--;
-
 
517
    } else {
420
  } while (findnext(dta) == 0);
518
      if (findnext(dta) != 0) break;
-
 
519
    }
-
 
520
 
-
 
521
  }
421
 
522
 
422
  if (wcolcount != 0) {
523
  if (wcolcount != 0) {
423
    outputnl(""); /* in wide mode make sure to end on a clear row */
524
    outputnl(""); /* in wide mode make sure to end on a clear row */
424
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
525
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
425
  }
526
  }
Line 450... Line 551...
450
    output(" ");
551
    output(" ");
451
    nls_outputnl(37,24); /* "bytes free" */
552
    nls_outputnl(37,24); /* "bytes free" */
452
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
553
    if (flags & DIR_FLAG_PAUSE) dir_pagination(&availrows);
453
  }
554
  }
454
 
555
 
-
 
556
  /* free the buffer memory (if used) */
-
 
557
  if (dtabuf_root != NULL) _ffree(dtabuf_root);
-
 
558
 
455
  return(CMD_OK);
559
  return(CMD_OK);
456
}
560
}