cface32000-01-10Martin Nilsson // RXML Help // Copyright (c) 2000 Idonex AB // Martin Nilsson //
2feec42000-01-24Martin Nilsson //#define RXMLHELP_DEBUG #ifdef RXMLHELP_DEBUG # define RXMLHELP_WERR(X) werror("RXML help: %s\n", X); #else # define RXMLHELP_WERR(X) #endif
a104662000-01-25Martin Nilsson // --------------------- Layout help functions -------------------- string mktable(array table) { string ret="<table boder=\"0\" cellpadding=\"0\" border=\"0\"><tr><td bgcolor=\"#000000\">\n" "<table border=\"0\" cellspacing=\"1\" cellpadding=\"5\">\n"; foreach(table, array row) ret+="<tr><td bgcolor=\"#d9dee7\">"+(row*"</td><td bgcolor=\"#d9dee7\">")+"</td></tr>\n"; ret+="</table></tr></td></table>"; return ret; } string available_languages(object id) { string pl="en"; if(id->misc->pref_languages && sizeof(id->misc->pref_languages)) { pl=id->misc->pref_languages[0]; if(!roxen->languages[pl]) pl="en"; } mapping languages=roxen->languages[pl]->languages; return mktable( Array.map(indices(languages), lambda(string code) { return ({ code, languages[code] }); } )); } // --------------------- Help layout functions --------------------
cface32000-01-10Martin Nilsson  private string desc_cont(string t, mapping m, string c, string rt) { string dt=rt; m->type=m->type||""; if(m->tag) dt=sprintf("&lt;%s/&gt;", rt); if(m->cont) dt=(m->tag?dt+" and ":"")+sprintf("&lt;%s&gt;&lt;/%s&gt;", rt, rt); return sprintf("<h2>%s</h2><p>%s</p>",dt,c); } private string attr_cont(string t, mapping m, string c) { string p=""; if(!m->name) m->name="(Not entered)"; if(m->value) p=sprintf("<i>%s=%s</i><br>",m->name,attr_vals(m->value)); return sprintf("<p><b>%s</b><br>%s%s</p>",m->name,p,c); } private string attr_vals(string v) { if(search(v,",")!=-1) return "{"+(v/",")*", "+"}"; //FIXME Use real config url if(v=="langcodes") return "<a href=\"/help/langcodes.pike\">language code</a>"; return v; }
9dcf432000-01-23Martin Nilsson private string ex_cont(string t, mapping m, string c, string rt, void|object id) { if(!id) return ""; string parsed=id->conf->parse_rxml(c,id); c=replace(c, ({"<",">","&"}), ({"&lt;","&gt;","&amp;"}) ); switch(m->type) { case "hr": return c+"<hr>"+parsed; case "vert":
a104662000-01-25Martin Nilsson  return "<br>"+mktable( ({ ({ c }), ({ parsed }) }) );
9dcf432000-01-23Martin Nilsson  case "hor": default:
a104662000-01-25Martin Nilsson  return "<br>"+mktable( ({ ({ c, parsed }) }) );
9dcf432000-01-23Martin Nilsson  } } private string format_doc(string|mapping doc, string name, void|object id) { if(mappingp(doc)) {
a104662000-01-25Martin Nilsson  if(id && id->misc->pref_languages) { object lang=roxen->languages[id->misc->pref_languages[0]];
dfe0642000-01-26Martin Nilsson  array lang_id; if(lang) { lang_id=lang->id(); if(doc[lang_id[2]]) doc=doc[lang_id[2]]; else if(doc[lang_id[1]]) doc=doc[lang_id[1]]; }
a104662000-01-25Martin Nilsson  else doc=doc["standard"];
9dcf432000-01-23Martin Nilsson  } else doc=doc->standard; }
cface32000-01-10Martin Nilsson  return parse_html(doc, ([]), ([ "desc":desc_cont,
9dcf432000-01-23Martin Nilsson  "attr":attr_cont,
a104662000-01-25Martin Nilsson  "ex":ex_cont, "lang":lambda(string t, mapping m) { return available_languages(id); }
9dcf432000-01-23Martin Nilsson  ]), name, id);
cface32000-01-10Martin Nilsson }
c284a02000-01-21Martin Nilsson 
cface32000-01-10Martin Nilsson // ------------------ Parse docs in mappings --------------
9dcf432000-01-23Martin Nilsson private string parse_doc(string|mapping|array doc, string name, void|object id) {
c284a02000-01-21Martin Nilsson  if(arrayp(doc))
9dcf432000-01-23Martin Nilsson  return format_doc(doc[0], name, id)+ "<dl><dd>"+parse_mapping(doc[1], id)+"</dd></dl>"; return format_doc(doc, name, id);
c284a02000-01-21Martin Nilsson }
9dcf432000-01-23Martin Nilsson private string parse_mapping(mapping doc, void|object id) {
cface32000-01-10Martin Nilsson  string ret=""; if(!mappingp(doc)) return ""; foreach(indices(doc), string tmp) {
9dcf432000-01-23Martin Nilsson  ret+=parse_doc(doc[tmp], tmp, id);
cface32000-01-10Martin Nilsson  } return ret; }
c284a02000-01-21Martin Nilsson 
cface32000-01-10Martin Nilsson // --------------------- Find documentation --------------
c284a02000-01-21Martin Nilsson mapping call_tagdocumentation(RoxenModule o) { mapping doc;
2feec42000-01-24Martin Nilsson #ifdef RXMLHELP_DEBUG doc=o->tagdocumentation(); #else
c284a02000-01-21Martin Nilsson  catch { doc=o->tagdocumentation(); };
2feec42000-01-24Martin Nilsson #endif RXMLHELP_WERR(sprintf("tagdocumentation() returned %t.",doc));
c284a02000-01-21Martin Nilsson  if(!doc || !mappingp(doc)) return 0; return doc; }
dbbfdf2000-01-12Martin Nilsson 
9dcf432000-01-23Martin Nilsson private int generation; multiset undocumented_tags=(<>); string find_tag_doc(string name, void|object id) {
124c202000-01-24Martin Nilsson  RXMLHELP_WERR("Help for tag "+name+" requested.");
c284a02000-01-21Martin Nilsson  RXML.TagSet tag_set=RXML.get_context()->tag_set; string doc; int new_gen=tag_set->generation;
9dcf432000-01-23Martin Nilsson  if((doc=cache_lookup("tagdoc",name)) && generation==new_gen)
c284a02000-01-21Martin Nilsson  return doc; if(generation!=new_gen) {
9dcf432000-01-23Martin Nilsson  undocumented_tags=(<>);
c284a02000-01-21Martin Nilsson  cache_expire("tagdoc"); generation=new_gen; } array tags=tag_set->get_overridden_tags(name); if(!sizeof(tags)) return "<h4>That tag is not defined</h4>"; foreach(tags, array|object|function tag) { if(objectp(tag)) { // FIXME: New style tag. Check for internal documentation. tag=object_program(tag); } if(arrayp(tag)) { if(tag[0]) tag=tag[0][1]; else if(tag[1]) tag=tag[1][1]; } tag=function_object(tag); if(!objectp(tag)) continue;
2feec42000-01-24Martin Nilsson  RXMLHELP_WERR(sprintf("Tag defined in module %O", tag));
c284a02000-01-21Martin Nilsson  mapping tagdoc=call_tagdocumentation(tag); if(!tagdoc || !tagdoc[name]) continue;
9dcf432000-01-23Martin Nilsson  cache_set("tagdoc", name, tagdoc[name]); doc=parse_doc(tagdoc[name], name, id);
c284a02000-01-21Martin Nilsson  return doc; }
9dcf432000-01-23Martin Nilsson  undocumented_tags[name]=1;
cface32000-01-10Martin Nilsson  return "<h4>No documentation available for \""+name+"\".</h4>\n"; }
2feec42000-01-24Martin Nilsson string find_module_doc( string cn, string mn, RequestID id )
cface32000-01-10Martin Nilsson {
124c202000-01-24Martin Nilsson  RXMLHELP_WERR("Help for module "+mn+" requested.");
cface32000-01-10Martin Nilsson  object c = roxen.find_configuration( cn );
2feec42000-01-24Martin Nilsson  if(!c) return "";
cface32000-01-10Martin Nilsson 
2feec42000-01-24Martin Nilsson  RoxenModule o = c->find_module( replace(mn,"!","#") );
124c202000-01-24Martin Nilsson  if(!o) return "";
cface32000-01-10Martin Nilsson 
2feec42000-01-24Martin Nilsson  return parse_mapping(o->tagdocumentation());
cface32000-01-10Martin Nilsson }