home *** CD-ROM | disk | FTP | other *** search
- /*
- * A TSR file browser
- *
- * Copyright 1993-1994 Dave Dunfield
- * All rights reserved.
- *
- * Permission granted for personal (non-commercial) use only.
- *
- * Compile command: cc tfb -fop
- */
- #include <stdio.h>
- #include <window.h>
- #include <tsr.h>
-
- #define SCREEN_SIZE 80 /* Width of screen */
- #define LINE_SIZE 250 /* Maximum width of input line */
- #define NUM_TAGS 10 /* Maximum number of tag locations */
- #define NUM_FILES 10 /* Maximum number of pick files */
-
- int tab_size = 8, line, lcount, offset, tag, file, fnext = 0,
- file_info[NUM_FILES][NUM_TAGS+4], Msel, Mval[NUM_FILES];
-
- unsigned sizeh, sizel, maxline, lines[2048][2], tags[NUM_TAGS];
-
- char filename[NUM_FILES][51], search_string[NUM_FILES][51], *Mptr[NUM_FILES+1],
- *argptr = 0;
-
- struct WINDOW *mwin;
-
- FILE *fp = 0;
-
- /* Window video attributes */
- int attrs[] = {
- WSAVE|WCOPEN|0x70, /* 0: Message window */
- WSAVE|WCOPEN|0x07, /* 1: Main screen */
- WSAVE|WBOX1|WCOPEN|0x70 /* 2: Info entry */
- };
-
- /* Form for entering filename */
- char *form1[] = {
- 64<<8|3,
- "\x00\x00\x32Filename:",
- 0 };
-
- /* Form for setting tab size */
- char *form2[] = {
- 30<<8|3,
- "\x00\x00\x85Tab size:",
- 0 };
-
- /* Form for selecting line number */
- char *form3[] = {
- 30<<8|3,
- "\x00\x00\x85Line number:",
- 0 };
-
- /* Form for string searches */
- char *form4[] = {
- 64<<8|3,
- "\x00\x00\x32Search for:",
- 0 };
-
- /* Welcome message */
- char hello[] =
- "TFB [/ACLRS] [file] - Copyright 1993-1994 Dave Dunfield. All rights reserved.";
- /*
- * Main file browser program
- */
- browser()
- {
- int i, x;
- char buffer[LINE_SIZE+1];
-
- mwin = wopen(0, 0, 80, 1, attrs[0]);
- wputs(hello);
- wopen(0, 1, 80, 24, attrs[1]);
- wcursor_off();
-
- /* If file already active... reopen */
- if(fnext) {
- if(!(fp = fopen(filename[file], "rb")))
- fnext = 0; }
-
- /* If no file open... prompt for one. */
- if(!fnext) {
- *buffer = 0;
- do {
- if(argptr) {
- strcpy(buffer, argptr);
- argptr = 0; }
- else if(wform(7, 10, attrs[2], form1, buffer))
- *buffer = 0;
- if(!*buffer) {
- wclose();
- wclose();
- return; } }
- while(!open_file(buffer));
- strcpy(filename[file = fnext++], buffer); }
-
- /* Display screen from file */
- display:
- if(line > (lcount - 23)) line = lcount - 23;
- if(line < 0) line = 0;
- if(offset < 0) offset = 0;
- update_status();
- gotoline(line);
- for(i=0; i < 24; ++i) {
- wgotoxy(0, i);
- if(fgets(buffer, sizeof(buffer)-1, fp))
- display_line(buffer);
- if((line + i) == lcount) {
- *W_OPEN = 0x70;
- wputs(" End of file ");
- *W_OPEN = attrs[1];
- wcleow();
- break; } }
-
- /* Get and process command character */
- command:
- switch(x = wgetc()) {
- case _KUA : /* Backup one line */
- --line;
- goto display;
- case _KDA : /* Advance one line */
- ++line;
- goto display;
- case _KPU : /* Backup one page */
- line -= 23;
- goto display;
- case _KPD : /* Advance one page */
- line += 23;
- goto display;
- case _CPU : /* Go to start of file */
- line = 0;
- goto display;
- case _CPD : /* Go to end of file */
- line = 32767;
- goto display;
- case _KRA : /* Advance one column */
- ++offset;
- goto display;
- case _KLA : /* Backup one column */
- --offset;
- goto display;
- case _KEN : /* Advance 20 columns */
- offset += 20;
- goto display;
- case _KHO : /* Backup 20 columns */
- offset -= 20;
- goto display;
- case _CHO : /* Reset to 1st column */
- offset = 0;
- goto display;
- case _K1 : /* Display Fkey help */
- w_clwin(mwin);
- w_puts("1:Help 2:Goto 3:Search 4:Again 5:Gotag 6:Setag 7:Tabsize 8:Colors 9:File 10:Pick", mwin);
- goto command;
- case _K2 : /* Goto line number */
- x = line+1;
- if(!wform(20, 10, attrs[2], form3, &x))
- line = x - 1;
- goto display;
- case _K3 : /* Initial Search */
- if(!wform(7, 10, attrs[2], form4, search_string[file])
- && search(search_string[file], line))
- goto display;
- goto command;
- case _K4 : /* Repeat Search */
- if(search(search_string[file], line+1))
- goto display;
- goto command;
- case _K5 : /* Move to tag */
- if((!tag_menu(15, 8)) && tags[tag])
- line = tags[tag] - 1;
- goto display;
- case _K6 : /* Set tag */
- if(!tag_menu(55, 8))
- tags[tag] = line + 1;
- goto command;
- case _K7 : /* Set TAB size */
- x = tab_size;
- if(!wform(20, 10, attrs[2], form2, &x))
- tab_size = x ? x : 1;
- goto display;
- case _K8 :
- colors();
- goto display;
- case _K9 : /* Browse another file */
- *buffer = 0;
- if(!wform(7, 10, attrs[2], form1, buffer)) {
- save_info();
- if(open_file(buffer)) {
- strcpy(filename[file = fnext++ % NUM_FILES], buffer);
- goto display; } }
- goto command;
- case _K10 : /* Pick a previously opened file */
- for(i=Msel=x=0; i < NUM_FILES; ++i) {
- if(*filename[i]) {
- if(i == file)
- Msel = x;
- Mptr[x] = filename[i];
- Mval[x++] = i; } }
- Mptr[x] = 0;
- if(!wmenu(15, 8, attrs[2], Mptr, &Msel)) {
- save_info();
- if(open_file(filename[Msel])) {
- file = Msel;
- restore_info();
- goto display; } }
- goto command;
- case 0x1B : /* exit */
- save_info();
- fclose(fp);
- wclose();
- wclose();
- return; }
-
- /* Command key not recognized... */
- wputc(7);
- goto command;
- }
-
- /*
- * Open and index a file
- */
- open_file(name)
- char *name;
- {
- int c;
-
- /* Attempt to open the file - report if failure */
- if(!(c = fopen(name, "rb"))) {
- w_clwin(mwin);
- w_printf(mwin,"Unable to access: '%s'", name);
- return 0; }
-
- w_clwin(mwin);
- w_printf(mwin,"Indexing '%s'...", name);
-
- /* Close previously open file (if any) */
- if(fp)
- fclose(fp);
- fp = c;
-
- /* Reset viewer file control variables */
- sizeh = sizel = maxline = lcount = line = offset = tag = 0;
- for(c=0; c < NUM_TAGS; ++c)
- tags[c] = 0;
-
- /* Build table of line numbers .vs. file offsets */
- while((c = getc(fp)) != EOF) {
- if(!++sizel)
- ++sizeh;
- if(c == '\n') {
- /* if(!++sizel)
- ++sizeh; */
- if(!(++lcount & 0x1F)) {
- lines[maxline][0] = sizel;
- lines[maxline++][1] = sizeh; } } }
-
- return -1;
- }
-
- /*
- * Display status in the message window
- */
- update_status()
- {
- w_gotoxy(0, 0, mwin);
- w_printf(mwin,"%-50s Line: %u of %u, Col: %u", filename[file], line+1, lcount, offset+1);
- w_cleow(mwin);
- }
-
- /*
- * Position file to line 'n'
- */
- gotoline(line)
- unsigned line;
- {
- int c, i;
-
- rewind(fp);
-
- /* If more than 32 lines... seek to it */
- if(i = line >> 5) {
- --i;
- fseek(fp, lines[i][1], lines[i][0], 0); }
-
- /* Read till we get to exact line */
- i = line & 0x1F;
- while(i) {
- if((c = getc(fp)) == EOF)
- return -1;
- if(c == '\n')
- --i; }
-
- return 0;
- }
-
- /*
- * Display a line with tabs expanded
- */
- display_line(text)
- char *text;
- {
- int p, o;
- unsigned char c;
-
- o = offset + SCREEN_SIZE;
- p = 0;
- while((c = *text++) && (p < o)) {
- if(c == '\t') { /* tab */
- do
- if(p >= offset)
- wputc(' ');
- while(++p % tab_size); }
- else if(c != '\r') { /* not a tab */
- if(++p > offset) {
- if(c < ' ') { /* Control character */
- *W_OPEN = 0x70;
- wputc(c + 0x40);
- *W_OPEN = attrs[1];
- continue; }
- wputc((c <= '~') ? c : 0xFE); } } }
- if(p < o)
- wcleol();
- }
-
- /*
- * Search for string in file
- */
- search(string, l)
- char *string;
- int l;
- {
- char buffer[LINE_SIZE+1];
-
- w_clwin(mwin);
- w_printf(mwin, "Searching from line %u for '%s'... ", l+1, string);
- gotoline(l);
- while(fgets(buffer, sizeof(buffer)-1, fp)) {
- if(inline(buffer, string)) {
- line = l;
- return -1; }
- ++l; }
- w_printf(mwin, "Not found!", string);
- return 0;
- }
-
- /*
- * Test for string occuring within a line.
- * We could easily do this in 'C', however its a good chance to show
- * off inline assembly language, and get a slight speed improvement.
- */
- inline(line, string) asm
- {
- MOV SI,6[BP] ; Get line
- inl1: MOV DI,4[BP] ; Get string
- inl2: MOV AL,[DI] ; Get char from string
- MOV AH,[SI] ; Get char from line
- AND AL,AL ; End of string?
- JZ inl3 ; Yes, we have match
- INC SI ; Advance line
- INC DI ; Advance string
- CMP AL,AH ; *line == *string?
- JZ inl2 ; Yes, keep looking
- AND AH,AH ; End of string?
- JNZ inl1 ; No, keep trying
- ; End of line... string was not found
- XOR AX,AX ; 0 = Not found
- JMP SHORT inl4 ; And exit
- ; Found string
- inl3: MOV AX,-1 ; 1 = Success
- inl4:
- }
-
- /*
- * Save viewer information for current file.
- */
- save_info()
- {
- int i, *ptr;
- ptr = file_info[file];
- *ptr = line;
- *++ptr = offset;
- *++ptr = tab_size;
- *++ptr = tag;
- for(i=0; i < NUM_TAGS; ++i)
- *++ptr = tags[i];
- }
-
- /*
- * Reload viewer information for current file.
- */
- restore_info()
- {
- int i, *ptr;
- ptr = file_info[file];
- line = *ptr;
- offset = *++ptr;
- tab_size = *++ptr;
- tag = *++ptr;
- for(i=0; i < NUM_TAGS; ++i)
- tags[i] = *++ptr;
- }
-
- /*
- * Build and perform a menu of tag line numbers.
- */
- tag_menu(x, y)
- int x, y;
- {
- int i;
- char *tagnames[NUM_TAGS+1], text[NUM_TAGS][6];
- for(i=0; i < NUM_TAGS; ++i) {
- if(tags[i])
- sprintf(tagnames[i] = text[i], "%u", tags[i]);
- else
- tagnames[i] = "-----"; }
- tagnames[NUM_TAGS] = 0;
- return wmenu(x, y, attrs[2], tagnames, &tag);
- }
-
- /*
- * Set window colors
- */
- colors()
- {
- int num, color, f, b;
- static char *cnames[] = {
- "Message line",
- "Main screen",
- "Pop up windows" };
-
- num = 0;
- for(;;) {
- color = attrs[num];
- f = color & 0x0F;
- b = color & 0xF0;
- wopen(20, 9, 32, 7, (WSAVE|WCOPEN|WBOX2)|(color & 0xFF));
- wcursor_off();
- *W_OPEN = (f << 4) | (b >> 4);
- wputs(cnames[num]);
- *W_OPEN = color;
- wputs("\n\nUp/Down = Change forground\n");
- wputs("Left/Right = Change background\n");
- wputs("PgUp/PgDn = Change screen");
- switch(wgetc()) {
- case 0x1B :
- wclose();
- *mwin = attrs[0];
- *W_OPEN = attrs[1];
- return;
- case _KPU : num = (num + 1) % 3; break;
- case _KPD : num = (num + 2) % 3; break;
- case _KUA : ++f; goto setcolor;
- case _KDA : --f; goto setcolor;
- case _KRA : b += 16; goto setcolor;
- case _KLA : b -= 16;
- setcolor:
- attrs[num] = (color & 0xFF00) | (f & 0x0f) | (b & 0xF0);
- default: }
- wclose(); }
- }
-
- /*
- * Main program - parse arguments, and start browser (if not TSR).
- */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int i;
-
- /* At startup, zero filenames & search strings */
- for(i=0; i < NUM_FILES; ++i)
- *filename[i] = *search_string[i] = 0;
-
- /* If not TSR, activate browser now */
- if((argc < 2) || (*(argptr = argv[1]) != '/')) {
- browser();
- return; }
-
- /* TSR... parse hotkeys & set TSR vectors */
- i = 0;
- while(*++argptr) switch(toupper(*argptr)) {
- case 'A' : i |= ALT; break;
- case 'C' : i |= CONTROL; break;
- case 'L' : i |= L_SHIFT; break;
- case 'R' : i |= R_SHIFT; break;
- case 'S' : i |= SYS_REQ; break;
- default: abort("\nInvalid HOTKEY"); }
- argptr = (argc > 2) ? argv[2] : 0;
- tsr(&browser, i, 10000);
- }
-