Subversion Repositories SvarDOS

Rev

Rev 417 | Rev 421 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
368 mateuszvis 1
/*
2
 * dir
3
 *
4
 * Displays a list of files and subdirectories in a directory.
5
 *
6
 * DIR [drive:][path][filename] [/P] [/W] [/A[:]attributes] [/O[[:]sortorder]] [/S] [/B] [/L]
7
 *
8
 * /P Pauses after each screenful of information.
9
 * /W Uses wide list format.
10
 *
11
 * /A Displays file with specified attributes:
12
 *     D Directories           R Read-only files     H Hidden files
13
 *     A Ready for archiving   S System files        - prefix meaning "not"
14
 *
15
 * /O List files in sorted order:
16
 *     N by name            S by size              E by extension
17
 *     D by date            G group dirs first     - prefix to reverse order
18
 *
19
 * /S Displays files in specified directory and all subdirectories.
20
 * /B Uses bare format (no heading information or summary)
21
 * /L Uses lowercases
22
 */
23
 
396 mateuszvis 24
/* NOTE: /A attributes are matched in an exclusive way, ie. only files with
25
 *       the specified attributes are matched. This is different from how DOS
26
 *       itself matches attributes hence DIR cannot rely on the attributes
27
 *       filter within FindFirst.
28
 *
29
 * NOTE: Multiple /A are not supported - only the last one is significant.
30
 */
31
 
420 mateuszvis 32
#define WCOLWIDTH 15  /* width of a column in wide mode output */
33
 
