/*
* Original by Ember.
* Improved version by Pinkfish.
* Debugged by Deutha.
*/
#include <nroff.h>
#define ROWS ( (int)this_player()->query_rows() - 1 )
#define COLS (int)this_player()->query_cols()
private nosave int fsize, topl, botl, charl, real_rows, search_flag;
private nosave mixed mark_data;
private nosave string fname,
*mark_name,
*filenames,
finish_func,
stat_line,
last_search;
private void display_file() {
int i, ncols, nrows;
string file, *bits, *lines;
ncols = COLS;
nrows = ROWS;
file = read_file( fname, topl, nrows );
if ( !file )
return;
file = replace( file, ({ "\t", "<TAB>", sprintf( "%c", 13 ), "\\n" }) );
/* We add the extra character and then remove it from the resulting
* array because this won't work on totally blank lines. :( */
bits = explode( "x\n" + file, "\n" )[1 .. ];
if ( charl )
bits[ 0 ] = bits[ 0 ][ charl .. strlen( bits[ 0 ] ) - 1 ];
real_rows = 0;
lines = ({ });
for ( i = 0; i < sizeof( bits ); i++ ) {
if ( strlen( bits[ i ] ) > ncols ) {
lines += ({ bits[ i ][ 0 .. ncols - 1 ] });
bits[ i ] = bits[ i ][ ncols .. strlen( bits[ i ] ) - 1 ];
charl += ncols;
i--;
} else {
lines += ({ bits[ i ] });
charl = 0;
real_rows++;
}
if ( sizeof( lines ) == nrows )
break;
}
printf( "%s\n", implode( lines, "\n" ) );
botl = topl + real_rows - 1;
if ( botl > fsize )
botl = fsize;
} /* display_file() */
private void get_next_filename() {
string str;
fname = filenames[0];
fsize = file_length( fname );
if( !file_size( fname ) ) {
printf( "Empty file.\n" );
if(sizeof(filenames) > 1) {
filenames = filenames[1..sizeof(filenames) - 1];
get_next_filename();
return;
}
else
return;
}
if (fsize == -1) {
printf( "File does not exist.\n" );
if(sizeof(filenames) > 1) {
filenames = filenames[1..sizeof(filenames) - 1];
get_next_filename();
return;
}
else
return;
}
if (fsize == -2) {
printf( "You cannot more a directory.\n" );
if(sizeof(filenames) > 1) {
filenames = filenames[1..sizeof(filenames)-1];
get_next_filename();
return;
}
else
return;
}
topl = 1;
if(sizeof(filenames) > 1)
filenames = filenames[1..sizeof(filenames) - 1];
else
filenames = ({ });
printf( "\n" );
str = read_file(fname, 1, 1);
if(!str)
return;
if (str[0] == '.') {
string s2;
/*
* Nroff file... do horrible things! Turn into a mushroom! Blow up
* all the hairy crater eating womble doovalacies...
* In the case of a nroff file we push the file through nroff then shove it
* through more_string...
*/
str = "/tmp/nroffed_file";
if (NROFF_HAND->create_nroff(fname, "/tmp/nroffed_file")) {
s2 = NROFF_HAND->cat_file("/tmp/nroffed_file");
rm("/tmp/nroffed_file.o");
if (s2) {
this_player()->more_string(s2, fname);
fsize = ROWS-3;
return ;
}
}
}
display_file();
} /* get_next_file_name() */
private string *expand_path(string s) {
string *s1;
s1 = (string *)this_player()->get_files(s);
if (!s1)
return ({ s });
return s1;
} /* expand_path() */
int set_mark(string s) {
int i;
if (!mark_name) {
mark_name = ({ });
mark_data = ({ });
}
if ((i=member_array(s,mark_name))!=-1)
mark_data[i] = ({ fname, topl });
else {
mark_name += ({ s });
mark_data += ({ ({ fname, topl }) });
}
return 1;
} /* set_mark() */
private void status_line() {
string *frog;
string s;
int i, percentage;
if (!stat_line)
stat_line = "$N From $T to $B of $S ($%%) - h for help. ";
s = "";
frog = explode(stat_line, "$");
for (i=0;i<sizeof(frog);i++) {
if (frog[i] == "") {
s += "$";
i ++;
} else switch (frog[i][0]) {
case 'N' :
s += fname+frog[i][1..1000];
break;
case 'T' :
s += topl+frog[i][1..1000];
break;
case 'B' :
if (botl > fsize)
s += fsize+frog[i][1..100];
else
s += botl+frog[i][1..100];
break;
case '%' : {
percentage = (botl*100)/fsize;
if(percentage > 100) percentage = 100;
s += percentage+frog[i][1..100];
break;
}
case 'S' :
s += fsize+frog[i][1..1000];
break;
}
}
printf( "%s", s );
return;
printf( fname +" From "+ topl +" to "+ botl +" of "+ fsize +" ("+
( ( botl * 100 ) / fsize ) +"%) - h for help. " );
} /* status_line() */
void next_page(string str) {
int num, noargs, i, j, k, redraw;
string s1, *s3;
if (!str)
str = "";
if (sscanf(str,"%d%s", num, str)!=2)
noargs = 1;
s1 = extract(str,1);
/* case statements WEEEEEE */
switch(str[0..0]) {
case "" :
case " " :
topl += real_rows;
redraw = 1;
break;
case "f" :
/* go on a number of pages... */
if (noargs)
num = 1;
topl += ROWS * num;
redraw = 1;
break;
case "q" :
printf( "Ok.\n" );
return ;
case "/" :
/* sigh */
search_flag = 0;
j = topl+4;
if (s1[0] == '!') {
search_flag = 1;
s1 = extract(s1,1);
}
set_mark("'");
if (s1=="" || !s1)
s1 = last_search;
if (s1 == "") {
printf( "No previous search string.\n" );
break;
}
do {
i = j;
j = i+900;
if (j>fsize)
j = fsize;
s3 = explode(read_file(fname,i,j),"\n");
for (k=0;k<sizeof(s3);k++)
if (!search_flag) {
if (sscanf(s3[k],"%*s"+s1+"%*s")==2)
if (num--<=0)
break;
} else
if (sscanf(s3[k],"%*s"+s1+"%*s")!=2)
if (num--<=0)
break;
} while (j<fsize && k == sizeof(s3));
if (k==sizeof(s3))
printf( "Sorry "+ s1 +" not found.\n" );
else {
topl = i+k-3;
redraw = 1;
}
last_search = s1;
break;
case "?" :
i = topl;
if (s1[0] == '!') {
s1 = extract(s1,1);
search_flag = 3;
} else
search_flag = 2;
set_mark("'");
if (s1=="" || !s1)
s1 = last_search;
if (s1 == "") {
printf( "No previous search string.\n" );
break;
}
do {
j = i-900;
if (j<0)
j = 0;
s3 = explode(read_file(fname,j,i),"\n");
for (k=0;k<sizeof(s3);k++)
if (search_flag == 2) {
if (sscanf(s3[k],"%*s"+s1+"%*s")==2)
if (num--<=0)
break;
} else
if (sscanf(s3[k],"%*s"+s1+"%*s")!=2)
if (num--<=0)
break;
i = j;
} while (j>0 && k == sizeof(s3));
if (k==sizeof(s3))
printf( "Sorry "+ s1 +" not found.\n" );
else {
topl = k+i-2;
redraw = 1;
}
last_search = s1;
break;
case "n" :
switch (search_flag) {
case 0 : next_page(num+"/");
break;
case 1 : next_page(num+"/!");
break;
case 2 : next_page(num+"?");
break;
case 3 : next_page(num+"?!");
break;
}
return;
case "b" :
if (noargs)
num = 1;
if (topl>0) {
topl -= ROWS * num;
redraw = 1;
if (topl<0)
topl = 0;
}
break;
case "G" :
if (noargs)
num = fsize-ROWS+1;
case "g" :
set_mark("'");
topl = num;
if (topl>=fsize)
topl = fsize-2;
redraw = 1;
break;
case "P" :
if (noargs)
num = 100;
case "p" :
case "%" :
redraw = 1;
set_mark("'");
topl = (num*fsize)/100;
if (topl+ROWS-1>fsize)
topl -= ROWS-1;
break;
case "d" :
if (noargs)
num = ROWS/2;
topl += num;
redraw = 1;
break;
case "u" :
if (noargs)
num = ROWS/2;
topl -= num;
redraw = 1;
break;
case "r" :
redraw = 1;
break;
case "m" :
if (s1=="") {
printf( "Sorry, you must specify a name.\n" );
break;
}
set_mark(s1);
printf( "Okay, mark "+ s1 +" set.\n" );
break;
case "'" :
if (!mark_name) {
printf( "Sorry, must go to a mark.\n" );
break;
}
if ((i=member_array(s1,mark_name))!=-1) {
if (fname != mark_data[i][0]) {
fname = mark_data[i][0];
redraw = 1;
}
if (topl != mark_data[i][1]) {
topl = mark_data[i][1];
redraw = 1;
}
} else
printf( "Mark "+ s1 +" not set.\n" );
break;
case "F" :
filenames = expand_path(str);
if (!sizeof(filenames)) {
printf( "No matching files.\n" );
break;
}
last_search = "";
get_next_filename();
redraw = 1;
break;
case "h" :
cat("/doc/helpdir/more");
break;
}
if (redraw)
display_file();
if ( ( botl < fsize ) || charl ) {
status_line();
input_to( "next_page" );
} else
if(sizeof(filenames)) {
get_next_filename();
input_to("next_page");
} else {
if (finish_func)
call_other(this_player(), finish_func);
}
} /* next_page() */
int more_file(string str) {
filenames = expand_path(str);
if (!sizeof(filenames)) {
notify_fail("No matching files.\n");
return 0;
}
last_search = "";
get_next_filename();
if ( ( botl < fsize ) || charl ) {
status_line();
input_to( "next_page" );
} else
if (finish_func)
call_other(this_player(), finish_func);
return 1;
} /* more_file() */