Dave:
First, less is now available on most modern $nix systems. From the command line, perform a:
man less
Below is my pgit utility. It was developed for ASCII files greater with lines greater than 80 chars. The pg and more utilities wrap. This one allows the user to move to the right, left, down, and up.
To compile:
cc pgit.c -lcurses -o pgit
This program has been compiled under SCO Open Server, Solaris, and HP-UX. If the curses library isn't installed, obviously, this fails.
If you have problems cutting and pasting this, I'll gladly email it to you.
Let me know if you have any questions.
Regards,
Ed
cut here
/*
progrm name: pgit.c pg/more replacement. view an ascii file
Author: Ed Schaefer
Usage:
pgit <filename> # is NOT a pipe.
To compile:
cc pgit.c -lcurses -o pgit
This is a curses program using a "pad". Some old curses libraries
(such as xenix) may not support the "pad".
This is free software. No warranty is granted or implied. Use at your
own risk or reward.
Instead the keys:
u=scroll up; d=scroll down; l=scroll left=scroll
left; r=scroll right; U=page up; D=page down.
******************************************************************************/
#include <curses.h>
#include <ctype.h>
#include <signal.h>
#define KEY_JUMP 5 /* Number of columns to move with an arrow */
#define PAGE_LEN 66 /* Number of rows in a report page */
#define SCROLL_DOWN 'd' /* Alt Key to scroll down */
#define SCROLL_UP 'u' /* Alt Key to scroll up */
#define SCROLL_RIGHT 'r' /* Alt Key to scroll right */
#define SCROLL_LEFT 'l' /* Key to scroll left */
#define PAGE_UP 'p' /* Key to page up */
#define PAGE_DOWN 'n' /* Key to page down */
#define PAGE_RIGHT 'R' /* Page Right */
#define PAGE_LEFT 'L' /* Page Left */
FILE *in, *fopen();
WINDOW *wpad, *cmdwin, *exewin, *blankit;
void alter();
int x = 114;
int y = 260;
#define YLEN 260
int xpad = 0;
int padptr = 0;
int winwid = 36;
int winlen = 19;
int totlines;
#define is_uppercase(x) ((x >= 'A' && x <= 'Z') ? 1 : 0)
#define to_lowercase(x) ((is_uppercase(x)) ? x + 'a' - 'A' : x)
struct node
{
int padno; /*identify the pad number*/
int nlines; /*number of lines in the pad number*/
long poffset; /*offset into ascii file to read for each pad */
int accum; /*total number of lines in file */
struct node *next, *prev; /*next and previous nodes in linked list*/
};
typedef struct node node_t;
struct head /*header node*/
{
int length; /*current length of list */
/*pointers to first, last, and current elements*/
struct node *first, *last, *current;
};
typedef struct head head_t;
head_t *createl();
node_t *inst_node();
node_t *new_list;
char buffer[YLEN];
char tbuffer[60];
head_t *nlist; /*define head of new list */
void open_input(), read_file(), err_win(), update_pad(), show_pad();
void run_cmd(), blank_buf(), set_pad(), show_line(), show_help();
char spacebuf[YLEN];
int mainrow = 0;
int maincol = 0;
main(argc,argv)
int argc;
char *argv[];
{
int i;
signal(SIGINT, alter);
initscr();
nonl();
if((wpad = newpad(x,y)) == (WINDOW *)NULL)
exit(1);
if((exewin = newwin(4,79,20,0)) == (WINDOW *)NULL)
exit(1);
if((cmdwin = newwin(4,70,20,3)) == (WINDOW *)NULL)
exit(1);
if((blankit = newwin(20,79,0,0)) == (WINDOW *)NULL)
exit(1);
keypad(exewin,TRUE); /*turn on allowing extended keys*/
/*box(cmdwin,0,0); */
open_input(argv[1]);
nlist = createl(); /*create the head of the list*/
fclose(in);
open_input(argv[1]);
read_file();
/*read_list(); */
for(i=0; i < YLEN; i++)
spacebuf
= ' ';
spacebuf[YLEN] = '\0';
set_pad(0L);
padptr = 1;
new_list = nlist->first;
show_pad(0,0);
run_cmd();
fclose(in);
endwin();
exit(0);
}
void open_input(fstr)
char *fstr;
{
char errsrg[40];
if((in = fopen(fstr,"r"
) == NULL)
{
sprintf(errsrg,"%s %s","Can not open input file",fstr);
err_win(errsrg);
}
}
void err_win(err_str)
char *err_str;
{
mvwaddstr(cmdwin,1,2,err_str);
wrefresh(cmdwin);
wait(3);
endwin();
exit(0);
}
void show_win(err_str)
char *err_str;
{
mvwaddstr(cmdwin,1,2,err_str);
wrefresh(cmdwin);
}
void set_pad(xoff)
long xoff;
{
int cnt=0;
int i;
fseek(in,xoff,0);
while(1)
{
fgets(buffer,YLEN,in);
cnt++;
if(feof(in) || cnt > x)
break;
blank_buf(buffer);
update_pad();
}
if(cnt < x)/*null out any rows from previous page*/
{
strcpy(buffer,spacebuf);
for(i=cnt; i <= x; i++)
update_pad();
}
}
void update_pad()
{
mvwaddstr(wpad,xpad,0,buffer);
xpad++;
}
void show_pad(xrows,xcols)
int xrows, xcols;
{
prefresh(wpad,xrows,xcols, 1,1,19,78);
}
void run_cmd()
{
int c,d;
int bflag=0;
int line_no;
char page_no[5];
show_line();
mvwaddstr(exewin,1,0,"Page : n=Scrn Dn R=Scrn Right Dn ->,d=Scroll Dn ->,r=Scroll Right b=BOF"
;
mvwaddstr(exewin,2,0,"q = Quit p=Scrn Up L=Scrn Left Up ->,u=Scroll Up <-,l=Scroll Left e=EOF"
;
sprintf(page_no, "%d", 1);
mvwaddstr(exewin, 1, 8, page_no);
wrefresh(exewin);
while(1)
{
d = wgetch(exewin);
if ((d != PAGE_LEFT) && (d != PAGE_RIGHT))
c = to_lowercase(d);
else
c = d;
switch(c)
{
case KEY_BREAK:
bflag=1;
break;
case 'q':
bflag=1;
break;
case KEY_RIGHT:
case SCROLL_RIGHT:
if(update_cord('R', KEY_JUMP))
show_pad(mainrow,maincol); /*show pad */
break;
case KEY_LEFT:
case SCROLL_LEFT:
if(update_cord('L', KEY_JUMP))
show_pad(mainrow,maincol); /*show pad */
break;
case KEY_DOWN:
case SCROLL_DOWN:
if(update_cord('D', 1)){
show_pad(mainrow,maincol); /*show pad */
}
break;
case KEY_UP:
case SCROLL_UP:
if(update_cord('U', 1))
show_pad(mainrow,maincol); /*show pad */
break;
case PAGE_UP: /*page up*/
if(update_cord('u',winlen))
show_pad(mainrow,maincol); /*show pad */
break;
case PAGE_DOWN: /*page down*/
if(update_cord('d',winlen) )
show_pad(mainrow,maincol); /*show pad */
break;
case PAGE_RIGHT: /*page right */
if(update_cord('O',winwid))
show_pad(mainrow,maincol); /*show pad */
break;
case PAGE_LEFT: /*page left */
if(update_cord('B',winwid))
show_pad(mainrow,maincol); /*show pad */
break;
case 'b': /*home postion*/
padptr = 1;
new_list = nlist->first;
xpad = 0;
mainrow = 0;
maincol = 0;
set_pad(0L);
show_pad(0,0);
break;
case 'e': /*end postion*/
if(nlist->length == 2)
{
mainrow = nlist->last->nlines - winlen;
}
else
{
padptr = nlist->length - 1;
new_list = nlist->last->prev;
mainrow = new_list->nlines - winlen;
xpad = 0;
set_pad(new_list->poffset);
}
maincol = 0;
show_pad(mainrow,maincol);
break;
default:
break;
}
line_no = ((padptr - 1) * x) + mainrow;
sprintf(page_no, "%d", ((line_no / PAGE_LEN) + 1));
mvwaddstr(exewin, 1, 8, " "
;
mvwaddstr(exewin, 1, 8, page_no);
wrefresh(exewin);
if(bflag)
break;
/* if(c == KEY_DOWN)
bflag=1; */
}
}
int update_cord(xchar,lenl)
char xchar;
int lenl;
{
int bufit, pivot;
int c;
/*determine whether to use the end of the pad or the total number of
lines read into the pad*/
/*if(totlines < x)
pivot = totlines;
else
pivot = x;
pivot = nlist->current->nlines; */
pivot = x;
if(padptr > (nlist->length -1))
return(0);
/* move right -> R = one KEY_JUMP, O = one page */
if(xchar == 'R' || xchar == 'O')
{
if(maincol == y) /* We are at the end, so don't move */
return(0);
bufit = maincol + lenl;
if(bufit <= y) /* Move full lenl chars */
maincol += lenl;
else
maincol = y; /* < lenl chars left, move to the end */
return(1);
}
/* move left -> L = one KEY_JUMP, B = one page */
if(xchar == 'L' || xchar == 'B')
{
if(maincol == 0) /* At the beginning, so don't move */
return(0);
bufit = maincol - lenl;
if(bufit >= 0) /* Move full lenl chars */
maincol -= lenl;
else /* < lenl left, move to beginning */
maincol = 0;
return(1);
}
/* move up -> U = one char, u = one page */
if(xchar == 'U' || xchar == 'u')
{
bufit = mainrow - lenl;
if(bufit >= 0)
{
mainrow -= lenl;
return(1);
}
else
{
if(padptr > 1)
{
padptr--;
new_list = new_list->prev;
xpad = 0;
set_pad(new_list->poffset);
mainrow = x - winlen;
return(1);
}
else
{
mainrow = 0;
return(1);
}
}
}
/* move down -> D = one char, d = one page */
if(xchar == 'D' || xchar == 'd')
{
bufit = mainrow + lenl;
if(bufit < (pivot - winlen))
{
mainrow += lenl;
return(1);
}
else
{
if(padptr < (nlist->length-1))
{
padptr++;
new_list = new_list->next;
xpad = 0;
mainrow = 0;
set_pad(new_list->poffset);
return(1);
}
else
return(0);
}
}
} /* update_cord */
/*blank everything at the end of the line to allow old data over screen to
be blanked out when the cursor movement keys are used*/
void blank_buf(buf)
char *buf;
{
int len,i;
len = strlen(buf);
for(i=len; i < YLEN; i++)
{
if(buf == '\r' || buf == '\n' || buf == '\0')
buf = ' ';
}
buf[YLEN-1] = '\0';
}
/*append a node to the linked list*/
int app_node(pno, pset, list)
int pno;
long pset;
head_t *list;
{
node_t *new;
if(new = inst_node(pno,pset,list->last,NULL))
{
if(list->length) /*if list is not empty*/
list->last->next = new; /*link in the new node */
else
{
list->first = new; /*set first pointer to new*/
list->current = new; /*set the current only once */
}
list->last = new; /*link in the new node*/
list->length++; /*update list length*/
return(TRUE);
}
else
return(FALSE);
}
/*instantiate new node*/
node_t *inst_node(pno,pset,prev,next)
int pno;
long pset;
node_t *prev, *next;
{
node_t *new;
new = (struct node *)malloc(sizeof(struct node));
if(new == (struct node *)NULL)
{
fprintf(stderr,"Insufficient memory for node"
;
exit(1);
}
new->poffset = pset;
new->padno = pno;
new->prev = prev;
new->next = next;
return(new);
}
void read_file()
{
int cnt=0;
int ppno=1;
long poff=0L;
int read_flag = 1;
int break_flag=0, tots=0;
while(1)
{
if(read_flag)
{
if(!app_node(ppno,poff,nlist))
{
fprintf(stderr, "Can NOT Append \n"
;
exit(1);
}
nlist->last->nlines = cnt;
nlist->last->accum = 0;
read_flag = 0;
}
fgets(buffer,YLEN,in);
if(feof(in))
break_flag = 1;
else
cnt++;
if((cnt == x) || (break_flag && cnt > 0))
{
poff = ftell(in);
ppno++;
if(!app_node(ppno,poff,nlist))
{
printw("Can NOT Append to list\n"
;
refresh();
exit(1);
}
nlist->last->nlines = cnt;
tots = tots + cnt;
nlist->last->accum = tots;
cnt = 0;
}
if(break_flag)
break;
}
/*rewind(in); */
}
/*create a linked list header*/
head_t *createl()
{
head_t *new;
new = (struct head *)malloc(sizeof(struct head));
if(new == (struct head *)NULL)
{
fprintf(stderr,"Insufficient memory for head"
;
exit(1);
}
/*init the values */
new->length = 0;
new->first = new->last = NULL;
return(new);
}
/* int read_list()
{
node_t *new_list;
int i;
new_list = nlist->first;
while(new_list != NULL)
{
printw("padno, length is %d %d\n",new_list->padno, nlist->length);
printw("nlines is %d\n",new_list->nlines);
printw("poffset is %ld %d\n",new_list->poffset, new_list->accum);
printw("last poffset is %ld \n",nlist->last->poffset);
new_list = new_list->next;
refresh();
i = getch();
}
}*/
void show_line()
{
int i;
for(i=0; i < 79; i++)
mvwaddch(exewin,0,i,'=');
}
void alter()
{
signal(SIGINT, alter);
}