/*
* A nroff like object for formating text files.
*
* This creates a saveable file format thingy.
*/
#include "nroff.h"
mixed *nroffed_file;
string nroffed_file_name;
int modified_time;
void create() {
nroffed_file = ({ });
seteuid("Root"); /* Security risk? nahhhhh */
} /* create() */
#define do_bounds(bing) (bing<0?bing+cols:bing)
/*
* Creates a string from a nroffed file
*
* If update is non zero it will try and find the file_name and return
* 0 from here if it is either not found, or non existant...
*/
string cat_file(string fname, int update) {
int i, cols;
string ret;
if (!"/secure/master"->valid_read(fname, geteuid(previous_object()),
"restore_object"))
return 0;
nroffed_file_name = 0;
modified_time = 0;
if (!restore_object(fname,1))
return 0;
if (!nroffed_file_name && update)
return 0;
if (update) {
mixed *something;
if (!"/secure/master"->valid_read(nroffed_file_name,
geteuid(previous_object()),
"restore_object"))
return 0;
if (file_size(nroffed_file_name) <= 0)
return 0;
something = stat(nroffed_file_name);
if (something[1] > modified_time)
return 0;
}
ret = "";
cols = (int)this_player()->query_cols();
for (i=0;i<sizeof(nroffed_file);i++)
if (stringp(nroffed_file[i]))
ret += nroffed_file[i];
else
switch (nroffed_file[i]) {
case V_CENTER :
ret += sprintf("%|=*s", cols, nroffed_file[i+1]);
i++;
break;
case V_ALL :
ret += sprintf("%-*s%|*s%*s\n", nroffed_file[i+1],
nroffed_file[i+2],
cols - nroffed_file[i+1]*2,
nroffed_file[i+3],
nroffed_file[i+1],
nroffed_file[i+4]);
i += 4;
break;
case V_INDENT :
ret += sprintf("%*=s%-=*s\n", nroffed_file[i+1], "",
cols-nroffed_file[i+1],
nroffed_file[i+2]);
i += 2;
break;
case V_PARA :
ret += sprintf("%*=s%-=*s%=*s\n", nroffed_file[i+1], "",
cols-nroffed_file[i+1]-
nroffed_file[i+2], nroffed_file[i+3],
nroffed_file[i+2], "");
i += 3;
break;
case V_LEFT :
ret += sprintf("%-=*s", cols, nroffed_file[i+1]);
i++;
break;
case V_TABLE :
ret += sprintf("%-#*s", cols, nroffed_file[i+1]);
i++;
break;
case V_COLUMN : {
int j;
switch (sizeof(nroffed_file[i+1])) {
case 2 :
for (j=0;j<sizeof(nroffed_file[i+2]);j++)
ret += sprintf("%*-=s%*-=s\n", do_bounds(nroffed_file[i+1][0]),
nroffed_file[i+2][j],
do_bounds(nroffed_file[i+1][1]),
nroffed_file[i+3][j]);
i += 3;
break;
case 3 :
for (j=0;j<sizeof(nroffed_file[i+2]);j++)
ret += sprintf("%*-=s%*-=s%*-=s\n",
do_bounds(nroffed_file[i+1][0]),
nroffed_file[i+2][j],
do_bounds(nroffed_file[i+1][1]),
nroffed_file[i+3][j],
do_bounds(nroffed_file[i+1][2]),
nroffed_file[i+4][j]);
i += 4;
break;
}
break;
}
}
return " \n"+ret;
}
static int new_string, force_string;
void add_array(mixed *i) {
if (!sizeof(nroffed_file))
nroffed_file += ({ i });
else if (force_string)
nroffed_file += ({ "", i });
else
nroffed_file += ({ i });
force_string = 0;
new_string = 0;
}
void add_int(int i) {
if (!sizeof(nroffed_file))
nroffed_file += ({ i });
else if (force_string)
nroffed_file += ({ "", i });
else
nroffed_file += ({ i });
force_string = 0;
new_string = 0;
}
void add_string(string s) {
if (!sizeof(nroffed_file) || new_string)
nroffed_file += ({ s });
else if (stringp(nroffed_file[sizeof(nroffed_file)-1]))
nroffed_file[sizeof(nroffed_file)-1] += s;
else
nroffed_file += ({ s });
new_string = 0;
force_string = 0;
}
int create_nroff(string in_file, string out_file) {
string text,
tmp,
*bits;
string *bing;
mixed *cols;
int strip_crs,
col_mode,
conv_tabs,
i, j, k,
num_cols;
if (!"/secure/master"->valid_read(in_file, geteuid(previous_object()),
"read_file"))
return 0;
if (!"/secure/master"->valid_write(out_file, geteuid(previous_object()),
"save_object"))
return 0;
nroffed_file_name = in_file;
modified_time = time();
text = read_file(in_file);
if (!text)
return 0;
bits = explode("#\n"+text, "\n.");
bits[0] = bits[0][1..strlen(bits[0])-1];
nroffed_file = ({ 0 });
if (strlen(bits[0]))
add_string(bits[0]);
for (i=1;i<sizeof(bits);i++) {
/*
if (!strlen(bits[i])) {
if (col_mode) {
for (j=0;j<num_cols;j++)
cols[j] += "\n";
} else if (strip_crs)
add_string("\n\n");
else
add_string("\n");
} else if (bits[i][0] == '.') {
*/
if (sscanf(bits[i], "%s\n%s", tmp, bits[i]) != 2) {
tmp = bits[i];
bits[i] = "";
}
switch (tmp[0..1]) {
case "SI" : /* Start indent */
add_int(V_INDENT);
j = 0;
sscanf(tmp[2..1000], "%d%s", j, tmp);
add_int(j);
force_string = 1;
break;
case "EI" : /* End paragraph */
new_string = 1;
break;
case "SP" : /* Start paragraph */
add_int(V_PARA);
j = 0;
sscanf(tmp[2..1000], "%d%s", j, tmp);
add_int(j);
j = 0;
sscanf(tmp, " %d%s", j, tmp);
add_int(j);
force_string = 1;
strip_crs = 1;
break;
case "EP" : /* End paragraph */
new_string = 1;
strip_crs = 0;
break;
case "SC" : /* start centering */
add_int(V_CENTER);
force_string = 1;
break;
case "EC" : /* End centering */
new_string = 1;
break;
case "SL" : /* Start left justify */
add_int(V_LEFT);
force_string = 1;
break;
case "EL " : /* End left justify */
new_string = 1;
break;
case "ST" : /* Start table mode (Turn tabs into new lines) */
add_int(V_TABLE);
force_string = 1;
conv_tabs = 1;
break;
case "ET" : /* End table mode */
new_string = 1;
conv_tabs = 0;
break;
case "DT" : /* Do title. Take the next three lines... */
bing = explode(bits[i], "\n");
if (sizeof(bing) < i+3)
return 0; /* failed! */
add_int(V_ALL);
if (strlen(bing[0]) > strlen(bing[2]))
add_int(strlen(bing[0]));
else
add_int(strlen(bing[2]));
new_string = 1;
add_string(bing[0]);
new_string = 1;
add_string(bing[1]);
new_string = 1;
add_string(bing[2]);
new_string = 1;
bits[i] = implode(bing[3..1000], "\n");
break;
case "SO" : /* starts column mode. The numbers after it
* are column size */
num_cols = 0;
tmp = tmp[2..1000];
cols = ({ });
while (sscanf(tmp, "%d%s", j, tmp) == 2) {
cols += ({ j });
num_cols++;
while (strlen(tmp) && tmp[0] == ' ')
tmp = tmp[1..1000];
}
add_int(V_COLUMN);
if (sscanf(tmp, "%d", j) == 1) {
cols += ({ j });
num_cols++;
}
add_array(cols);
cols = allocate(num_cols);
for (j=0;j<num_cols;j++) cols[j] = ({ });
col_mode = 1;
break;
case "EO" : /* End column mode */
for (j=0;j<num_cols;j++) {
add_array(cols[j]);
}
col_mode = 0;
break;
}
/* Now dis bit... */
if (!strlen(bits[i])) continue;
if (conv_tabs)
bits[i] = replace(bits[i], "\t", "\n");
if (col_mode) {
string *frog;
frog = explode(bits[i], "\n");
for (k=0;k<sizeof(frog);k++) {
bing = explode("#"+frog[k], "\t");
bing[0] = bing[0][1..1000];
for (j=0;j<num_cols && j < sizeof(bing);j++)
cols[j] += ({ bing[j] });
for (j=sizeof(bing);j<num_cols;j++)
cols[j] += ({ "\n" });
}
} else if (strip_crs) {
bits[i] = replace_string(bits[i], "\n\n", "$%^NeW_LiNe^%$");
bits[i] = replace_string(bits[i], "\n", " ");
bits[i] = replace_string(bits[i], "$%^NeW_LiNe^%$", "\n\n");
add_string(bits[i]+" ");
} else
add_string(bits[i]+"\n");
/*
}
*/
}
new_string = 0;
force_string = 0;
save_object(out_file,1);
return 1;
}
void create_help(string path, string file) {
if (path[0..4] == "/doc/")
this_object()->create_nroff(path+file, NROFF_DIR+file);
else
write("Invalid path. "+path+"\n");
}
void create_chelp(string path, string file) {
if (path[0..4] == "/doc/")
this_object()->create_nroff(path+file, CNROFF_DIR+file);
else
write("Invalid path.\n");
}