372 mateuszvis 34
static int cmd_dir(struct cmd_funcparam *p) {
393 mateuszvis 35
  const char *filespecptr = NULL;
388 mateuszvis 36
  struct DTA *dta = (void *)0x80; /* set DTA to its default location at 80h in PSP */
417 mateuszvis 37
  unsigned short i;
396 mateuszvis 38
  unsigned short availrows;  /* counter of available rows on display (used for /P) */
420 mateuszvis 39
  unsigned short wcols = screen_getwidth() / WCOLWIDTH; /* number of columns in wide mode */
40
  unsigned char wcolcount;
41
  struct nls_patterns *nls = (void *)(p->BUFFER + (BUFFER_SIZE / 3));
42
  char *buff2 = p->BUFFER + (BUFFER_SIZE / 3 * 2);
43
 
396 mateuszvis 44
  #define DIR_FLAG_PAUSE  1
45
  #define DIR_FLAG_RECUR  4
420 mateuszvis 46
  #define DIR_FLAG_LCASE  8
396 mateuszvis 47
  unsigned char flags = 0;
368 mateuszvis 48
 
420 mateuszvis 49
  #define DIR_OUTPUT_NORM 1
50
  #define DIR_OUTPUT_WIDE 2
51
  #define DIR_OUTPUT_BARE 3
52
  unsigned char format = DIR_OUTPUT_NORM;
53
 
390 mateuszvis 54
  if (cmd_ishlp(p)) {
396 mateuszvis 55
    outputnl("Displays a list of files and subdirectories in a directory");
56
    outputnl("");
57
    outputnl("DIR [drive:][path][filename] [/P] [/W] [/A[:]attributes] [/O[[:]sortorder]] [/S] [/B] [/L]");
58
    outputnl("");
59
    outputnl("/P Pauses after each screenful of information");
60
    outputnl("/W Uses wide list format");
61
    outputnl("");
62
    outputnl("/A Displays files with specified attributes:");
63
    outputnl("    D Directories            R Read-only files        H Hidden files");
64
    outputnl("    A Ready for archiving    S System files           - prefix meaning \"not\"");
65
    outputnl("");
66
    outputnl("/O List files in sorted order:");
67
    outputnl("    N by name                S by size                E by extension");
68
    outputnl("    D by date                G group dirs first       - prefix to reverse order");
69
    outputnl("");
70
    outputnl("/S Displays files in specified directory and all subdirectories");
71
    outputnl("/B Uses bare format (no heading information or summary)");
72
    outputnl("/L Uses lowercases");
73
 
74
    /* TODO FIXME REMOVE THIS ONCE ALL IMPLEMENTED */
75
    outputnl("\r\n*** THIS COMMAND IS NOT FULLY IMPLEMENTED YET ***");
76
 
390 mateuszvis 77
    return(-1);
78
  }
79
 
420 mateuszvis 80
  i = nls_getpatterns(nls);
81
  if (i != 0) outputnl(doserr(i));
82
 
393 mateuszvis 83
  /* parse command line */
84
  for (i = 0; i < p->argc; i++) {
85
    if (p->argv[i][0] == '/') {
396 mateuszvis 86
      char arg;
87
      char neg = 0;
88
      /* detect negations and get actual argument */
89
      if (p->argv[i][1] == '-') neg = 1;
90
      arg = p->argv[i][1 + neg];
91
      /* */
92
      switch (arg) {
93
        case 'a':
94
        case 'A':
95
          /* TODO */
96
          outputnl("/A NOT IMPLEMENTED YET");
97
          return(-1);
98
          break;
399 mateuszvis 99
        case 'b':
100
        case 'B':
420 mateuszvis 101
          format = DIR_OUTPUT_BARE;
399 mateuszvis 102
          break;
420 mateuszvis 103
        case 'w':
104
        case 'W':
105
          format = DIR_OUTPUT_WIDE;
106
          break;
396 mateuszvis 107
        case 'p':
108
        case 'P':
109
          flags |= DIR_FLAG_PAUSE;
110
          if (neg) flags &= (0xff ^ DIR_FLAG_PAUSE);
111
          break;
420 mateuszvis 112
        case 'l':
113
        case 'L':
114
          flags |= DIR_FLAG_LCASE;
115
          break;
393 mateuszvis 116
        default:
117
          outputnl("Invalid switch");
118
          return(-1);
119
      }
120
    } else {  /* filespec */
121
      if (filespecptr != NULL) {
122
        outputnl("Too many parameters");
123
        return(-1);
124
      }
125
      filespecptr = p->argv[i];
126
    }
127
  }
368 mateuszvis 128
 
393 mateuszvis 129
  if (filespecptr == NULL) filespecptr = ".";
130
 
417 mateuszvis 131
  /* special case: "DIR drive:" (truename() fails on "C:" under MS-DOS 6.0) */
132
  if ((filespecptr[0] != 0) && (filespecptr[1] == ':') && (filespecptr[2] == 0)) {
133
    if ((filespecptr[0] >= 'a') && (filespecptr[0] <= 'z')) {
134
      p->BUFFER[0] = filespecptr[0] - ('a' - 1);
135
    } else {
136
      p->BUFFER[0] = filespecptr[0] - ('A' - 1);
399 mateuszvis 137
    }
417 mateuszvis 138
    i = curpathfordrv(p->BUFFER, p->BUFFER[0]);
139
  } else {
140
    i = file_truename(filespecptr, p->BUFFER);
399 mateuszvis 141
  }
417 mateuszvis 142
  if (i != 0) {
143
    outputnl(doserr(i));
144
    return(-1);
145
  }
393 mateuszvis 146
 
420 mateuszvis 147
  if (format != DIR_OUTPUT_BARE) {
399 mateuszvis 148
    unsigned char drv = p->BUFFER[0];
149
    if (drv >= 'a') {
150
      drv -= 'a';
151
    } else {
152
      drv -= 'A';
153
    }
403 mateuszvis 154
    cmd_vol_internal(drv, buff2);
155
    sprintf(buff2, "Directory of %s", p->BUFFER);
399 mateuszvis 156
    /* trim at first '?', if any */
403 mateuszvis 157
    for (i = 0; buff2[i] != 0; i++) if (buff2[i] == '?') buff2[i] = 0;
158
    outputnl(buff2);
399 mateuszvis 159
    outputnl("");
160
  }
161
 
417 mateuszvis 162
  /* if dir: append a backslash (also get its len) */
163
  i = path_appendbkslash_if_dir(p->BUFFER);
393 mateuszvis 164
 
417 mateuszvis 165
  /* if ends with a \ then append ????????.??? */
166
  if (p->BUFFER[i - 1] == '\\') strcat(p->BUFFER, "????????.???");
393 mateuszvis 167
 
417 mateuszvis 168
  i = findfirst(dta, p->BUFFER, DOS_ATTR_RO | DOS_ATTR_HID | DOS_ATTR_SYS | DOS_ATTR_DIR | DOS_ATTR_ARC);
169
  if (i != 0) {
170
    outputnl(doserr(i));
171
    return(-1);
172
  }
173
 
396 mateuszvis 174
  availrows = screen_getheight();
420 mateuszvis 175
  wcolcount = 0; /* may be used for columns counting with wide mode */
396 mateuszvis 176
 
420 mateuszvis 177
  do {
178
    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... */
368 mateuszvis 179
 
420 mateuszvis 180
    switch (format) {
181
      case DIR_OUTPUT_NORM:
182
        /* print fname-space-extension (unless it's "." or "..", then print as-is) */
183
        if (dta->fname[0] == '.') {
184
          output(dta->fname);
185
          i = strlen(dta->fname);
186
          while (i++ < 12) output(" ");
187
        } else {
188
          file_fname2fcb(buff2, dta->fname);
189
          memmove(buff2 + 9, buff2 + 8, 4);
190
          buff2[8] = ' ';
191
          output(buff2);
192
        }
193
        output(" ");
194
        /* either <DIR> or right aligned 10-chars byte size */
195
        memset(buff2, ' ', 10);
196
        if (dta->attr & DOS_ATTR_DIR) {
197
          strcpy(buff2 + 10, "<DIR>");
198
        } else {
199
          _ultoa(dta->size, buff2 + 10, 10); /* OpenWatcom extension */
200
        }
201
        output(buff2 + strlen(buff2) - 10);
202
        /* two spaces and NLS DATE */
203
        buff2[0] = ' ';
204
        buff2[1] = ' ';
205
        nls_format_date(buff2 + 2, dta->date_yr + 1980, dta->date_mo, dta->date_dy, nls);
206
        output(buff2);
207
 
208
        /* one space and NLS TIME */
209
        nls_format_time(buff2 + 1, dta->time_hour, dta->time_min, nls);
210
        outputnl(buff2);
211
        break;
212
 
213
      case DIR_OUTPUT_WIDE: /* display in columns of 12 chars per item */
214
        i = strlen(dta->fname);
215
        if (dta->attr & DOS_ATTR_DIR) {
216
          i += 2;
217
          output("[");
218
          output(dta->fname);
219
          output("]");
220
        } else {
221
          output(dta->fname);
222
        }
223
        while (i++ < WCOLWIDTH) output(" ");
224
        if (++wcolcount == wcols) {
225
          wcolcount = 0;
226
          outputnl("");
227
        }
228
        break;
229
 
230
      case DIR_OUTPUT_BARE:
231
        outputnl(dta->fname);
232
        break;
396 mateuszvis 233
    }
368 mateuszvis 234
 
420 mateuszvis 235
    if ((flags & DIR_FLAG_PAUSE) && (--availrows < 2)) {
236
      press_any_key();
237
      availrows = screen_getheight();
238
    }
239
 
240
  } while (findnext(dta) == 0);
241
 
242
  if (wcolcount != 0) outputnl("");
243
 
368 mateuszvis 244
  return(-1);
245
}