0e834c2000-02-24Martin Nilsson // This is a roxen module. Copyright © 2000, Roxen IS. //
fb74971997-09-16Per Hedbor #include <module.h> inherit "module";
6a4ce21999-09-26Martin Nilsson constant thread_safe=1;
b13cba1999-09-25Martin Nilsson 
9b03652001-03-07Kenneth Johansson constant cvs_version = "$Id: check_spelling.pike,v 1.15 2001/03/07 13:42:10 kuntri Exp $";
559b491998-01-21Henrik Grubbström (Grubba) 
b3281f2000-09-10Martin Nilsson constant module_type = MODULE_TAG;
59ae152000-04-06Mattias Wingstedt constant module_name = "Spell checker"; constant module_doc = #"Checks for misspelled words inside the <tt>&lt;spell&gt;</tt> tag.";
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström mapping find_internal(string f, RequestID id)
fb74971997-09-16Per Hedbor {
c2dc4a2000-02-22Stefan Wallström  switch(f) { case "red.gif":
1a73582000-04-30Martin Nilsson  return Roxen.http_string_answer("GIF89a\5\0\5\0\200\0\0\0\0\0\267\0\0,\0\0\0\0\5\0\5\0\0\2\7\204\37i\31\253g\n\0;","image/gif");
c2dc4a2000-02-22Stefan Wallström  case "green.gif":
1a73582000-04-30Martin Nilsson  return Roxen.http_string_answer("GIF89a\5\0\5\0\200\0\0\2\2\2\0\267\14,\0\0\0\0\5\0\5\0\0\2\7\204\37i\31\253g\n\0;","image/gif");
c2dc4a2000-02-22Stefan Wallström  default: return 0; }
fb74971997-09-16Per Hedbor }
c2dc4a2000-02-22Stefan Wallström void create() { defvar("spellchecker","/usr/bin/ispell", "Spell checker", TYPE_STRING,
59ae152000-04-06Mattias Wingstedt  "Spell checker program to use.");
fb74971997-09-16Per Hedbor 
905ae42000-09-04Johan Sundström  defvar("dictionary", "american", "Default dictionary", TYPE_STRING,
59ae152000-04-06Mattias Wingstedt  "The default dictionary used, when not specified in the tag.");
fb74971997-09-16Per Hedbor 
905ae42000-09-04Johan Sundström  defvar("report", "popup", "Default report type", TYPE_STRING_LIST,
59ae152000-04-06Mattias Wingstedt  "The default report type used, when not specified in the tag.",
c2dc4a2000-02-22Stefan Wallström  ({ "popup","table" }) );
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  defvar("prestate", "", "Prestate",TYPE_STRING, "If specified, only check spelling when this prestate is present.");
fb74971997-09-16Per Hedbor  }
b956721998-02-03Per Hedbor 
c2dc4a2000-02-22Stefan Wallström string render_table(array spellreport) { string ret="<table bgcolor=\"#000000\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n" "<tr><td><table border=\"0\" cellspacing=\"0\" cellpadding=\"4\">\n" "<tr bgcolor=\"#112266\">\n" "<th align=\"left\"><font color=\"#ffffff\">Word</font></th><th align=\"left\"><font color=\"#ffffff\">Suggestions</th></tr>\n";
b956721998-02-03Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  int row=0; foreach(spellreport,array word) { row++; ret+="<tr bgcolor=\"#"+(row&1?"ffffff":"ddeeff")+"\"><td align=\"left\">"+word[0]+"</td><td align=\"left\">"+word[1]+"</td></tr>\n"; } return ret+"</table></td></tr>\n</table>";
b956721998-02-03Per Hedbor }
c2dc4a2000-02-22Stefan Wallström  string do_spell(string q, mapping args, string content,RequestID id)
fb74971997-09-16Per Hedbor {
c2dc4a2000-02-22Stefan Wallström  string ret="";
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  if(args->help) return register_module()[2]+"<p>";
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  string dict=args->dictionary || query("dictionary"); if(!sizeof(dict)) dict="american";
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  string text=Protocols.HTTP.unentity(content);
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  text=replace(text,({"\n","\r"}),({" "," "})); text=Array.everynth((replace(text,">","<")/"<"),2)*" "; text=replace(text, ({ ".",",",":",";","\t","!","|","?","(",")","\"" }), ({ "", "", "", "", "", "", "", "", "", "", "" }) ); array(string) words=text/" "; words-=({"-",""}); array result=spellcheck(words,dict); if(args->report||query("report")=="popup") { if(!sizeof(result))
db053e2000-12-05Martin Nilsson  return "<img src=\""+query_absolute_internal_location(id)+"green.gif\">"+content;
0e834c2000-02-24Martin Nilsson 
c2dc4a2000-02-22Stefan Wallström  if(!id->misc->__checkspelling) { id->misc->__checkspelling=1;
0e834c2000-02-24Martin Nilsson 
c2dc4a2000-02-22Stefan Wallström  ret+=#"<script language=\"javascript\"> var spellcheckpopup=''; var isNav4 = false; if (navigator.appVersion.charAt(0) == \"4\" && navigator.appName == \"Netscape\") isNav4 = true; function getObj(obj) { if (isNav4) return eval(\"document.\" + obj); else return eval(\"document.all.\" + obj);
fb74971997-09-16Per Hedbor }
c2dc4a2000-02-22Stefan Wallström function getRecursiveLeft(o)
fb74971997-09-16Per Hedbor {
c2dc4a2000-02-22Stefan Wallström  if(o.tagName == \"BODY\") return o.offsetLeft; return o.offsetLeft + getRecursiveLeft(o.offsetParent); }
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström function getRecursiveTop(o) { if(o.tagName == \"BODY\") return o.offsetTop; return o.offsetTop + getRecursiveTop(o.offsetParent); }
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström function showPopup(popupid,e) { if(isNav4){ getObj(popupid).moveTo(e.target.x,e.target.y); } else { getObj(popupid).style.pixelLeft=getRecursiveLeft(window.event.srcElement); getObj(popupid).style.pixelTop=getRecursiveTop(window.event.srcElement);
fb74971997-09-16Per Hedbor  }
c2dc4a2000-02-22Stefan Wallström  spellcheckpopup=popupid if(isNav4) { getObj(popupid).visibility=\"visible\"; document.captureEvents(Event.MOUSEMOVE); document.onMouseMove = checkPopupCoord;
0e834c2000-02-24Martin Nilsson  } else {
c2dc4a2000-02-22Stefan Wallström  getObj(popupid).style.visibility=\"visible\"; document.onmousemove = checkPopupCoord;
cd1dde2000-02-17Per Hedbor  }
c2dc4a2000-02-22Stefan Wallström }
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström function checkPopupCoord(e) { p = getObj(spellcheckpopup); if(isNav4) { x=e.pageX; y=e.pageY; pw=p.clip.width; ph=p.clip.height; px=p.left; py=p.top; } else { x=window.event.clientX + document.body.scrollLeft; y=window.event.clientY + document.body.scrollTop; pw=p.offsetWidth; ph=p.offsetHeight; px=p.style.pixelLeft; py=p.style.pixelTop; } if(!((x > px && x < px + pw) && (y > py && y < py + ph))) { if(isNav4) { p.visibility=\"hidden\"; document.releaseEvents(Event.MOUSEMOVE); } else { p.style.visibility=\"hidden\";
0e834c2000-02-24Martin Nilsson  document.onMouseMove = 0;
c2dc4a2000-02-22Stefan Wallström  } } } </script>";
0e834c2000-02-24Martin Nilsson 
c2dc4a2000-02-22Stefan Wallström  }
fb74971997-09-16Per Hedbor 
cd1dde2000-02-17Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  string popupid="spellreport"+sprintf("%02x",id->misc->__checkspelling);
0e834c2000-02-24Martin Nilsson 
c2dc4a2000-02-22Stefan Wallström  ret+="<style>#"+popupid+" {position:absolute; left:0; top:0; visibility:hidden}</style>"; ret+="<div id=\""+popupid+"\">"+render_table(result)+"</div>";
cd1dde2000-02-17Per Hedbor 
db053e2000-12-05Martin Nilsson  ret+= "<a href=\"\" onMouseOver='if(isNav4) showPopup(\""+popupid+"\",event);else showPopup(\""+popupid+"\");'><img border=0 src=\""+query_absolute_internal_location(id)+"red.gif\"></a>"+content;
0e834c2000-02-24Martin Nilsson 
c2dc4a2000-02-22Stefan Wallström  id->misc->__checkspelling++; return ret; }
fb74971997-09-16Per Hedbor 
cd1dde2000-02-17Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  return content + "<p><b>Spell checking report:</b><p>"+ render_table(result); }
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström class TagSpell { inherit RXML.Tag; constant name="spell";
cd1dde2000-02-17Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  class Frame { inherit RXML.Frame; array do_return (RequestID id) { string _prestate=id->variables->prestate||query("prestate"); if(sizeof(_prestate) && !id->prestate[_prestate]) return ({ content }); else return ({ do_spell("spell",args,content,id) }); }
fb74971997-09-16Per Hedbor 
c2dc4a2000-02-22Stefan Wallström  } }
cd1dde2000-02-17Per Hedbor 
c2dc4a2000-02-22Stefan Wallström array spellcheck(array(string) words,string dict) { array res=({ });
0e834c2000-02-24Martin Nilsson 
c2dc4a2000-02-22Stefan Wallström  object file1=Stdio.File(); object file2=file1->pipe(); object file3=Stdio.File(); object file4=file3->pipe(); string spell_res; Process.create_process( ({ query("spellchecker"),"-a","-d",dict }) ,(["stdin":file2,"stdout":file4 ]) ); file1->write(" "+words*"\n "+"\n"); file1->close(); file2->close(); file4->close(); spell_res=file3->read(); file3->close(); array ispell_data=spell_res/"\n";
0e834c2000-02-24Martin Nilsson 
c2dc4a2000-02-22Stefan Wallström  if(sizeof(ispell_data)>1) { int i,row=0,pos=0,pos2; string word,suggestions; for(i=1;i<sizeof(ispell_data)-1 && row<sizeof(words);i++) { if(!sizeof(ispell_data[i])){ // next row row++; pos=0;
fb74971997-09-16Per Hedbor  }
c2dc4a2000-02-22Stefan Wallström  else { switch(ispell_data[i][0]) { case '&': // misspelled, suggestions sscanf(ispell_data[i],"& %s %*d %d:%s",word,pos2,suggestions); res += ({ ({ words[row],suggestions }) });; pos=pos2-1+sizeof(word); break; case '#': //misspelled sscanf(ispell_data[i],"# %s %d",word,pos2); res += ({ ({ words[row],"-" }) }); pos=pos2-1+sizeof(word); break;
fb74971997-09-16Per Hedbor  } } }
c2dc4a2000-02-22Stefan Wallström  return res;
fb74971997-09-16Per Hedbor  } }
7ec4e32000-04-06Kenneth Johansson  TAGDOCUMENTATION; #ifdef manual constant tagdoc=([
9b03652001-03-07Kenneth Johansson "spell":#"<desc cont='cont'><p><short> Checks words for spelling problems.</short> The spellchecker uses the ispell dictionary. </p></desc>
7ec4e32000-04-06Kenneth Johansson 
9b03652001-03-07Kenneth Johansson <attr name='dict' value='american,others'><p> Select dictionary to use in the spellchecking. American is default.</p>
7ec4e32000-04-06Kenneth Johansson </attr>
9b03652001-03-07Kenneth Johansson <attr name='prestate' value='string'><p> What prestate to use.</p>
7ec4e32000-04-06Kenneth Johansson </attr>
9b03652001-03-07Kenneth Johansson <attr name='report' value='popup,table'><p>
7ec4e32000-04-06Kenneth Johansson  Either recieve the spellreport as a popup-window when clicking on the
9b03652001-03-07Kenneth Johansson  misspelled word or as a table with all misspelled words.</p>
7ec4e32000-04-06Kenneth Johansson </attr>",
9b03652001-03-07Kenneth Johansson 
7ec4e32000-04-06Kenneth Johansson  ]); #endif