/*** *dirent.c - disked disk directory maintenence. * *Copyright (c) 1993-1995, Gregg Jennings. All wrongs reserved. * P O Box 200, Falmouth, MA 02541-0200 * *Purpose: * Handles the displaying and editing of directory sectors. * *Notice: * This progam may be freely used and distributed. Any distrubution * with modifications must retain the above copyright statement and * modifications noted. * No pulp-publication, in whole or in part, permitted without * permission (magazines or books). *******************************************************************************/ /* Versions: 1.3 13-Nov-1993 more use of structures, cleaned up changedir() 1.2 14-Jan-1994 =0 bug fix in changedir() 1.1 13-Nov-1993 Started structures 1.0 June 1993 Release Notes: This is all "Brute Force" code. Written in a couple a days after I wanted to arange all my directories is a certain non-sorted way easier than a touch program. */ #include #include #include #include "mylib.h" /* getnum() */ #include "keys.h" #include "dirent.h" /* DosTime, DosDate, dDIR */ #include "console.h" /* input, output, cursor stuff */ /* NO globals referenced here */ /* NO globals defined here */ #define isexten(c) ( (c>0x7f) && (c<255) ) static int command(int c); static int text(int len, unsigned char *b); static int attrib(unsigned char *b); static int dostime(DosTime time, DosTime *t); static int dosdate(DosDate date, DosDate *d); static int pdirent(dDIR *); /* ...filename.txt...ttri...hh:mm:ss...mm/dd/yy...1234567...1234567 */ static char *dir_header=" File Attr Time Date Cluster Size\n"; /* display directory */ extern void dumpdir(unsigned char *buf, int sec_size) { int i; dDIR *dir = (dDIR *)buf; output('\n'); output('\n'); print(dir_header); /* print header */ for (i = 0; i < sec_size; i+=sizeof(dDIR),dir++) /* and each entry */ { output('\n'); put(3,' '); pdirent(dir); } output('\n'); } /* change dir command structure */ /* ...filename.txt...ttri...hh:mm:ss...mm/dd/yy...1234567...1234567 */ struct fields { int beg; /* starting column */ int end; /* ending column */ int (*inp)(); /* function to do the change */ } field[] = { {4,7, command}, {9,16, text}, {18,20,text}, {24,28,attrib}, {32,33,dostime}, {43,44,dosdate}, }; /*** *changedir() - edit directory entry(s) in sector buffer * * ver 1.1 fixed =0 bug ****/ #define NUMFIELDS (sizeof(field)/sizeof(struct fields)-1) #define LASTENTRY ((int)(sec_size/sizeof(dDIR))-1) extern int changedir(unsigned char *buf,int sec_size) { int i; unsigned int a,x; unsigned int *b; unsigned int c; unsigned int n; int o; /* offset into buffer (dDIR pointer) */ int r; int p; /* absolute position */ int f; /* field in */ get_cursor(&a,&x); print("\n\n %s",dir_header); i = r = 0; for (;;) { c = f = 0; /* start off at command function */ p = field[f].beg; print("\n%03d ",i+1); o = i*sizeof(dDIR); r = pdirent((dDIR *)(buf+o)); get: set_cursor(a,p); switch (f) { case 0: /* command */ c = (*field[f].inp)(r); /* arg: entry type */ break; case 1: /* file name */ c = (*field[f].inp)(8,buf+o); /* args: length, char* */ break; case 2: /* file extension */ c = (*field[f].inp)(3,buf+o+8); /* args: length, char* */ break; case 3: /* attribute */ c = (*field[f].inp)(buf+o+11); /* arg: int* */ break; case 4: /* time */ b=(unsigned int *)(buf+o+0x16); /* arg: DosTime* */ c = (*field[f].inp)(*b,b); break; case 5: /* date */ b=(unsigned int *)(buf+o+0x18); /* arg: DosDate* */ c = (*field[f].inp)(*b,b); break; } /* deal with key returned from functions */ switch (c) /* convert scancodes to ASCII */ { case RIGHT: /* next field */ case CRIGHT: c = '\t'; break; case SHTAB: /* previous field */ case CLEFT: case LEFT: c = 0x7f; break; case DOWN: /* next entry */ c = '\r'; break; case UP: /* previous entry */ c = '\b'; break; default: c &= 0xff; /* convert to ASCII */ break; } /* ASCII */ switch (c) { case 0x7f: /* previous field */ if (f > 0) p = field[--f].beg; break; case '\t': /* next field */ if (f < NUMFIELDS) p = field[++f].beg; break; case '\r': case ' ': /* next entry */ if (i == LASTENTRY) /* if at end */ { /* wrap */ i = 0; print("\n\n %s",dir_header); /* redisplay header */ } else i++; continue; /* redisplay entry */ break; case '\b': /* previous entry */ if (i == 0) /* if at beginning */ { /* wrap */ i = LASTENTRY; print("\n\n %s",dir_header); /* redisplay header */ } else i--; continue; break; case '=': /* select entry */ output(c); if (getnum(sec_size/sizeof(dDIR),&n,10) > 0 && n > 0) i = n-1; continue; break; case '/': case '?': print("\n\n\tCR/SP next file"); print("\n\tBS previous file"); print("\n\tTAB next field"); print("\n\tSHTAB previous field"); print("\n\t=n goto file n"); print("\n\t'C' goto filename"); print("\n\t.|ESC exit\n"); continue; break; case '.': case ESC: output('\n'); return 0; break; default: if (isalnum(c)) /* letter? */ { int j; c = toupper(c); for (j = i+1; ;j++) { if (j > LASTENTRY) j = 0; if (*(buf+(j*sizeof(dDIR))) == c) break; if (j == i) break; } if (j != i) { i = j; continue; } } break; } goto get; } } static int command(int c) { int i; i = scankey(); if (c < 1 && (i==RIGHT || i==TAB)) i = 0; return i; } /*** *text() -- edit a text entry (filename/ext) * * can enter ALL printable characters including '.' and ' ' ****/ static int text(int len, unsigned char *buf) { int c; int i; for (i=0;;) { c=scankey(); if (c==RIGHT) { if (i==len-1) break; curright(); ++i; continue; } if (c==LEFT || c==BACKSP) { if (!i) break; --i; curleft(); continue; } if (c==RETURN || c==TAB || c==SHTAB || c==DOWN || c==UP) break; if (c==ESCAPE) return(0); if (c>0x352f) continue; c&=0xff; if (isgraph(c) || isexten(c)) { *(buf+i)=(char)c; i++; output(c); if (i==len) { c=RIGHT; break; } } } return(c); } /*** *attrib() - toggle filename attributes, except for dir * ****/ static int attrib(unsigned char *buf) { int i; int b,c,p,d; byte isvol; /* 01234 */ /* RHSDA */ isvol = (byte)(*buf&8); b=d=p=0; /* no need to set d,b but it gets rid of */ /* MSC warning C4701 */ for (;;) { i=scankey(); if (i==RETURN || i==TAB || i==SHTAB || i==DOWN || i==UP) break; if (i==ESCAPE) { i=0; break; } if (i==RIGHT) { if (p==4) /* end */ break; curright(); ++p; continue; } if (i==LEFT || i==BACKSP) { if (p==0) break; --p; curleft(); continue; } if ( !isvol && p!=3 && (i&0xff)==' ') { if (p==0) { b=1; d='R'; } else if (p==1) { b=2; d='H'; } else if (p==2) { b=4; d='S'; } else if (p==4) { b=0x20; d='A'; } if (*buf&b) { c='_'; *buf&=~b; } else { c=d; *buf|=b; } output(c); curleft(); } } return(i); } static int dostime(DosTime time, DosTime *t) { int i; int h,m,s; unsigned int r,x; int c,p; /* 01234567 */ /* hh:mm:ss */ get_cursor(&r,&x); c = x; /* set starting column */ p = c; /* set the working column pointer */ h = time.hours; /* set the working values */ m = time.minutes; s = time.seconds; for (;;) { set_cursor(r,p); i=scankey(); if (i==TAB || i==RETURN || i==SHTAB || i==DOWN || i==UP) return(i); if (i==ESCAPE) { i=0; break; } if (i==LEFT || i==BACKSP) { if (p==c && i==LEFT) return(i); if (p==c && i==BACKSP) continue; if (p==c+3 || p==c+6) p-=2; else p--; continue; } right: if (i==RIGHT) { if (p==c+7) return(i); if (p==c+1 || p==c+4) p+=2; else p++; continue; } i&=0xff; if (isdigit(i)) { output(i); i=i-'0'; /* convert ascii to bin */ /* based on column, */ /* calculate new time with the */ /* number input */ if (p==c) h=(i*10)+(h%10); else if (p==c+1) h=i+((h/10)*10); else if (p==c+3) m=(i*10)+(m%10); else if (p==c+4) m=i+((m/10)*10); else if (p==c+6) s=(i*10)+(s%10); else if (p==c+7) s=i+((s/10)*10); time.hours = h; time.minutes = m; time.seconds = s; *t = time; i = RIGHT; goto right; } } return i; } /*** *dosdate() - edit date field * * ver 1.1 fixed right arrow at last number from wrapping ****/ static int dosdate(DosDate date, DosDate *dt) { int i; int m,d,y; unsigned int r,x; int c,p; /* 01234567 */ /* mm/dd/yy */ get_cursor(&r,&x); c = x; p = c; m = date.month; d = date.day; y = date.year+80; for (;;) { set_cursor(r,p); i=scankey(); if (i==TAB || i==RETURN || i==SHTAB || i==DOWN || i==UP) break; if (i==ESCAPE) return 0; if (i==LEFT || i==BACKSP) { if (p==c && i==LEFT) return(i); if (p==c && i==BACKSP) continue; if (p==c+3 || p==c+6) p-=2; else p--; continue; } right: if (i==RIGHT) { if (p==c+7) continue; if (p==c+1 || p==c+4) p+=2; else p++; continue; } i&=0xff; if (isdigit(i)) { output(i); i=i-'0'; if (p==c) m=(i*10)+(m%10); else if (p==c+1) m=i+((m/10)*10); else if (p==c+3) d=(i*10)+(d%10); else if (p==c+4) d=i+((d/10)*10); else if (p==c+6) y=(i*10)+(y%10); else if (p==c+7) y=i+((y/10)*10); if (y>80) y-=80; else y=0; date.month = m; date.day = d; date.year = y; y += 80; *dt = date; i=RIGHT; goto right; } } return i; } /*** *pdirent() - print directory entry * * Returns: 0 unused, 1 normal, -1 for directory or erased * * 1.2 11/12/94 references a dDIR structure, can't edit '.' dirs * v1.1 removed superfluous pointer ****/ static int pdirent(dDIR *dir) { int i,r; unsigned char c; r = 1; if (dir->name[0] == 0) { print(" unused"); r = 0; } else { /* set can't edit return flag */ if (dir->name[0] == 0xE5 || dir->name[0] == '.') r = -1; /* check for bad chars in case and non-dir sector is displayed */ for (i = 0; i < 8; i++) { c = dir->name[i]; if (isspace((int)c) || c==255 || !c || c==7 || c==8) output(' '); else output(c); } output('.'); for (i = 0; i < 3; i++) { c = dir->ext[i]; if (isspace((int)c) || c==255 || !c || c==7 || c==8) output(' '); else output(c); } print(" "); if (dir->attr.volume) print(" Vol "); else { output(dir->attr.rdonly ? 'R' : '_'); output(dir->attr.hidden ? 'H' : '_'); output(dir->attr.system ? 'S' : '_'); output(dir->attr.subdir ? 'D' : '_'); output(dir->attr.archiv ? 'A' : '_'); } print(" %02d:%02d:%02d",dir->time.hours,dir->time.minutes,dir->time.seconds); print(" %02d/%02d/%02d",dir->date.month,dir->date.day,dir->date.year+80); print(" % 7u",dir->start); if (!dir->attr.subdir) print(" % 7lu",dir->size); } return r; }