home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
d
/
dec92.zip
/
BROW.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-13
|
16KB
|
604 lines
/*
* brow.c - file browser, virtual display output
* Bob Bybee, 3/22/91
*/
#include <ssdef.h>
#include <stdio.h>
#include <descrip.h>
#include <smgdef.h>
#include <stat.h>
#include <time.h>
#include "vaxkeys.h"
int kb_id, pb_id, output_device, pb_rows, pb_cols;
int top_disp_id, bot_disp_id, main_disp_id;
int vid_attr, main_size;
int one = 1, two = 2, ins_dir;
int top_line = 0;
int tabsize = 8;
int found_line = -1;
char ftimebuf[80];
FILE *fp;
char filename[80];
#define INPUT_BUFSIZE 60
char inputbuf[INPUT_BUFSIZE + 1];
char searchbuf[INPUT_BUFSIZE + 1];
int input_bufsize = INPUT_BUFSIZE;
int inputlen, searchlen;
#define MAX_LINES 10000
#define MAX_LINE_LENGTH 150
char *pointers[MAX_LINES];
int lastline;
/* prototypes
*/
void help_info( void );
void repaint_page( void );
void show_lineno( void );
void bottom_line( char *msg );
void get_line( int lineno, char *buf );
void testret( int where, int ret );
int getkey( void );
void getline( char *prompt );
void string_to_des( char *buf, struct dsc$descriptor *dp );
void snuff_nl( char *buf );
void filetime( FILE *fp, char *buf );
void tabex( char *buf );
void get_pointers( void );
void strupr( char *s );
int main( int argc, char **argv )
{
int c, i = 0, ret, row, col, how_far_in, how_far_down;
int found_it, rendition, first_search, case_insens = 0;
struct dsc$descriptor des;
char buf[MAX_LINE_LENGTH], orig_buf[MAX_LINE_LENGTH], *p;
--argc, ++argv;
if (argc != 1)
{
printf("Usage: brow <filename>\n");
exit(1);
}
if ((fp = fopen(*argv, "r")) == NULL)
{
printf("Can't open file: %s\n", *argv);
exit(1);
}
filetime(fp, ftimebuf);
strcpy(filename, *argv);
filename[sizeof(filename) - 1] = '\0';
get_pointers();
testret(1, SMG$CREATE_VIRTUAL_KEYBOARD(&kb_id));
testret(2, SMG$CREATE_PASTEBOARD(&pb_id,
NULL, &pb_rows, &pb_cols));
vid_attr = SMG$M_REVERSE;
testret(3, SMG$CREATE_VIRTUAL_DISPLAY(&one, &pb_cols,
&top_disp_id, 0, &vid_attr));
testret(4, SMG$CREATE_VIRTUAL_DISPLAY(&one, &pb_cols,
&bot_disp_id, 0, &vid_attr));
vid_attr = 0;
main_size = pb_rows - 2;
testret(5, SMG$CREATE_VIRTUAL_DISPLAY(&main_size, &pb_cols,
&main_disp_id, 0, &vid_attr));
testret(6, SMG$PASTE_VIRTUAL_DISPLAY(&top_disp_id,
&pb_id, &one, &one));
testret(7, SMG$PASTE_VIRTUAL_DISPLAY(&bot_disp_id,
&pb_id, &pb_rows, &one));
testret(8, SMG$PASTE_VIRTUAL_DISPLAY(&main_disp_id,
&pb_id, &two, &one));
top_line = 0;
repaint_page();
while (1)
{
c = getkey();
switch (c)
{
case '?':
help_info();
getkey();
repaint_page();
break;
case DOWN_KEY:
case 'D':
case 'd':
if (top_line + main_size - 1 < lastline)
{
++top_line;
strcpy(buf, pointers[top_line + main_size - 1]);
tabex(buf);
string_to_des(buf, &des);
ins_dir = SMG$M_UP;
testret(10, SMG$INSERT_LINE(&main_disp_id, &main_size,
&des, &ins_dir));
show_lineno();
}
break;
case NEXT_SCREEN_KEY:
case 'N':
case 'n':
case 'N' - '@':
top_line += main_size - 1;
repaint_page();
break;
case UP_KEY:
case 'U':
case 'u':
if (top_line > 0)
{
--top_line;
strcpy(buf, pointers[top_line]);
tabex(buf);
string_to_des(buf, &des);
ins_dir = SMG$M_DOWN;
testret(10, SMG$INSERT_LINE(&main_disp_id, &one,
&des, &ins_dir));
show_lineno();
}
break;
case PREV_SCREEN_KEY:
case 'P':
case 'p':
case 'P' - '@':
top_line -= main_size - 1;
repaint_page();
break;
case 'H':
case 'h':
case 'H' - '@':
top_line = 0;
repaint_page();
break;
case 'E':
case 'e':
case 'E' - '@':
top_line = lastline - (main_size - 1);
repaint_page();
break;
case 'L' - '@':
testret(15, SMG$REPAINT_SCREEN(&pb_id));
break;
case '#':
getline("Go to line: ");
if (sscanf(inputbuf, "%d", &top_line) == 1)
{
--top_line; /* make it 0-based */
repaint_page();
}
break;
case 'I' - '@':
getline("New tab size: ");
if (sscanf(inputbuf, "%d", &tabsize) == 1)
repaint_page();
break;
case PF3_KEY:
if (found_line < 0)
bottom_line("No previous search string.");
else
{
first_search = found_line + 1;
goto continue_search;
}
break;
case '\\':
case_insens = 1;
goto ask_search;
case '/':
case FIND_KEY:
case_insens = 0;
ask_search:
getline("Search for: ");
if (inputlen == 0)
break;
strcpy(searchbuf, inputbuf);
if (case_insens)
strupr(searchbuf);
searchlen = inputlen;
first_search = top_line;
continue_search:
found_it = 0;
for (i = first_search; !found_it && i <= lastline; ++i)
{
strcpy(buf, pointers[i]);
tabex(buf);
if (case_insens)
{
strcpy(orig_buf, buf);
strupr(buf);
}
if ((p = strstr(buf, searchbuf)) != NULL)
{
/* found it. center the display on that string.
* make how_far_in, how_far_down the 1-based
* screen coords of the string on the screen.
*/
how_far_in = p - buf + 1;
top_line = i - main_size / 2;
repaint_page();
how_far_down = i - top_line + 1;
rendition = SMG$M_REVERSE;
if (case_insens)
strcpy(buf, orig_buf); /* replace orig buffer */
p[searchlen] = '\0';
string_to_des(p, &des);
testret(14, SMG$PUT_CHARS(&main_disp_id, &des,
&how_far_down, &how_far_in,
0, &rendition));
show_lineno(); /* move cursor to bottom line */
found_it = 1;
found_line = i;
}
}
if (!found_it)
bottom_line("Not found.");
break;
case 'Q':
case 'q':
case 'Q' - '@':
case 'X':
case 'x':
case 'X' - '@':
show_lineno(); /* put cursor on bottom line */
printf("\n\n");
exit(0);
break;
default:
break;
}
}
return (1);
}
/*
* Display help-screen.
*/
void help_info( void )
{
int i, y;
char **pp;
struct dsc$descriptor des;
static char *help_msgs[] =
{
" ",
" BROWSE version 1.0 3/26/91",
" ",
" H: home (top of file) /, FIND: locate text string",
" E: end (bottom of file) \\: locate (case insensitive)",
" U, up-arrow: up one line PF3: continue search",
" P, prev-screen: up one screen",
" D, down-arrow: down one line",
" N, next-screen: down one screen",
" ",
" #: go to a line # ^L: repaint screen",
" TAB: change tab-size setting",
" Q, X: quit",
" ",
" hit any key to continue...",
NULL
};
/* batch up the following stuff.
*/
SMG$BEGIN_PASTEBOARD_UPDATE(&pb_id);
SMG$SET_CURSOR_ABS(&main_disp_id, &one, &one);
for (pp = help_msgs, y = 1, i = 0; i < main_size; ++i, ++y)
{
if (*pp != NULL)
{
string_to_des(*pp, &des);
++pp;
}
else
string_to_des(" ", &des);
testret(11, SMG$PUT_LINE(&main_disp_id, &des));
}
/* end batching.
*/
SMG$END_PASTEBOARD_UPDATE(&pb_id);
}
/*
* Get an input line, prompting on the bottom line of the screen.
* Put result in inputbuf, length in inputlen.
*/
void getline( char *prompt )
{
struct dsc$descriptor result_des, prompt_des;
int modifiers = 0;
short result_len;
string_to_des(prompt, &prompt_des);
result_des.dsc$w_length = INPUT_BUFSIZE;
result_des.dsc$a_pointer = inputbuf;
result_des.dsc$b_class = DSC$K_CLASS_S;
result_des.dsc$b_dtype = DSC$K_DTYPE_T;
SMG$READ_STRING(&kb_id,
&result_des,
&prompt_des,
&input_bufsize,
&modifiers,
0, /* timeout */
0, /* terminator set */
&result_len,
0, /* word terminator code */
&bot_disp_id);
inputbuf[result_len] = '\0';
inputlen = result_len;
show_lineno(); /* fix the bottom line of the screen */
}
/*
* Repaint the screen, given the current value of top_line.
*/
void repaint_page( void )
{
int i, y, bot_line;
struct dsc$descriptor des;
char buf[MAX_LINE_LENGTH];
/* sanity-check the top_line variable.
*/
if (top_line + main_size - 1 > lastline)
top_line = lastline - (main_size - 1);
if (top_line < 0)
top_line = 0;
/* batch up the following stuff.
*/
SMG$BEGIN_PASTEBOARD_UPDATE(&pb_id);
/* label the top line with the file time/date.
*/
sprintf(buf, " File: %s %s", filename, ftimebuf);
string_to_des(buf, &des);
testret(9, SMG$PUT_LINE(&top_disp_id, &des));
SMG$SET_CURSOR_ABS(&main_disp_id, &one, &one);
/* put N lines in the main viewing area
*/
bot_line = top_line + main_size - 1;
for (y = 1, i = top_line; i <= bot_line; ++i, ++y)
{
get_line(i, buf);
string_to_des(buf, &des);
testret(11, SMG$PUT_LINE(&main_disp_id, &des));
}
show_lineno();
/* end batching, flush this update to the screen.
*/
SMG$END_PASTEBOARD_UPDATE(&pb_id);
}
/*
* Label the bottom line with current line # and max lines in file.
*/
void show_lineno( void )
{
char buf[80];
struct dsc$descriptor des;
int last_shown;
last_shown = top_line + main_size;
if (last_shown > lastline + 1)
last_shown = lastline + 1;
sprintf(buf, " lines %5d - %5d (of %5d) BROWSE v1.0 ?=help",
top_line + 1, last_shown, lastline + 1);
string_to_des(buf, &des);
testret(12, SMG$PUT_LINE(&bot_disp_id, &des));
}
/*
* Put a message on bottom line of the screen.
*/
void bottom_line( char *msg )
{
struct dsc$descriptor des;
string_to_des(msg, &des);
testret(12, SMG$PUT_LINE(&bot_disp_id, &des));
}
/*
* Get the strings of all lines in the file.
* Set lastline to the last used entry in pointers[].
*/
void get_pointers( void )
{
char *p, buf[MAX_LINE_LENGTH];
while (lastline < MAX_LINES && fgets(buf, MAX_LINE_LENGTH, fp) != NULL)
{
if ((p = malloc(strlen(buf) + 1)) == NULL)
{
printf("Out of memory!\n");
exit(1);
}
strcpy(p, buf);
pointers[lastline++] = p;
}
--lastline;
}
/*
* Return the text corresponding to lineno of the file.
* Tab-expand the text and put it in buf.
*/
void get_line( int lineno, char *buf )
{
int i;
/* if past EOF, return a blank line
*/
if (lineno > lastline)
{
*buf = '\0';
return;
}
strcpy(buf, pointers[lineno]);
tabex(buf);
}
/*
* Tab-expand a buffer, in place.
*/
void tabex( char *buf )
{
char buf2[200], c;
int i = 0, j = 0;
while ((c = buf[i++]) != '\0' && c != '\n')
{
if (c == '\t')
{
do {
buf2[j++] = ' ';
} while (j % tabsize != 0);
}
else
buf2[j++] = c;
}
buf2[j] = '\0';
strcpy(buf, buf2);
}
/*
* Test the return value from a system call,
* error out if not success.
*/
void testret( int where, int ret )
{
if (ret != SS$_NORMAL)
{
printf("Error: where= %d code= %d\n", where, ret);
exit(0);
}
}
/*
* Get one keystroke from kb_id
*/
int getkey( void )
{
short termcode;
SMG$READ_KEYSTROKE(&kb_id, &termcode);
return (termcode);
}
/*
* install character string in a descriptor
*/
void string_to_des( char *buf, struct dsc$descriptor *dp )
{
dp->dsc$w_length = strlen(buf);
dp->dsc$a_pointer = buf;
dp->dsc$b_class = DSC$K_CLASS_S;
dp->dsc$b_dtype = DSC$K_DTYPE_T;
}
/*
* Insert NUL at first control-char in a buffer.
*/
void snuff_nl( char *buf )
{
while (*buf >= ' ')
++buf;
*buf = '\0';
}
/*
* Get file time/date into a string buffer.
*/
void filetime( FILE *fp, char *buf )
{
int fd, r;
time_t bintim;
stat_t statbuf;
struct dsc$descriptor des;
des.dsc$w_length = 23;
des.dsc$a_pointer = buf;
des.dsc$b_class = DSC$K_CLASS_S;
des.dsc$b_dtype = DSC$K_DTYPE_T;
fd = fileno(fp);
if ((r = fstat(fd, &statbuf)) != 0)
{
printf("fstat returned %d\n", r);
exit(1);
}
bintim = statbuf.st_mtime;
strcpy(buf, ctime(&bintim));
snuff_nl(buf);
}
/*
* Convert a string to upper case.
*/
void strupr( char *s )
{
char c;
while ((c = *s) != '\0')
{
if ('a' <= c && c <= 'z')
*s -= 'a' - 'A';
++s;
}
}