/svarcom/trunk/cmd/dir.c |
---|
29,20 → 29,28 |
* NOTE: Multiple /A are not supported - only the last one is significant. |
*/ |
#define WCOLWIDTH 15 /* width of a column in wide mode output */ |
static int cmd_dir(struct cmd_funcparam *p) { |
const char *filespecptr = NULL; |
struct DTA *dta = (void *)0x80; /* set DTA to its default location at 80h in PSP */ |
unsigned short i; |
unsigned short availrows; /* counter of available rows on display (used for /P) */ |
unsigned short wcols = screen_getwidth() / WCOLWIDTH; /* number of columns in wide mode */ |
unsigned char wcolcount; |
struct nls_patterns *nls = (void *)(p->BUFFER + (BUFFER_SIZE / 3)); |
char *buff2 = p->BUFFER + (BUFFER_SIZE / 3 * 2); |
#define DIR_FLAG_PAUSE 1 |
#define DIR_FLAG_WIDE 2 |
#define DIR_FLAG_RECUR 4 |
#define DIR_FLAG_BARE 8 |
#define DIR_FLAG_LCASE 16 |
#define DIR_FLAG_LCASE 8 |
unsigned char flags = 0; |
// unsigned char attribs_show = 0; /* show only files with ALL these attribs */ |
// unsigned char attribs_hide = 0; /* hide files with ANY of these attribs */ |
#define DIR_OUTPUT_NORM 1 |
#define DIR_OUTPUT_WIDE 2 |
#define DIR_OUTPUT_BARE 3 |
unsigned char format = DIR_OUTPUT_NORM; |
if (cmd_ishlp(p)) { |
outputnl("Displays a list of files and subdirectories in a directory"); |
outputnl(""); |
69,6 → 77,9 |
return(-1); |
} |
i = nls_getpatterns(nls); |
if (i != 0) outputnl(doserr(i)); |
/* parse command line */ |
for (i = 0; i < p->argc; i++) { |
if (p->argv[i][0] == '/') { |
87,13 → 98,21 |
break; |
case 'b': |
case 'B': |
flags |= DIR_FLAG_BARE; |
format = DIR_OUTPUT_BARE; |
break; |
case 'w': |
case 'W': |
format = DIR_OUTPUT_WIDE; |
break; |
case 'p': |
case 'P': |
flags |= DIR_FLAG_PAUSE; |
if (neg) flags &= (0xff ^ DIR_FLAG_PAUSE); |
break; |
case 'l': |
case 'L': |
flags |= DIR_FLAG_LCASE; |
break; |
default: |
outputnl("Invalid switch"); |
return(-1); |
125,9 → 144,8 |
return(-1); |
} |
if ((flags & DIR_FLAG_BARE) == 0) { |
if (format != DIR_OUTPUT_BARE) { |
unsigned char drv = p->BUFFER[0]; |
char *buff2 = p->BUFFER + (BUFFER_SIZE / 2); |
if (drv >= 'a') { |
drv -= 'a'; |
} else { |
154,20 → 172,74 |
} |
availrows = screen_getheight(); |
wcolcount = 0; /* may be used for columns counting with wide mode */ |
do { |
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... */ |
switch (format) { |
case DIR_OUTPUT_NORM: |
/* print fname-space-extension (unless it's "." or "..", then print as-is) */ |
if (dta->fname[0] == '.') { |
output(dta->fname); |
i = strlen(dta->fname); |
while (i++ < 12) output(" "); |
} else { |
file_fname2fcb(buff2, dta->fname); |
memmove(buff2 + 9, buff2 + 8, 4); |
buff2[8] = ' '; |
output(buff2); |
} |
output(" "); |
/* either <DIR> or right aligned 10-chars byte size */ |
memset(buff2, ' ', 10); |
if (dta->attr & DOS_ATTR_DIR) { |
strcpy(buff2 + 10, "<DIR>"); |
} else { |
_ultoa(dta->size, buff2 + 10, 10); /* OpenWatcom extension */ |
} |
output(buff2 + strlen(buff2) - 10); |
/* two spaces and NLS DATE */ |
buff2[0] = ' '; |
buff2[1] = ' '; |
nls_format_date(buff2 + 2, dta->date_yr + 1980, dta->date_mo, dta->date_dy, nls); |
output(buff2); |
/* one space and NLS TIME */ |
nls_format_time(buff2 + 1, dta->time_hour, dta->time_min, nls); |
outputnl(buff2); |
break; |
case DIR_OUTPUT_WIDE: /* display in columns of 12 chars per item */ |
i = strlen(dta->fname); |
if (dta->attr & DOS_ATTR_DIR) { |
i += 2; |
output("["); |
output(dta->fname); |
output("]"); |
} else { |
output(dta->fname); |
} |
while (i++ < WCOLWIDTH) output(" "); |
if (++wcolcount == wcols) { |
wcolcount = 0; |
outputnl(""); |
} |
break; |
case DIR_OUTPUT_BARE: |
outputnl(dta->fname); |
availrows--; |
break; |
} |
while (findnext(dta) == 0) { |
outputnl(dta->fname); |
if (flags & DIR_FLAG_PAUSE) { |
availrows--; |
if (availrows < 2) { |
if ((flags & DIR_FLAG_PAUSE) && (--availrows < 2)) { |
press_any_key(); |
availrows = screen_getheight(); |
} |
} |
} |
} while (findnext(dta) == 0); |
if (wcolcount != 0) outputnl(""); |
return(-1); |
} |
/svarcom/trunk/helpers.c |
---|
4,9 → 4,11 |
*/ |
#include <i86.h> /* MK_FP() */ |
#include <stdio.h> /* sprintf() */ |
#include "helpers.h" |
/* case-insensitive comparison of strings, returns non-zero on equality */ |
int imatch(const char *s1, const char *s2) { |
for (;;) { |
252,8 → 254,8 |
unsigned short i; |
/* fill dst with 11 spaces and a NULL terminator */ |
for (i = 0; i < 12; i++) dst[i] = ' '; |
dst[12] = 0; |
for (i = 0; i < 11; i++) dst[i] = ' '; |
dst[11] = 0; |
/* copy fname until dot (.) or 8 characters */ |
for (i = 0; i < 8; i++) { |
399,3 → 401,111 |
return(r); |
} |
/* fills a nls_patterns struct with current NLS patterns, returns 0 on success, DOS errcode otherwise */ |
unsigned short nls_getpatterns(struct nls_patterns *p) { |
unsigned short r = 0; |
_asm { |
mov ax, 0x3800 /* DOS 2+ -- Get Country Info for current country */ |
mov dx, p /* DS:DX points to the CountryInfoRec buffer */ |
int 0x21 |
jnc DONE |
mov [r], ax /* copy DOS err code to r */ |
DONE: |
} |
return(r); |
} |
/* computes a formatted date based on NLS patterns found in p |
* returns length of result */ |
unsigned short nls_format_date(char *s, unsigned short yr, unsigned char mo, unsigned char dy, const struct nls_patterns *p) { |
unsigned short items[3]; |
/* preset date/month/year in proper order depending on date format */ |
switch (p->dateformat) { |
case 0: /* USA style: m d y */ |
items[0] = mo; |
items[1] = dy; |
items[2] = yr; |
break; |
case 1: /* EU style: d m y */ |
items[0] = dy; |
items[1] = mo; |
items[2] = yr; |
break; |
case 2: /* Japan-style: y m d */ |
default: |
items[0] = yr; |
items[1] = mo; |
items[2] = dy; |
break; |
} |
/* compute the string */ |
return(sprintf(s, "%02u%s%02u%s%02u", items[0], p->datesep, items[1], p->datesep, items[2])); |
} |
/* computes a formatted time based on NLS patterns found in p |
* returns length of result */ |
unsigned short nls_format_time(char *s, unsigned char ho, unsigned char mn, const struct nls_patterns *p) { |
char ampm[2] = {0, 0}; |
const char *fmt = "%02u%s%02u%s"; |
if (p->timefmt == 0) { |
if (ho == 12) { |
ampm[0] = 'p'; |
} else if (ho > 12) { |
ho -= 12; |
ampm[0] = 'p'; |
} else { /* ho < 12 */ |
if (ho == 0) ho = 12; |
ampm[0] = 'a'; |
} |
fmt = "%2u%s%02u%s"; |
} |
return(sprintf(s, fmt, ho, p->timesep, mn, ampm)); |
} |
/* computes a formatted integer number based on NLS patterns found in p |
* returns length of result */ |
unsigned short nls_format_number(char *s, long num, const struct nls_patterns *p) { |
unsigned short sl = 0, res, i; |
unsigned char thcount = 0; |
/* handle negative values */ |
if (num < 0) { |
s[sl++] = '-'; |
num = 0 - num; |
} |
/* write the absolute value now */ |
do { |
if ((thcount == 3) && (p->thousep[0] != 0)) { |
s[sl++] = p->thousep[0]; |
thcount = 0; |
} |
s[sl++] = '0' + num % 10; |
num /= 10; |
thcount++; |
} while (num > 0); |
/* terminate the string and remember its size */ |
s[sl] = 0; |
res = sl; |
/* reverse the string now (it has been build in reverse) */ |
if (s[0] == '-') { |
sl--; |
s++; |
} |
for (i = 0; i <= (sl / 2); i++) { |
thcount = s[i]; |
s[i] = s[sl - (i + 1)]; |
s[sl - (i + 1)] = thcount; |
} |
return(res); |
} |
/svarcom/trunk/helpers.h |
---|
26,12 → 26,49 |
_Packed struct DTA { |
char reserved[21]; |
unsigned char attr; |
unsigned short time; |
unsigned short date; |
unsigned short time_sec2:5; |
unsigned short time_min:6; |
unsigned short time_hour:5; |
unsigned short date_dy:5; |
unsigned short date_mo:4; |
unsigned short date_yr:7; |
unsigned long size; |
char fname[13]; |
}; |
/* this is also known as the "Country Info Block" or "CountryInfoRec": |
* offset size desc |
* +0 2 wDateFormat 0=USA (m d y), 1=Europe (d m y), 2=Japan (y m d) |
* +2 5 szCrncySymb currency symbol (ASCIIZ) |
* +7 2 szThouSep thousands separator (ASCIIZ) |
* +9 2 szDecSep decimal separator (ASCIIZ) |
* +0bH 2 szDateSep date separator (ASCIIZ) |
* +0dH 2 szTimeSep time separator (ASCIIZ) |
* +0fH 1 bCrncyFlags currency format flags |
* +10H 1 bCrncyDigits decimals digits in currency |
* +11H 1 bTimeFormat time format 0=12h 1=24h |
* +12H 4 pfCasemap Casemap FAR call address |
* +16H 2 szDataSep data list separator (ASCIIZ) |
* +18H 10 res reserved zeros |
* 34 total length |
*/ |
_Packed struct nls_patterns { |
unsigned short dateformat; |
char currency[5]; |
char thousep[2]; |
char decsep[2]; |
char datesep[2]; |
char timesep[2]; |
unsigned char currflags; |
unsigned char currdigits; |
unsigned char timefmt; |
void far *casemapfn; |
char datalistsep[2]; |
char reserved[10]; |
}; |
#define DOS_ATTR_RO 1 |
#define DOS_ATTR_HID 2 |
#define DOS_ATTR_SYS 4 |
89,4 → 126,19 |
* returns 0 on success, doserr otherwise */ |
unsigned short curpathfordrv(char *buff, unsigned char d); |
/* fills a nls_patterns struct with current NLS patterns, returns 0 on success, DOS errcode otherwise */ |
unsigned short nls_getpatterns(struct nls_patterns *p); |
/* computes a formatted date based on NLS patterns found in p |
* returns length of result */ |
unsigned short nls_format_date(char *s, unsigned short yr, unsigned char mo, unsigned char dy, const struct nls_patterns *p); |
/* computes a formatted time based on NLS patterns found in p |
* returns length of result */ |
unsigned short nls_format_time(char *s, unsigned char ho, unsigned char mn, const struct nls_patterns *p); |
/* computes a formatted integer number based on NLS patterns found in p |
* returns length of result */ |
unsigned short nls_format_number(char *s, long num, const struct nls_patterns *p); |
#endif |