#include "tx.h" #include char *FName[MAX_FILES_IN_DIR] ; int num; void TxDir(void) { struct ffblk FFind ; int i,j,selection,memidx=0,baddrv=0 ; int row,col,oldrive,DosDrives,DrivesShown=0 ; char *TextInWindow , *TextInLine, NameSel[15], NewPath[MAXPATH] ; char *FMem[1+(MAX_FILES_IN_DIR/40)]; void krqsort (int,int); int ShowFiles(void) ; void AppendStars(char *) ; /* apppend *.* to path */ int StripStars(char *) ; int DriveExists[26]; void TestDrives(int *,int *,int *); extern void DrawFrame(int,int,int,int,int); oldrive = CurrDrive ; strcpy(NewPath,Path) ; AppendStars(NewPath) ; for (i=0;i<26;i++) /* Initialize */ DriveExists[i]=0; TestDrives(DriveExists,&DosDrives,&DrivesShown); --DrivesShown; row = wherey() ; col = wherex() ; /* Save cursor position */ _setcursortype(_NOCURSOR) ; /* Hide cursor */ TextInWindow = malloc(757); gettext(3,3,20,23,TextInWindow); TextInLine = malloc(161); gettext(1,2,80,2,TextInLine); window(3,3,20,23) ; /* L T R B */ clrscr() ; /* Clear text in window area */ window(1,1,80,25) ; /* But work in absolute coordinates */ DrawFrame(3,3,20,23,0) ; /* Draw window frame (single) */ do { /* Start of main loop */ if ( DrivesShown ) FName[0]=FMem[0]=malloc(5*DrivesShown); for ( i=1 ; i < DrivesShown ; i++ ) FName[i] = FName[i-1] + 5 ; for ( i=0,j=0 ; i < DrivesShown ; i++ ) { strcpy(FName[i],"") ; for ( ; (!DriveExists[i+j])||((i+j)==CurrDrive) ; j++) ; *(FName[i]+1) = i + j + 'A' ; } /* Start mem index at 0 if only 1 drive, 1 otherwise */ memidx = DrivesShown ? 1 : 0 ; i = findfirst(NewPath,&FFind,FA_DIREC) ; for ( num=DrivesShown ; (i==0) && (num < MAX_FILES_IN_DIR) ; num++ ) { if ( ( (num-DrivesShown) % 40) == 0 ) { FName[num] = FMem[memidx++] = malloc(600); for ( j = 1 ; j < 40 ; j++ ) FName[num+j] = FName[num] + (j * 15) ; } if ( FFind.ff_attrib & FA_DIREC ) { *(FName[num]) = '[' ; /* Enclose directories in brackets */ strcpy(FName[num]+1,FFind.ff_name) ; strcat(FName[num],"]") ; } else strcpy(FName[num],FFind.ff_name) ; i = findnext(&FFind) ; } /* num contains number of files in directory + actual logical drives */ /* memidx contains de number of times malloc has been called */ /* We now have all names in FName. Drives are enclosed in <> and directories in []. Drives are already ordered, so we may forget about them. Directories and files will be sorted separately, namely, the [ will precede other characters in the lexicographic order we use. To help avoiding problems in case of a future change, we also make < the character with the highest precedence. */ /* Sorting procedure borrowed from K&R */ krqsort(DrivesShown,num-1); puttext(1,2,80,2,TextInLine) ; gotoxy(4,2) ; cputs(NewPath) ; if ( (selection = ShowFiles()) == -1 ) break ; strcpy(NameSel,FName[selection]) ; for ( j=0 ; j < memidx ; j++ ) free(FMem[j]) ; if (!( ( *NameSel == '[' ) || ( *NameSel == '<' )) ) break ; /* A file has been selected */ if (!strcmp(NameSel,"[.]") ) /* current directory */ continue ; /* reread current directory */ i = StripStars(NewPath) ; if ( !strcmp(NameSel,"[..]") ) { /* parent directory */ for (; (i-3) && (NewPath[i] != BACKSLASH );i-- ) ; NewPath[i] = '\0' ; chdir(NewPath) ; } else if ( *NameSel == '[' ) { /* Another directory */ if ( i-3 ) NewPath[i++] = BACKSLASH ; for (j=0 ; (NewPath[i]=NameSel[++j])!=']';i++); NewPath[i]='\0' ; /* get rid of terminating ] */ chdir(NewPath) ; } else { /* Now NameSel[0] equals '<', so we change drive */ CurrDrive = ( (int) NameSel[1] ) - 'A' ; setdisk(CurrDrive) ; /* set disk */ NewPath[0]='\0'; if ( getcwd(NewPath,MAXPATH)==NULL ) { baddrv = 1 ; selection = -1 ; break; } } AppendStars(NewPath) ; } while (1) ; /* End of main loop */ /* Restore settings */ puttext(3,3,20,23,TextInWindow) ; free(TextInWindow) ; puttext(1,2,80,2,TextInLine) ; free(TextInLine) ; _setcursortype(_NORMALCURSOR) ; /* show cursor */ gotoxy(col,row) ; /* restore cursor position */ if (selection == -1 ) { /* Leave everything as before */ if ( !baddrv ) for ( j=0 ; j < memidx ; j++ ) free(FMem[j]) ; setdisk(oldrive) ; CurrDrive = oldrive ; chdir(Path) ; return ; } i=StripStars(NewPath) ; strcpy(Path,NewPath) ; if ( Path[--i] != BACKSLASH ) Path[++i] = BACKSLASH; for (j=0 ; ( Path[++i] = NameSel[j++] ) ; ); SplitPath(); } int ShowFiles(void) { int i,j,init=0,last ; int previous=0, current = 0 ; while ( previous != -1 ) { previous = 0 ; last = ( init + 19 < num ) ? init + 18 : num - 1 ; window(5,4,18,22) ; clrscr() ; window(1,1,80,25) ; for ( i = init ; i <= last ; i++ ) { gotoxy(5,4+(i-init)) ; cputs(FName[i]) ; } while ( previous >= 0 ) { while (1) { /* Highlight currently selected entry */ textattr(color[(previous == current)]) ; gotoxy(5,4+previous) ; cputs(FName[init+previous]) ; j = 14 - strlen(FName[init+previous]) ; while ( j-- ) putch(' ') ; if ( previous == current ) break ; previous = current ; } textattr(color[0]) ; i = getch(); /* Read character from keyboard */ if ( i == 0 ) { /* If extended character */ i = getch() ; /* Get character */ i *= -1 ; /* Make it different from regular ascii */ } switch ( i ) { case CR : previous = -1 ; /* Choose current entry */ break ; case HOMEKEY : if ( init > 0 ) { init = 0 ; previous = -2 ; } current = 0 ; /* Go to first entry */ break ; case ENDKEY : last = num-1 ; /* Go to last entry */ previous = -2 ; init = ( num > 18 ) ? last - 18 : 0 ; current = last - init ; break ; case UPKEY : case LEFTKEY : if ( current ) --current ; /* Move up one position */ else if (init) { --init ; /* Scroll back one position */ previous = -2 ; } break ; case DOWNKEY : case RIGHTKEY : if ( init+current < last ) ++current ; /* Move down one position */ else if ( last+1 < num ) { ++init ; /* Scroll forward one position */ previous = -2 ; } break ; case PGUPKEY : if (init==0) current = 0; else if (init > 17 ) { init -= 18 ; /* current = 18 ; Leave current as it is now */ previous = -2 ; } else { current = init ; init = 0 ; previous = -2 ; } break ; case PGDNKEY : if ( last+1 >= num ) current = last - init ; else { init = last ; if ( last + current > num - 1 ) current = num - (last+1) ; previous = -2 ; } break ; default : previous = -1 ; current = -1 ; break ; } /* switch (i) */ } /* while (previous >= 0) */ } /* while (previous != -1) */ if ( current == -1 ) return -1 ; else return init+current ; } void krqsort (int krleft, int krright) { int kri,krlast; void krswap(int,int) ; int krcomp(char *,char *); if (krleft >= krright ) return; krswap(krleft,(krleft+krright)/2); krlast=krleft; for (kri=krleft+1;kri<=krright;kri++) if (krcomp(FName[kri],FName[krleft])<0) krswap(++krlast,kri); krswap(krleft,krlast); krqsort(krleft,krlast-1); krqsort(krlast+1,krright); } void krswap(int ki,int kj) { char *temp; temp=FName[ki]; FName[ki]=FName[kj];FName[kj]=temp; } /* Lexicographical comparison, but giving priority to the drive symbols "<" and to the directory symbols "[". */ int krcomp(char *a, char *b) { for ( ; *a == *b ; a++, b++ ) if ( *a == '\0' ) return 0 ; if ( *a == '<' ) return -1 ; else if ( *b == '<' ) return 1 ; else if ( *a == '[' ) return -1 ; else if ( *b == '[' ) return 1 ; else return *a - *b ; } void TestDrives(int *DriveExists,int *DosDrives, int *ValidDrives) { int i; union REGS r; *DosDrives=setdisk(CurrDrive); *ValidDrives=0; for ( i=0; i< *DosDrives; i++) { setdisk(i); DriveExists[i] = ( i == getdisk() ) ; if (DriveExists[i]) { r.x.ax = 0x440E; r.x.bx = 0; intdos(&r,&r); if ((!( r.x.flags & 1 )) && (r.x.ax & 0xFF)&& (r.x.ax & 0xFF) != i+1 ) DriveExists[i]= 0; /* Drive already referenced */ } *ValidDrives += DriveExists[i]; } setdisk(CurrDrive) ; /* Restore current disk after tests */ } void AppendStars(char *Pname) { for (; *Pname ; Pname++) ; /* go to end of string */ if (*--Pname != BACKSLASH ) /* make sure last char is a backslash */ *++Pname = BACKSLASH ; *++Pname = '*' ; *++Pname = '.' ; *++Pname = '*' ; *++Pname = '\0' ; } int StripStars(char *Pname) { int i; for (i=0; *Pname!='*' ; i++,Pname++) ; --Pname; /* Point to backslash */ if (*--Pname == ':' && ++i ) ++Pname; *++Pname = '\0' ; return --i; }