Subversion Repositories SvarDOS

Rev

Rev 417 | Rev 421 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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