/* Hamlet, March 1996 -- This object displays manual pages and/or lets the user navigate the manual system. */ #include <man.h> object user; /* Who owns this displayer? */ int MENUING; /* Are we in the menu system? */ string *curpath; /* What directory are they in? */ /* These are scratchpad sorts of things... keeps us from having to re-query or recalculate. */ string curmenu; string ftext; string *subdirs; string *docs; void create() { seteuid("Root"); curpath = ({ }); MENUING = 0; /* paranoia */ } void dest_me() { destruct(this_object()); } varargs void show_menu(string file, int redisplay); void show_document(string file); void input_prompt(string str); void delay_prompt(string str); void do_query(string str, object me) { string *bits; int building; string fname; user = me; if(!str) str = ""; else { bits = explode(str," "); if(sizeof(bits) > 1) str = implode(bits,"/"); } building = MAN_HANDLER->doc_index_building(); fname = MAN_HANDLER->get_doc_fname(str); if(!fname || !strlen(fname)) { tell_object(user,"Your subject was not found in the index.\n"); if(building) tell_object(user,"However, the system is currently loading. " "Try again in a minute or so.\n"); return; } /* Okay! We've got a match. Do we enter the menuing system or just display a page? */ bits = explode(fname,"/"); if(bits[sizeof(bits)-1] == "README") { /* It's a directory. */ if(building) { tell_object(user,"The manual system is currently loading. " "Please wait a few seconds.\n"); return; } if(sizeof(bits) == 2) curpath = ({ }); else curpath = bits[1..sizeof(bits)-2]; curmenu = fname; MENUING = 1; show_menu(fname); return; } /* else (it's a document.) */ show_document(fname); } /* This one shows both a directory's doc file (dir/README) and a list of available documents and subtopics in the dir. It relies on curpath being properly set. */ varargs void show_menu(string file, int redisplay) { if(!redisplay) { if(file_size(MANDIR+file) > 0) ftext = read_file(MANDIR+file); else ftext = read_file(MANDIR+"NO_README"); subdirs = MAN_HANDLER->get_subdirs(implode(curpath,"/")); docs = MAN_HANDLER->get_docs_in_dir(implode(curpath,"/")); } if(sizeof(curpath)) tell_object(user,"\n%^BOLD%^%^BLUE%^Topic: "+implode(curpath,"/")+ "%^RESET%^\n\n"); else tell_object(user,"\n"); tell_object(user,ftext+"\n"); if(sizeof(subdirs)) tell_object(user,"Subtopics:\n\n%^BOLD%^%^CYAN%^"+ sprintf(" %-#*s",user->query_cols(), implode(subdirs,"\n"))+"\n\n%^RESET%^"); if(sizeof(docs)) tell_object(user,"Documents:\n\n%^CYAN%^"+ sprintf(" %-#*s",user->query_cols(), implode(docs,"\n"))+"\n\n%^RESET%^"); tell_object(user,"Type 'q' to quit. Enter subtopic or document to " "continue.\n'.' will redisplay this menu. Press <ret> " "to go one level lower.\n%^BOLD%^%^BLUE%^/"+ implode(curpath,"/")+">%^RESET%^ "); input_to("input_prompt"); } /* This one displays a document, more'ing it if necessary. */ void show_document(string file) { string *fdata; string data; if(file_size(MANDIR+file) == 0) { tell_object(user,"Oops. That file seems to be empty.\n" "[Press return to continue.]"); input_to("delay_prompt"); return; } else { fdata = explode(file,"/"); data = "\n%^BOLD%^%^BLUE%^Topic: "+ implode(fdata[1..sizeof(fdata)],"/")+"%^RESET%^\n\n"; data += read_file(MANDIR+file); if(sizeof(explode(data,"\n")) <= user->query_rows()) { tell_object(user,data+"\n"); if(MENUING) { tell_object(user,"[Press return to continue.]"); input_to("delay_prompt"); } else dest_me(); return; } else { user->set_finish_func("finish_func"); user->more_string(data,"["+file+"]"); } } } /* We just more'd a file. This function gets entered when we get back. */ void finish_func() { if(MENUING) show_menu(curmenu,1); else dest_me(); } /* Needed for files shorter than one screen. */ void delay_prompt(string str) { finish_func(); } void input_prompt(string str) { int i; string doc; if(!str || !strlen(str) || (str == "..")) { /* Drop a level. */ if(!sizeof(curpath)) { /* exit the system */ dest_me(); return; } /* Otherwise, just go one directory shallower */ if(sizeof(curpath) == 1) curpath = ({ }); else curpath = curpath[0..sizeof(curpath) - 2]; curmenu = MAN_HANDLER->get_doc_fname(implode(curpath,"/")); show_menu(curmenu); return; } /* else */ if(str == "q") { /* They're quitting the system. */ dest_me(); return; } /* else */ if(str == ".") { show_menu(curmenu,1); return; } /* else, this is a real attempt to view a subtopic or document. */ i = member_array(str,subdirs); if(i == -1) { i = member_array(str,docs); if(i == -1) { /* Dummies, they didn't type anything valid. */ tell_object(user,"That selection is not valid.\n\n" "[Press return to continue.]"); input_to("delay_prompt"); return; } /* Else, they're viewing a document. */ if(sizeof(curpath)) doc = implode(curpath,"/")+"/"+str; else doc = str; show_document(MAN_HANDLER->get_doc_fname(doc)); } else { /* They want to view a new directory */ if(sizeof(curpath)) doc = implode(curpath,"/")+"/"+str; else doc = str; curmenu = MAN_HANDLER->get_doc_fname(doc); curpath += ({ str }); show_menu(curmenu); } }