HTMLTransformer.Mod 95 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435
  1. MODULE HTMLTransformer; (** AUTHOR "Simon L. Keel"; PURPOSE "transforming HTML to BB-text"; *)
  2. IMPORT
  3. WebBrowserComponents, XMLTransformer,
  4. Strings, XML, XMLObjects, DynamicStrings, UTF8Strings, WMGraphics, KernelLog, WMEvents, WMCharCodes,
  5. WMComponents, WMRectangles, WMTextView, TextUtilities, Texts, WMStandardComponents,
  6. WMMessages, Streams, WMEditors, WMPopups, Messages := WMMessages;
  7. CONST
  8. verbose = TRUE;
  9. (* default generic font families *)
  10. (* Note: All font-names are case-sensitive! *)
  11. defSerif = "TimesNewRoman";
  12. defSansSerif = "Arial";
  13. defCursive = "ComicSansMS";
  14. defFantasy = "Arial";
  15. defMonospace = "CourierNew";
  16. defaultFont = "Oberon"; (* the default browser-font is defSerif; defaultFont is only used, if defSerif doesn't exist! *)
  17. (* current text is *)
  18. cText = 0;
  19. cNewLine = 1;
  20. cParagraph = 2;
  21. alignLeft = 0;
  22. alignCenter = 1;
  23. alignRight = 2;
  24. alignJustify = 3;
  25. VAR
  26. serif : ARRAY 64 OF CHAR;
  27. sansSerif : ARRAY 64 OF CHAR;
  28. cursive : ARRAY 64 OF CHAR;
  29. fantasy : ARRAY 64 OF CHAR;
  30. monospace : ARRAY 64 OF CHAR;
  31. TYPE
  32. String = Strings.String;
  33. VisualComponent = WMComponents.VisualComponent;
  34. CharsetConvProc = PROCEDURE {DELEGATE} (VAR input : ARRAY OF CHAR) : String;
  35. TextStyle = RECORD
  36. font : String;
  37. size : LONGINT;
  38. style : LONGINT;
  39. color : LONGINT;
  40. bgcolorPresent : BOOLEAN;
  41. bgcolor : LONGINT;
  42. link : String;
  43. linktarget : String;
  44. shift : LONGINT;
  45. align : LONGINT;
  46. indent : LONGINT;
  47. enumtype : LONGINT;
  48. preformatted : BOOLEAN;
  49. form : Form;
  50. END;
  51. OLULStackItem=POINTER TO RECORD
  52. prev : OLULStackItem;
  53. value : LONGINT;
  54. END;
  55. EmbeddedObject*=POINTER TO RECORD
  56. prev* : EmbeddedObject;
  57. object* : VisualComponent;
  58. END;
  59. Transformer* = OBJECT
  60. VAR
  61. doc: XML.Container;
  62. url : String;
  63. baseAddress : String;
  64. baseTarget : String;
  65. sequencer : WMMessages.MsgSequencer;
  66. initWidth : LONGINT;
  67. loadLink* : WMEvents.EventListener;
  68. charset : String;
  69. frameName : String;
  70. txtElem: XML.Element;
  71. paragraph : XML.Element;
  72. title-: String;
  73. pageBgColor- : LONGINT;
  74. bgImage- : String;
  75. embeddedObjectsList- : EmbeddedObject;
  76. textColor : LONGINT;
  77. linkColor : LONGINT;
  78. vlinkColor : LONGINT;
  79. alinkColor : LONGINT;
  80. crlfStr : String;
  81. crlfDoubleStr : String;
  82. charsetConv : CharsetConvProc;
  83. currentText : LONGINT;
  84. olulStackTop : OLULStackItem;
  85. ulDepth : LONGINT;
  86. inDL : BOOLEAN;
  87. currentAlign : LONGINT;
  88. currentIndent : LONGINT;
  89. form : Form;
  90. formButton : FormButton;
  91. formCheckbox : FormCheckbox;
  92. formTextInput : FormTextInput;
  93. formRadioButton : FormRadioButton;
  94. formMenu : FormMenu;
  95. formHiddenControl : FormHiddenControl;
  96. initAlignment : LONGINT;
  97. isTableContent : BOOLEAN;
  98. PROCEDURE &Init*(doc: XML.Container; url : String; initWidth : LONGINT; loadLink : WMEvents.EventListener; charset : String; frameName : String);
  99. VAR
  100. crlf : ARRAY 5 OF CHAR;
  101. BEGIN
  102. SELF.doc := doc;
  103. SELF.url := url;
  104. SELF.baseAddress := url;
  105. SELF.initWidth := initWidth;
  106. SELF.loadLink := loadLink;
  107. crlf[0] := 0DX; crlf[1] := 0AX; crlf[2] := 0X;
  108. crlfStr := Strings.NewString(crlf);
  109. crlf[2] := 0DX; crlf[3] := 0AX; crlf[4] := 0X;
  110. crlfDoubleStr := Strings.NewString(crlf);
  111. IF charset # NIL THEN
  112. charsetConv := GetCharsetConverter(charset^);
  113. SELF.charset := charset;
  114. ELSE
  115. charsetConv := GetCharsetConverter("iso8859-1");
  116. SELF.charset := Strings.NewString("iso8859-1");
  117. END;
  118. SELF.frameName := frameName;
  119. textColor := 0000000H;
  120. linkColor := 00000EEH;
  121. vlinkColor := 0551A8BH;
  122. alinkColor := 0EE0000H;
  123. pageBgColor := 0FFFFFFH;
  124. currentText := cParagraph;
  125. ulDepth := 0;
  126. inDL := FALSE;
  127. initAlignment := alignLeft;
  128. END Init;
  129. PROCEDURE Transform*() : XML.Document;
  130. VAR
  131. bbtTxt: XML.Document;
  132. xmlDecl: XML.XMLDecl;
  133. pi: XML.ProcessingInstruction;
  134. s: String;
  135. style : TextStyle;
  136. BEGIN
  137. NEW(bbtTxt);
  138. (* add header *)
  139. NEW(xmlDecl);
  140. s := Strings.NewString("1.0");
  141. xmlDecl.SetVersion(s^);
  142. s := Strings.NewString("UTF-8");
  143. xmlDecl.SetEncoding(s^);
  144. bbtTxt.AddContent(xmlDecl);
  145. NEW(pi);
  146. s := Strings.NewString("bluebottle format");
  147. pi.SetTarget(s^);
  148. s := Strings.NewString('version="0.1"');
  149. pi.SetInstruction(s^);
  150. bbtTxt.AddContent(pi);
  151. NEW(pi);
  152. s := Strings.NewString('xml-stylesheet type="text/xsl"');
  153. pi.SetTarget(s^);
  154. s := Strings.NewString('href="http://bluebottle.ethz.ch/bluebottle.xsl"');
  155. pi.SetInstruction(s^);
  156. bbtTxt.AddContent(pi);
  157. NEW(txtElem);
  158. s := Strings.NewString("Text");
  159. txtElem.SetName(s^);
  160. bbtTxt.AddContent(txtElem);
  161. style.font := Strings.NewString(serif);
  162. style.size := 3;
  163. style.style := 0;
  164. style.color := textColor;
  165. style.bgcolorPresent := FALSE;
  166. style.shift := 0;
  167. style.align := initAlignment;
  168. style.indent := 0;
  169. style.enumtype := 0;
  170. style.preformatted := FALSE;
  171. style.form := form;
  172. currentAlign := -1;
  173. currentIndent := -1;
  174. SetAlignmentAndIndent(style.align, style.indent);
  175. TransformContent(doc, style);
  176. RETURN bbtTxt;
  177. END Transform;
  178. PROCEDURE TransformContent(container : XML.Container; style : TextStyle);
  179. VAR
  180. enum: XMLObjects.Enumerator;
  181. p : ANY;
  182. BEGIN
  183. enum := container.GetContents();
  184. WHILE (enum.HasMoreElements()) DO
  185. p := enum.GetNext();
  186. IF p IS XML.Element THEN
  187. TransformElement(p(XML.Element), style);
  188. ELSIF (p IS XML.ArrayChars) & ~(p IS XML.Comment) THEN
  189. AddText(p(XML.ArrayChars).GetStr(), style);
  190. END;
  191. END;
  192. END TransformContent;
  193. PROCEDURE GetText(container : XML.Container) : String;
  194. VAR
  195. enum: XMLObjects.Enumerator;
  196. p : ANY;
  197. text, s : String;
  198. BEGIN
  199. text := Strings.NewString("");
  200. enum := container.GetContents();
  201. WHILE (enum.HasMoreElements()) DO
  202. p := enum.GetNext();
  203. IF (p IS XML.ArrayChars) & ~(p IS XML.Comment) THEN
  204. s := p(XML.ArrayChars).GetStr();
  205. text := Strings.ConcatToNew(text^, s^);
  206. END;
  207. END;
  208. RETURN text;
  209. END GetText;
  210. PROCEDURE TransformElement(elem : XML.Element; style : TextStyle);
  211. VAR
  212. name, s, s2, s3 : String;
  213. enum: XMLObjects.Enumerator;
  214. p : ANY;
  215. i, j, res : LONGINT;
  216. pos: SIZE;
  217. exitLoop : BOOLEAN;
  218. aoc : ARRAY 16 OF CHAR;
  219. olulStackItem : OLULStackItem;
  220. b : BOOLEAN;
  221. oldForm : Form;
  222. PROCEDURE ul;
  223. BEGIN
  224. IF olulStackTop = NIL THEN
  225. NewParagraph(FALSE);
  226. ELSE
  227. NewLine(FALSE);
  228. END;
  229. INC(style.indent);
  230. INC(ulDepth);
  231. s := GetElemAttributeValue(elem, "type", TRUE);
  232. IF s#NIL THEN
  233. IF s^="square" THEN
  234. style.enumtype := 1;
  235. ELSIF s^="circle" THEN
  236. style.enumtype := 2;
  237. ELSE (* "disc" *)
  238. style.enumtype := 0;
  239. END;
  240. ELSE
  241. IF ulDepth = 2 THEN
  242. style.enumtype := 2; (* circle *)
  243. ELSIF ulDepth >= 3 THEN
  244. style.enumtype := 1; (* square *)
  245. ELSE
  246. style.enumtype := 0; (* "disc" *)
  247. END;
  248. END;
  249. NEW(olulStackItem);
  250. olulStackItem.prev := olulStackTop;
  251. olulStackTop := olulStackItem;
  252. olulStackItem.value := 1;
  253. TransformContent(elem, style);
  254. olulStackTop := olulStackTop.prev;
  255. DEC(ulDepth);
  256. IF olulStackTop = NIL THEN
  257. NewParagraph(FALSE);
  258. ELSE
  259. NewLine(FALSE);
  260. END;
  261. END ul;
  262. PROCEDURE textInput(isPassword : BOOLEAN);
  263. BEGIN
  264. s := GetElemAttributeValue(elem, "name", FALSE);
  265. s2 := GetElemAttributeValue(elem, "value", FALSE);
  266. IF s2 = NIL THEN s2 := Strings.NewString("") END;
  267. s3 := GetElemAttributeValue(elem, "size", FALSE);
  268. IF s3 # NIL THEN
  269. Strings.StrToInt(s3^, i);
  270. ELSE
  271. i := 20
  272. END;
  273. s3 := GetElemAttributeValue(elem, "maxlength", FALSE);
  274. IF s3 # NIL THEN
  275. Strings.StrToInt(s3^, j);
  276. ELSE
  277. j := 0
  278. END;
  279. NEW(formTextInput, s, s2, i, j, isPassword);
  280. style.form.AddFormComponent(formTextInput);
  281. AddVisualComponent(formTextInput.editor, style);
  282. END textInput;
  283. BEGIN
  284. name := elem.GetName();
  285. CASE name[0] OF
  286. |"A":
  287. IF name^="A" THEN
  288. s := GetElemAttributeValue(elem, "name", FALSE);
  289. IF s#NIL THEN
  290. AddLabel(s);
  291. END;
  292. s := GetElemAttributeValue(elem, "href", FALSE);
  293. IF s#NIL THEN
  294. style.color := linkColor;
  295. Strings.TrimWS(s^);
  296. style.link := ResolveAddress(baseAddress, s);
  297. s := GetElemAttributeValue(elem, "target", FALSE);
  298. IF s#NIL THEN
  299. Strings.TrimWS(s^);
  300. style.linktarget := s;
  301. ELSIF baseTarget # NIL THEN
  302. style.linktarget := baseTarget;
  303. ELSE
  304. style.linktarget := frameName;
  305. END;
  306. END;
  307. TransformContent(elem, style);
  308. ELSIF name^="ABBR" THEN
  309. TransformContent(elem, style);
  310. ELSIF name^="ACRONYM" THEN
  311. TransformContent(elem, style);
  312. ELSIF name^="ADDRESS" THEN
  313. IF style.style = 0 THEN
  314. style.style := 2;
  315. ELSIF style.style = 1 THEN
  316. style.style := 3;
  317. END;
  318. TransformContent(elem, style);
  319. NewLine(FALSE);
  320. ELSIF name^="APPLET" THEN
  321. (* to be implemented *)
  322. TransformContent(elem, style);
  323. ELSIF name^="AREA" THEN
  324. (* to be implemented *)
  325. TransformContent(elem, style);
  326. ELSE TransformContent(elem, style);
  327. END;
  328. |"B":
  329. IF name^="B" THEN
  330. IF style.style = 0 THEN
  331. style.style := 1;
  332. ELSIF style.style = 2 THEN
  333. style.style := 3;
  334. END;
  335. TransformContent(elem, style);
  336. ELSIF name^="BASE" THEN
  337. s := GetElemAttributeValue(elem, "href", FALSE);
  338. IF s#NIL THEN
  339. baseAddress := s;
  340. END;
  341. baseTarget := GetElemAttributeValue(elem, "target", FALSE);
  342. ELSIF name^="BASEFONT" THEN
  343. (* to be implemented *)
  344. TransformContent(elem, style);
  345. ELSIF name^="BDO" THEN
  346. (* to be implemented *)
  347. TransformContent(elem, style);
  348. ELSIF name^="BIG" THEN
  349. IF style.size < 7 THEN INC(style.size); END;
  350. TransformContent(elem, style);
  351. ELSIF name^="BLOCKQUOTE" THEN
  352. NewParagraph(FALSE);
  353. INC(style.indent);
  354. TransformContent(elem, style);
  355. NewParagraph(FALSE);
  356. ELSIF name^="BODY" THEN
  357. s := GetElemAttributeValue(elem, "bgcolor", TRUE);
  358. IF s#NIL THEN pageBgColor := GetColor(s); END;
  359. s := GetElemAttributeValue(elem, "text", TRUE);
  360. IF s#NIL THEN
  361. textColor := GetColor(s);
  362. style.color := textColor;
  363. END;
  364. s := GetElemAttributeValue(elem, "link", TRUE);
  365. IF s#NIL THEN linkColor := GetColor(s); END;
  366. s := GetElemAttributeValue(elem, "vlink", TRUE);
  367. IF s#NIL THEN vlinkColor := GetColor(s); END;
  368. s := GetElemAttributeValue(elem, "alink", TRUE);
  369. IF s#NIL THEN alinkColor := GetColor(s); END;
  370. s := GetElemAttributeValue(elem, "background", FALSE);
  371. IF s#NIL THEN
  372. bgImage := ResolveAddress(baseAddress, s);
  373. END;
  374. (* TODO: backround image *)
  375. TransformContent(elem, style);
  376. ELSIF name^="BR" THEN
  377. NewLine(TRUE);
  378. ELSIF name^="BUTTON" THEN
  379. (* to be implemented *)
  380. TransformContent(elem, style);
  381. ELSIF Strings.StartsWith2("BB:", name^) THEN
  382. XMLTransformer.AddContentsOf(XMLTransformer.Transform(elem), txtElem);
  383. currentAlign := -1;
  384. currentIndent := -1;
  385. SetAlignmentAndIndent(style.align, style.indent);
  386. ELSE TransformContent(elem, style);
  387. END;
  388. |"C":
  389. IF name^="CENTER" THEN
  390. NewLine(TRUE);
  391. style.align := alignCenter;
  392. TransformContent(elem, style);
  393. NewLine(TRUE);
  394. ELSIF name^="CITE" THEN
  395. IF style.style = 0 THEN
  396. style.style := 2;
  397. ELSIF style.style = 1 THEN
  398. style.style := 3;
  399. END;
  400. TransformContent(elem, style);
  401. ELSIF name^="CODE" THEN
  402. style.font := Strings.NewString(monospace);
  403. TransformContent(elem, style);
  404. ELSE TransformContent(elem, style);
  405. END;
  406. |"D":
  407. IF name^="DD" THEN
  408. INC(style.indent);
  409. TransformContent(elem, style);
  410. NewLine(FALSE);
  411. ELSIF name^="DEL" THEN
  412. (* to be implemented *)
  413. TransformContent(elem, style);
  414. ELSIF name^="DFN" THEN
  415. IF style.style = 0 THEN
  416. style.style := 2;
  417. ELSIF style.style = 1 THEN
  418. style.style := 3;
  419. END;
  420. TransformContent(elem, style);
  421. ELSIF name^="DIR" THEN
  422. ul();
  423. ELSIF name^="DIV" THEN
  424. s := GetElemAttributeValue(elem, "align", TRUE);
  425. IF s # NIL THEN
  426. Strings.TrimWS(s^);
  427. IF s^ = "left" THEN
  428. style.align := alignLeft;
  429. ELSIF s^ = "center" THEN
  430. style.align := alignCenter;
  431. ELSIF s^ = "right" THEN
  432. style.align := alignRight;
  433. ELSIF s^ = "justify" THEN
  434. style.align := alignJustify;
  435. END;
  436. END;
  437. NewLine(TRUE);
  438. TransformContent(elem, style);
  439. NewLine(TRUE);
  440. ELSIF name^="DL" THEN
  441. IF inDL THEN
  442. INC(style.indent);
  443. NewLine(FALSE);
  444. ELSE
  445. NewParagraph(FALSE);
  446. END;
  447. b := inDL;
  448. inDL := TRUE;
  449. TransformContent(elem, style);
  450. IF b THEN
  451. NewLine(FALSE);
  452. ELSE
  453. NewParagraph(FALSE);
  454. END;
  455. inDL := b;
  456. ELSIF name^="DT" THEN
  457. TransformContent(elem, style);
  458. NewLine(FALSE);
  459. ELSE TransformContent(elem, style);
  460. END;
  461. |"E":
  462. IF name^="EM" THEN
  463. IF style.style = 0 THEN
  464. style.style := 2;
  465. ELSIF style.style = 1 THEN
  466. style.style := 3;
  467. END;
  468. TransformContent(elem, style);
  469. ELSE TransformContent(elem, style);
  470. END;
  471. |"F":
  472. IF name^="FIELDSET" THEN
  473. (* to be implemented *)
  474. TransformContent(elem, style);
  475. ELSIF name^="FONT" THEN
  476. s := GetElemAttributeValue(elem, "size", FALSE);
  477. IF s#NIL THEN
  478. Strings.Copy(s^, 0, LEN(s^)-1, aoc);
  479. Strings.TrimLeft(aoc, ' ');
  480. Strings.StrToInt(aoc, res);
  481. IF (aoc[0]='+') OR (aoc[0]='-') THEN
  482. style.size := style.size + res;
  483. ELSE
  484. style.size := res;
  485. END;
  486. IF style.size < 1 THEN
  487. style.size := 1;
  488. ELSIF style.size > 7 THEN
  489. style.size := 7;
  490. END;
  491. END;
  492. s := GetElemAttributeValue(elem, "color", TRUE);
  493. IF s#NIL THEN style.color := GetColor(s); END;
  494. s := GetElemAttributeValue(elem, "face", FALSE);
  495. IF s#NIL THEN style.font := GetExistingFontName(s); END;
  496. TransformContent(elem, style);
  497. ELSIF name^="FORM" THEN
  498. oldForm := style.form;
  499. s := GetElemAttributeValue(elem, "action", FALSE);
  500. IF s = NIL THEN
  501. s := baseAddress;
  502. ELSE
  503. s := ResolveAddress(baseAddress, s);
  504. END;
  505. NEW(style.form, s, loadLink);
  506. TransformContent(elem, style);
  507. style.form := oldForm;
  508. ELSE TransformContent(elem, style);
  509. END;
  510. |"G":
  511. TransformContent(elem, style);
  512. |"H":
  513. IF name^="H1" THEN
  514. s := GetElemAttributeValue(elem, "align", TRUE);
  515. IF s # NIL THEN
  516. Strings.TrimWS(s^);
  517. IF s^ = "left" THEN
  518. style.align := alignLeft;
  519. ELSIF s^ = "center" THEN
  520. style.align := alignCenter;
  521. ELSIF s^ = "right" THEN
  522. style.align := alignRight;
  523. ELSIF s^ = "justify" THEN
  524. style.align := alignJustify;
  525. END;
  526. END;
  527. NewParagraph(FALSE);
  528. style.size := 6;
  529. style.style := 1;
  530. TransformContent(elem, style);
  531. NewParagraph(FALSE);
  532. ELSIF name^="H2" THEN
  533. s := GetElemAttributeValue(elem, "align", TRUE);
  534. IF s # NIL THEN
  535. Strings.TrimWS(s^);
  536. IF s^ = "left" THEN
  537. style.align := alignLeft;
  538. ELSIF s^ = "center" THEN
  539. style.align := alignCenter;
  540. ELSIF s^ = "right" THEN
  541. style.align := alignRight;
  542. ELSIF s^ = "justify" THEN
  543. style.align := alignJustify;
  544. END;
  545. END;
  546. NewParagraph(FALSE);
  547. style.size := 5;
  548. style.style := 1;
  549. TransformContent(elem, style);
  550. NewParagraph(FALSE);
  551. ELSIF name^="H3" THEN
  552. s := GetElemAttributeValue(elem, "align", TRUE);
  553. IF s # NIL THEN
  554. Strings.TrimWS(s^);
  555. IF s^ = "left" THEN
  556. style.align := alignLeft;
  557. ELSIF s^ = "center" THEN
  558. style.align := alignCenter;
  559. ELSIF s^ = "right" THEN
  560. style.align := alignRight;
  561. ELSIF s^ = "justify" THEN
  562. style.align := alignJustify;
  563. END;
  564. END;
  565. NewParagraph(FALSE);
  566. style.size := 4;
  567. style.style := 1;
  568. TransformContent(elem, style);
  569. NewParagraph(FALSE);
  570. ELSIF name^="H4" THEN
  571. s := GetElemAttributeValue(elem, "align", TRUE);
  572. IF s # NIL THEN
  573. Strings.TrimWS(s^);
  574. IF s^ = "left" THEN
  575. style.align := alignLeft;
  576. ELSIF s^ = "center" THEN
  577. style.align := alignCenter;
  578. ELSIF s^ = "right" THEN
  579. style.align := alignRight;
  580. ELSIF s^ = "justify" THEN
  581. style.align := alignJustify;
  582. END;
  583. END;
  584. NewParagraph(FALSE);
  585. style.size := 3;
  586. style.style := 1;
  587. TransformContent(elem, style);
  588. NewParagraph(FALSE);
  589. ELSIF name^="H5" THEN
  590. s := GetElemAttributeValue(elem, "align", TRUE);
  591. IF s # NIL THEN
  592. Strings.TrimWS(s^);
  593. IF s^ = "left" THEN
  594. style.align := alignLeft;
  595. ELSIF s^ = "center" THEN
  596. style.align := alignCenter;
  597. ELSIF s^ = "right" THEN
  598. style.align := alignRight;
  599. ELSIF s^ = "justify" THEN
  600. style.align := alignJustify;
  601. END;
  602. END;
  603. NewParagraph(FALSE);
  604. style.size := 2;
  605. style.style := 1;
  606. TransformContent(elem, style);
  607. NewParagraph(FALSE);
  608. ELSIF name^="H6" THEN
  609. s := GetElemAttributeValue(elem, "align", TRUE);
  610. IF s # NIL THEN
  611. Strings.TrimWS(s^);
  612. IF s^ = "left" THEN
  613. style.align := alignLeft;
  614. ELSIF s^ = "center" THEN
  615. style.align := alignCenter;
  616. ELSIF s^ = "right" THEN
  617. style.align := alignRight;
  618. ELSIF s^ = "justify" THEN
  619. style.align := alignJustify;
  620. END;
  621. END;
  622. NewParagraph(FALSE);
  623. style.size := 1;
  624. style.style := 1;
  625. TransformContent(elem, style);
  626. NewParagraph(FALSE);
  627. ELSIF name^="HEAD" THEN
  628. TransformContent(elem, style);
  629. ELSIF name^="HR" THEN
  630. s := GetElemAttributeValue(elem, "align", TRUE);
  631. IF s # NIL THEN
  632. Strings.TrimWS(s^);
  633. IF s^ = "left" THEN
  634. style.align := alignLeft;
  635. ELSIF s^ = "right" THEN
  636. style.align := alignRight;
  637. ELSE
  638. style.align := alignCenter;
  639. END;
  640. ELSE
  641. style.align := alignCenter;
  642. END;
  643. NewLine(FALSE);
  644. AddHR(style.align);
  645. NewLine(FALSE);
  646. ELSIF name^="HTML" THEN
  647. TransformContent(elem, style);
  648. ELSE TransformContent(elem, style);
  649. END;
  650. |"I":
  651. IF name^="I" THEN
  652. IF style.style = 0 THEN
  653. style.style := 2;
  654. ELSIF style.style = 1 THEN
  655. style.style := 3;
  656. END;
  657. TransformContent(elem, style);
  658. ELSIF name^="IFRAME" THEN
  659. (* to be implemented *)
  660. TransformContent(elem, style);
  661. ELSIF name^="IMG" THEN
  662. i := -1; j := -1;
  663. s := GetElemAttributeValue(elem, "width", FALSE);
  664. IF s#NIL THEN
  665. Strings.Copy(s^, 0, LEN(s^)-1, aoc);
  666. Strings.StrToInt(aoc, i);
  667. END;
  668. s := GetElemAttributeValue(elem, "height", FALSE);
  669. IF s#NIL THEN
  670. Strings.Copy(s^, 0, LEN(s^)-1, aoc);
  671. Strings.StrToInt(aoc, j);
  672. END;
  673. s := GetElemAttributeValue(elem, "src", FALSE);
  674. IF s#NIL THEN
  675. s := ResolveAddress(baseAddress, s);
  676. AddImage(s, i, j, style);
  677. END;
  678. ELSIF name^="INPUT" THEN
  679. IF style.form # NIL THEN
  680. s := GetElemAttributeValue(elem, "type", TRUE);
  681. IF s#NIL THEN
  682. IF s^="checkbox" THEN
  683. s := GetElemAttributeValue(elem, "name", FALSE);
  684. s2 := GetElemAttributeValue(elem, "value", FALSE);
  685. IF s2 = NIL THEN s2 := Strings.NewString("on") END;
  686. s3 := GetElemAttributeValue(elem, "checked", FALSE);
  687. b := FALSE;
  688. IF s3 # NIL THEN
  689. b := TRUE;
  690. Strings.TrimWS(s^);
  691. IF s3^ = "no" THEN
  692. b := FALSE;
  693. END;
  694. END;
  695. NEW(formCheckbox, s, s2, b);
  696. AddText(Strings.NewString(" "), style); AddText(Strings.NewString(" "), style); AddText(Strings.NewString(" "), style);
  697. style.form.AddFormComponent(formCheckbox);
  698. AddVisualComponent(formCheckbox.checkbox, style);
  699. AddText(Strings.NewString(" "), style);
  700. ELSIF s^="radio" THEN
  701. s := GetElemAttributeValue(elem, "name", FALSE);
  702. IF s = NIL THEN s := Strings.NewString("radioButton") END;
  703. s2 := GetElemAttributeValue(elem, "value", FALSE);
  704. IF s2 = NIL THEN s2 := Strings.NewString("on") END;
  705. s3 := GetElemAttributeValue(elem, "checked", FALSE);
  706. b := FALSE;
  707. IF s3 # NIL THEN
  708. b := TRUE;
  709. Strings.TrimWS(s^);
  710. IF s3^ = "no" THEN
  711. b := FALSE;
  712. END;
  713. END;
  714. NEW(formRadioButton, s, s2, b);
  715. style.form.AddRadioButton(formRadioButton);
  716. AddText(Strings.NewString(" "), style); AddText(Strings.NewString(" "), style); AddText(Strings.NewString(" "), style);
  717. AddVisualComponent(formRadioButton.radioButton, style);
  718. AddText(Strings.NewString(" "), style);
  719. ELSIF s^="submit" THEN
  720. s := GetElemAttributeValue(elem, "name", FALSE);
  721. s2 := GetElemAttributeValue(elem, "value", FALSE);
  722. IF s2 = NIL THEN s2 := Strings.NewString("Submit Query") END;
  723. NEW(formButton, s, s2, style.form.Send);
  724. style.form.AddFormComponent(formButton);
  725. AddVisualComponent(formButton.button, style);
  726. AddText(Strings.NewString(" "), style);
  727. ELSIF s^="reset" THEN
  728. s := GetElemAttributeValue(elem, "name", FALSE);
  729. s2 := GetElemAttributeValue(elem, "value", FALSE);
  730. IF s2 = NIL THEN s2 := Strings.NewString("Reset") END;
  731. NEW(formButton, s, s2, style.form.Reset);
  732. style.form.AddFormComponent(formButton);
  733. AddVisualComponent(formButton.button, style);
  734. AddText(Strings.NewString(" "), style);
  735. ELSIF s^="file" THEN
  736. ELSIF s^="hidden" THEN
  737. s := GetElemAttributeValue(elem, "name", FALSE);
  738. s2 := GetElemAttributeValue(elem, "value", FALSE);
  739. IF s2 = NIL THEN s2 := Strings.NewString("") END;
  740. NEW(formHiddenControl, s, s2);
  741. style.form.AddFormComponent(formHiddenControl);
  742. ELSIF s^="image" THEN
  743. ELSIF s^="button" THEN
  744. s := GetElemAttributeValue(elem, "name", FALSE);
  745. s2 := GetElemAttributeValue(elem, "value", FALSE);
  746. IF s2 = NIL THEN s2 := Strings.NewString("") END;
  747. NEW(formButton, s, s2, NIL); (* when implementing scripts: replace NIL with a function *)
  748. style.form.AddFormComponent(formButton);
  749. AddVisualComponent(formButton.button, style);
  750. AddText(Strings.NewString(" "), style);
  751. ELSIF s^="password" THEN
  752. textInput(TRUE);
  753. ELSE
  754. textInput(FALSE);
  755. END;
  756. ELSE
  757. textInput(FALSE);
  758. END;
  759. END;
  760. ELSIF name^="INS" THEN
  761. (* to be implemented *)
  762. TransformContent(elem, style);
  763. ELSIF name^="ISINDEX" THEN
  764. (* to be implemented *)
  765. TransformContent(elem, style);
  766. ELSE TransformContent(elem, style);
  767. END;
  768. |"J":
  769. TransformContent(elem, style);
  770. |"K":
  771. IF name^="KBD" THEN
  772. style.font := Strings.NewString(monospace);
  773. TransformContent(elem, style);
  774. ELSE TransformContent(elem, style);
  775. END;
  776. |"L":
  777. IF name^="LABEL" THEN
  778. (* to be implemented *)
  779. TransformContent(elem, style);
  780. ELSIF name^="LEGEND" THEN
  781. (* to be implemented *)
  782. TransformContent(elem, style);
  783. ELSIF name^="LI" THEN
  784. NewLine(FALSE);
  785. IF olulStackTop#NIL THEN
  786. s := GetElemAttributeValue(elem, "value", FALSE);
  787. IF s#NIL THEN
  788. Strings.StrToInt(s^, olulStackTop.value);
  789. END;
  790. END;
  791. i := style.enumtype;
  792. s := GetElemAttributeValue(elem, "type", FALSE);
  793. IF s#NIL THEN
  794. IF s^="square" THEN
  795. i := 1;
  796. ELSIF s^="circle" THEN
  797. i := 2;
  798. ELSE (* "disc" *)
  799. i := 0;
  800. END;
  801. END;
  802. CASE i OF
  803. | 1 : s := Strings.NewString("&#9633; "); (* square *)
  804. | 2 : s := Strings.NewString("&#9675; "); (* circle *)
  805. | 3 : IF olulStackTop#NIL THEN (* 1, 2, 3... *)
  806. Strings.IntToStr(olulStackTop.value, aoc);
  807. j :=Strings.Length(aoc);
  808. IF (j+2) <= (LEN(aoc)-1) THEN
  809. aoc[j]:='.'; aoc[j+1]:=' '; aoc[j+2]:=0X;
  810. END;
  811. ELSE
  812. aoc := "0. ";
  813. END;
  814. s := Strings.NewString(aoc);
  815. | 4 : IF olulStackTop#NIL THEN (* a, b, c... *)
  816. s := IntToABCString(olulStackTop.value, FALSE);
  817. ELSE
  818. s := Strings.NewString("0. ");
  819. END;
  820. | 5 : IF olulStackTop#NIL THEN (* A, B, C... *)
  821. s := IntToABCString(olulStackTop.value, TRUE);
  822. ELSE
  823. s := Strings.NewString("0. ");
  824. END;
  825. | 6 : IF olulStackTop#NIL THEN (* i, ii, iii... *)
  826. s := IntToRomanString(olulStackTop.value, FALSE);
  827. ELSE
  828. s := Strings.NewString("0. ");
  829. END;
  830. | 7 : IF olulStackTop#NIL THEN (* I, II, III... *)
  831. s := IntToRomanString(olulStackTop.value, TRUE);
  832. ELSE
  833. s := Strings.NewString("0. ");
  834. END;
  835. ELSE (* 0 *)
  836. s := Strings.NewString("&#9679; "); (* disc *)
  837. END;
  838. AddText(s, style);
  839. IF olulStackTop#NIL THEN INC(olulStackTop.value); END;
  840. TransformContent(elem, style);
  841. NewLine(FALSE);
  842. ELSIF name^="LINK" THEN
  843. (* ignore *)
  844. ELSE TransformContent(elem, style);
  845. END;
  846. |"M":
  847. IF name^="MAP" THEN
  848. (* to be implemented *)
  849. TransformContent(elem, style);
  850. ELSIF name^="MENU" THEN
  851. ul();
  852. ELSIF name^="META" THEN
  853. s := GetElemAttributeValue(elem, "content", TRUE);
  854. IF s#NIL THEN
  855. pos := Strings.Pos("charset", s^);
  856. IF i # -1 THEN
  857. pos := Strings.IndexOfByte('=', pos+7, s^) + 1;
  858. IF pos < Strings.Length(s^) THEN
  859. s := Strings.Substring2(pos, s^);
  860. charsetConv := GetCharsetConverter(s^);
  861. charset := s;
  862. END;
  863. END;
  864. END;
  865. ELSE TransformContent(elem, style);
  866. END;
  867. |"N":
  868. (* Frames are handeled in WebBrowserPanel.HTMLPanel
  869. ELSIF name^="NOFRAMES" THEN
  870. *)
  871. IF name^="NOSCRIPT" THEN
  872. (* TODO: remove if scripts are implemented *)
  873. TransformContent(elem, style);
  874. ELSE TransformContent(elem, style);
  875. END;
  876. |"O":
  877. IF name^="OBJECT" THEN
  878. (* to be implemented *)
  879. TransformContent(elem, style);
  880. ELSIF name^="OL" THEN
  881. IF olulStackTop = NIL THEN
  882. NewParagraph(FALSE);
  883. ELSE
  884. NewLine(FALSE);
  885. END;
  886. INC(style.indent);
  887. s := GetElemAttributeValue(elem, "type", FALSE);
  888. IF s#NIL THEN
  889. IF s^="a" THEN
  890. style.enumtype := 4;
  891. ELSIF s^="A" THEN
  892. style.enumtype := 5;
  893. ELSIF s^="i" THEN
  894. style.enumtype := 6;
  895. ELSIF s^="I" THEN
  896. style.enumtype := 7;
  897. ELSE (* "1" *)
  898. style.enumtype := 3;
  899. END;
  900. ELSE
  901. style.enumtype := 3;
  902. END;
  903. NEW(olulStackItem);
  904. olulStackItem.prev := olulStackTop;
  905. olulStackTop := olulStackItem;
  906. s := GetElemAttributeValue(elem, "start", FALSE);
  907. IF s#NIL THEN
  908. Strings.StrToInt(s^, olulStackItem.value);
  909. ELSE
  910. olulStackItem.value := 1;
  911. END;
  912. TransformContent(elem, style);
  913. olulStackTop := olulStackTop.prev;
  914. IF olulStackTop = NIL THEN
  915. NewParagraph(FALSE);
  916. ELSE
  917. NewLine(FALSE);
  918. END;
  919. ELSIF name^="OPTGROUP" THEN
  920. TransformContent(elem, style);
  921. ELSIF name^="OPTION" THEN
  922. IF formMenu # NIL THEN
  923. s := GetElemAttributeValue(elem, "value", FALSE);
  924. s2 := GetElemAttributeValue(elem, "label", FALSE);
  925. IF s2 = NIL THEN
  926. s2 := GetText(elem);
  927. END;
  928. s3 := GetElemAttributeValue(elem, "selected", FALSE);
  929. formMenu.NewItem(s, s2, s3 # NIL);
  930. END;
  931. ELSE TransformContent(elem, style);
  932. END;
  933. |"P":
  934. IF name^="P" THEN
  935. s := GetElemAttributeValue(elem, "align", TRUE);
  936. IF s # NIL THEN
  937. Strings.TrimWS(s^);
  938. IF s^ = "left" THEN
  939. style.align := alignLeft;
  940. ELSIF s^ = "center" THEN
  941. style.align := alignCenter;
  942. ELSIF s^ = "right" THEN
  943. style.align := alignRight;
  944. ELSIF s^ = "justify" THEN
  945. style.align := alignJustify;
  946. END;
  947. END;
  948. NewParagraph(FALSE);
  949. TransformContent(elem, style);
  950. NewParagraph(FALSE);
  951. ELSIF name^="PARAM" THEN
  952. (* to be implemented *)
  953. TransformContent(elem, style);
  954. ELSIF name^="PRE" THEN
  955. NewParagraph(FALSE);
  956. style.preformatted := TRUE;
  957. style.font := Strings.NewString(monospace);
  958. TransformContent(elem, style);
  959. NewParagraph(FALSE);
  960. ELSE TransformContent(elem, style);
  961. END;
  962. |"Q":
  963. IF name^="Q" THEN
  964. AddText(Strings.NewString('"'), style);
  965. TransformContent(elem, style);
  966. AddText(Strings.NewString('"'), style);
  967. ELSE TransformContent(elem, style);
  968. END;
  969. |"R":
  970. TransformContent(elem, style);
  971. |"S":
  972. IF name^="S" THEN
  973. (* to be implemented *)
  974. TransformContent(elem, style);
  975. ELSIF name^="SAMP" THEN
  976. style.font := Strings.NewString(monospace);
  977. TransformContent(elem, style);
  978. ELSIF name^="SCRIPT" THEN
  979. (* ignore *)
  980. ELSIF name^="SELECT" THEN
  981. IF style.form # NIL THEN
  982. s := GetElemAttributeValue(elem, "name", FALSE);
  983. IF s = NIL THEN s := Strings.NewString("defaultMenu") END;
  984. NEW(formMenu, s);
  985. style.form.AddFormComponent(formMenu);
  986. AddVisualComponent(formMenu.button, style);
  987. AddText(Strings.NewString(" "), style);
  988. TransformContent(elem, style);
  989. formMenu := NIL;
  990. END;
  991. ELSIF name^="SMALL" THEN
  992. IF style.size > 1 THEN DEC(style.size); END;
  993. TransformContent(elem, style);
  994. ELSIF name^="SPAN" THEN
  995. TransformContent(elem, style);
  996. ELSIF name^="STRIKE" THEN
  997. (* to be implemented *)
  998. TransformContent(elem, style);
  999. ELSIF name^="STRONG" THEN
  1000. IF style.style = 0 THEN
  1001. style.style := 1;
  1002. ELSIF style.style = 2 THEN
  1003. style.style := 3;
  1004. END;
  1005. TransformContent(elem, style);
  1006. ELSIF name^="STYLE" THEN
  1007. (* ignore *)
  1008. ELSIF name^="SUB" THEN
  1009. IF style.shift = 0 THEN style.shift := 1; END;
  1010. IF style.size >1 THEN DEC(style.size); END;
  1011. TransformContent(elem, style);
  1012. ELSIF name^="SUP" THEN
  1013. IF style.shift = 0 THEN style.shift := -1; END;
  1014. IF style.size >1 THEN DEC(style.size); END;
  1015. TransformContent(elem, style);
  1016. ELSIF name^="SVG" THEN
  1017. AddSVG(elem, style);
  1018. ELSE TransformContent(elem, style);
  1019. END;
  1020. |"T":
  1021. IF name^="TABLE" THEN
  1022. AddTable(elem, style);
  1023. ELSIF name^="TEXTAREA" THEN
  1024. (* to be implemented *)
  1025. TransformContent(elem, style);
  1026. ELSIF name^="TITLE" THEN
  1027. IF title = NIL THEN
  1028. exitLoop := FALSE;
  1029. enum := elem.GetContents();
  1030. WHILE enum.HasMoreElements() & ~exitLoop DO
  1031. p := enum.GetNext();
  1032. IF p IS XML.ArrayChars THEN
  1033. title := p(XML.ArrayChars).GetStr();
  1034. title := ReplaceWhiteSpaces(title);
  1035. title := charsetConv(title^);
  1036. title := TransformCharEnt(title);
  1037. exitLoop := TRUE;
  1038. END;
  1039. END;
  1040. END;
  1041. ELSIF name^="TT" THEN
  1042. style.font := Strings.NewString(monospace);
  1043. TransformContent(elem, style);
  1044. ELSE TransformContent(elem, style);
  1045. END;
  1046. |"U":
  1047. IF name^="U" THEN
  1048. (* to be implemented *)
  1049. TransformContent(elem, style);
  1050. ELSIF name^="UL" THEN
  1051. ul();
  1052. ELSE TransformContent(elem, style);
  1053. END;
  1054. |"V":
  1055. IF name^="VAR" THEN
  1056. IF style.style = 0 THEN
  1057. style.style := 2;
  1058. ELSIF style.style = 1 THEN
  1059. style.style := 3;
  1060. END;
  1061. TransformContent(elem, style);
  1062. ELSE TransformContent(elem, style);
  1063. END;
  1064. ELSE
  1065. TransformContent(elem, style);
  1066. END;
  1067. END TransformElement;
  1068. PROCEDURE SetAlignmentAndIndent(align : LONGINT; indent : LONGINT);
  1069. VAR
  1070. styleAttrPar : XML.Attribute;
  1071. s : String;
  1072. aoc : ARRAY 5 OF CHAR;
  1073. BEGIN
  1074. IF (align # currentAlign) OR (indent # currentIndent) THEN
  1075. NEW(paragraph);
  1076. paragraph.SetName("Paragraph");
  1077. NEW(styleAttrPar); s := Strings.NewString("style"); styleAttrPar.SetName(s^);
  1078. IF align = alignCenter THEN
  1079. s := Strings.NewString("AdHoc 1 ");
  1080. ELSIF align = alignRight THEN
  1081. s := Strings.NewString("AdHoc 2 ");
  1082. ELSIF align = alignJustify THEN
  1083. s := Strings.NewString("AdHoc 3 ");
  1084. ELSE
  1085. s := Strings.NewString("AdHoc 0 "); (* Left-aligned *)
  1086. END;
  1087. IF indent > 0 THEN
  1088. (* firstline indent *)
  1089. Strings.IntToStr(indent * 40, aoc);
  1090. Strings.TrimWS(aoc);
  1091. s := Strings.ConcatToNew(s^, aoc);
  1092. s := Strings.ConcatToNew(s^, " ");
  1093. (* left indent *)
  1094. Strings.IntToStr(indent * 40 + 20, aoc);
  1095. Strings.TrimWS(aoc);
  1096. s := Strings.ConcatToNew(s^, aoc);
  1097. (* right, top, bottom indent *)
  1098. s := Strings.ConcatToNew(s^, " 0 0 0");
  1099. ELSE
  1100. s := Strings.ConcatToNew(s^, "0 0 0 0 0");
  1101. END;
  1102. styleAttrPar.SetValue(s^);
  1103. paragraph.AddAttribute(styleAttrPar);
  1104. txtElem.AddContent(paragraph);
  1105. currentAlign := align;
  1106. currentIndent := indent;
  1107. END;
  1108. END SetAlignmentAndIndent;
  1109. PROCEDURE NewLine(allowMultiple : BOOLEAN);
  1110. VAR
  1111. span : XML.Element;
  1112. styleAttr : XML.Attribute;
  1113. cdata : XML.CDataSect;
  1114. aoc : ARRAY 39 OF CHAR;
  1115. BEGIN
  1116. IF (currentText = cNewLine) & ~allowMultiple THEN RETURN; END;
  1117. currentText := cNewLine;
  1118. NEW(span); span.SetName("Span");
  1119. aoc := "style";
  1120. NEW(styleAttr); styleAttr.SetName(aoc);
  1121. aoc := "AdHoc Oberon 12 0 0 00000000 00000000";
  1122. styleAttr.SetValue(aoc);
  1123. NEW(cdata);
  1124. cdata.SetStr(crlfStr^);
  1125. span.AddAttribute(styleAttr);
  1126. span.AddContent(cdata);
  1127. paragraph.AddContent(span);
  1128. END NewLine;
  1129. PROCEDURE NewParagraph(allowMultiple : BOOLEAN);
  1130. VAR
  1131. span : XML.Element;
  1132. styleAttr : XML.Attribute;
  1133. cdata : XML.CDataSect;
  1134. aoc : ARRAY 39 OF CHAR;
  1135. BEGIN
  1136. IF (currentText = cParagraph) & ~allowMultiple THEN RETURN; END;
  1137. NEW(cdata);
  1138. IF (currentText = cNewLine) THEN
  1139. cdata.SetStr(crlfStr^);
  1140. ELSE
  1141. cdata.SetStr(crlfDoubleStr^);
  1142. END;
  1143. currentText := cParagraph;
  1144. NEW(span); span.SetName("Span");
  1145. aoc := "style";
  1146. NEW(styleAttr); styleAttr.SetName(aoc);
  1147. aoc := "AdHoc Oberon 16 0 0 00000000 00000000";
  1148. styleAttr.SetValue(aoc);
  1149. span.AddAttribute(styleAttr);
  1150. span.AddContent(cdata);
  1151. paragraph.AddContent(span);
  1152. END NewParagraph;
  1153. PROCEDURE AddText(txt : String; style : TextStyle);
  1154. VAR
  1155. fontsize : LONGINT;
  1156. baselineshift : LONGINT;
  1157. span : XML.Element;
  1158. s : String;
  1159. aoc : ARRAY 33 OF CHAR;
  1160. styleAttr : XML.Attribute;
  1161. linkAttr : XML.Attribute;
  1162. cdata : XML.CDataSect;
  1163. dyn : DynamicStrings.DynamicString;
  1164. BEGIN
  1165. SetAlignmentAndIndent(style.align, style.indent);
  1166. IF ~style.preformatted THEN
  1167. IF StringHasNewLine(txt^) & StringIsWhiteSpace(txt^) THEN RETURN; END;
  1168. txt := ReplaceWhiteSpaces(txt);
  1169. END;
  1170. txt := charsetConv(txt^);
  1171. txt := TransformCharEnt(txt);
  1172. fontsize := MapFontSize(style.font, style.size);
  1173. baselineshift := MapBaselineShift(style.size);
  1174. NEW(span); aoc := "Span"; span.SetName(aoc);
  1175. IF style.link # NIL THEN
  1176. NEW(linkAttr); aoc := "link"; linkAttr.SetName(aoc);
  1177. span.AddAttribute(linkAttr);
  1178. s := EncodeLinkData(style.link, style.linktarget, url);
  1179. linkAttr.SetValue(s^);
  1180. END;
  1181. NEW(styleAttr); aoc := "style"; styleAttr.SetName(aoc);
  1182. NEW(dyn);
  1183. (* AdHoc *)
  1184. aoc := "AdHoc "; dyn.Append(aoc);
  1185. (* FontName *)
  1186. dyn.Append(style.font^);
  1187. aoc := " "; dyn.Append(aoc);
  1188. (* Fontsize *)
  1189. Strings.IntToStr(fontsize, aoc); dyn.Append(aoc);
  1190. aoc := " "; dyn.Append(aoc);
  1191. (* Fontstyle: normal, bold, italic, bold+italic *)
  1192. Strings.IntToStr(style.style, aoc); dyn.Append(aoc);
  1193. aoc := " "; dyn.Append(aoc);
  1194. (* Baseline-Shift *)
  1195. IF style.shift = 1 THEN
  1196. Strings.IntToStr(baselineshift, aoc);
  1197. ELSIF style.shift = -1 THEN
  1198. Strings.IntToStr(0-baselineshift, aoc);
  1199. ELSE
  1200. aoc := "0";
  1201. END;
  1202. dyn.Append(aoc);
  1203. aoc := " "; dyn.Append(aoc);
  1204. (* Text-Color *)
  1205. Strings.IntToHexStr(style.color * 0100H + 0FFH, 7, aoc);
  1206. dyn.Append(aoc);
  1207. aoc := " ";
  1208. dyn.Append(aoc);
  1209. (* Background-Color *)
  1210. IF style.bgcolorPresent THEN
  1211. Strings.IntToHexStr(style.bgcolor * 0100H + 0FFH, 7, aoc);
  1212. ELSE
  1213. aoc := "00000000";
  1214. END;
  1215. dyn.Append(aoc);
  1216. s := dyn.ToArrOfChar();
  1217. styleAttr.SetValue(s^);
  1218. span.AddAttribute(styleAttr);
  1219. NEW(cdata);
  1220. cdata.SetStr(txt^);
  1221. span.AddContent(cdata);
  1222. paragraph.AddContent(span);
  1223. currentText := cText;
  1224. END AddText;
  1225. PROCEDURE AddImage(src : String; x : LONGINT; y : LONGINT; style : TextStyle);
  1226. VAR
  1227. object : XML.Element;
  1228. img : WebBrowserComponents.StretchImagePanel;
  1229. imgLink : WebBrowserComponents.StretchImageLinkPanel;
  1230. msg : WMTextView.LinkWrapper;
  1231. BEGIN
  1232. SetAlignmentAndIndent(style.align, style.indent);
  1233. NEW(object);
  1234. object.SetName("Object");
  1235. paragraph.AddContent(object);
  1236. IF style.link # NIL THEN
  1237. NEW(msg);
  1238. msg.link := EncodeLinkData(style.link, style.linktarget, url);
  1239. NEW(imgLink, NIL, src, x, y, loadLink, msg);
  1240. object.AddContent(imgLink);
  1241. ToEmbeddedObjectsList(imgLink);
  1242. ELSE
  1243. NEW(img, NIL, src, x, y);
  1244. object.AddContent(img);
  1245. ToEmbeddedObjectsList(img);
  1246. END;
  1247. currentText := cText;
  1248. END AddImage;
  1249. PROCEDURE AddSVG(svgRoot: XML.Element; style : TextStyle);
  1250. VAR
  1251. object : XML.Element;
  1252. svg : WebBrowserComponents.SVGPanel;
  1253. svgLink : WebBrowserComponents.SVGLinkPanel;
  1254. msg : WMTextView.LinkWrapper;
  1255. BEGIN
  1256. SetAlignmentAndIndent(style.align, style.indent);
  1257. NEW(object);
  1258. object.SetName("Object");
  1259. paragraph.AddContent(object);
  1260. IF style.link # NIL THEN
  1261. NEW(msg);
  1262. msg.link := EncodeLinkData(style.link, style.linktarget, url);
  1263. NEW(svgLink, svgRoot, loadLink, msg);
  1264. object.AddContent(svgLink);
  1265. ToEmbeddedObjectsList(svgLink);
  1266. ELSE
  1267. NEW(svg, svgRoot);
  1268. object.AddContent(svg);
  1269. ToEmbeddedObjectsList(svg);
  1270. END;
  1271. currentText := cText;
  1272. END AddSVG;
  1273. PROCEDURE ToEmbeddedObjectsList(obj : VisualComponent);
  1274. VAR
  1275. item : EmbeddedObject;
  1276. BEGIN
  1277. NEW(item);
  1278. item.object := obj;
  1279. item.prev := embeddedObjectsList;
  1280. embeddedObjectsList := item;
  1281. END ToEmbeddedObjectsList;
  1282. PROCEDURE AddHR(align : LONGINT);
  1283. VAR
  1284. object : XML.Element;
  1285. hr : WebBrowserComponents.HR;
  1286. BEGIN
  1287. SetAlignmentAndIndent(align, currentIndent);
  1288. currentText := cText;
  1289. NEW(object);
  1290. object.SetName("Object");
  1291. paragraph.AddContent(object);
  1292. NEW(hr, initWidth);
  1293. object.AddContent(hr);
  1294. ToEmbeddedObjectsList(hr);
  1295. END AddHR;
  1296. PROCEDURE AddTable(tableElem : XML.Element; style : TextStyle);
  1297. VAR
  1298. object : XML.Element;
  1299. table : Table;
  1300. BEGIN
  1301. NewLine(FALSE);
  1302. NEW(object);
  1303. object.SetName("Object");
  1304. NEW(table, tableElem, initWidth, style.align, textColor, linkColor, vlinkColor, alinkColor, url, loadLink, charset, frameName, style.form, baseAddress, baseTarget, sequencer, isTableContent);
  1305. ToEmbeddedObjectsList(table);
  1306. SetAlignmentAndIndent(style.align, style.indent);
  1307. object.AddContent(table);
  1308. paragraph.AddContent(object);
  1309. SetAlignmentAndIndent(style.align, style.indent);
  1310. NewLine(TRUE);
  1311. END AddTable;
  1312. PROCEDURE AddVisualComponent(vc : WMComponents.VisualComponent; style : TextStyle);
  1313. VAR
  1314. object : XML.Element;
  1315. BEGIN
  1316. SetAlignmentAndIndent(style.align, style.indent);
  1317. NEW(object);
  1318. object.SetName("Object");
  1319. object.AddContent(vc);
  1320. paragraph.AddContent(object);
  1321. currentText := cText;
  1322. END AddVisualComponent;
  1323. PROCEDURE AddLabel(s : String);
  1324. VAR
  1325. label : XML.Element;
  1326. nameAttr : XML.Attribute;
  1327. aoc : ARRAY 5 OF CHAR;
  1328. BEGIN
  1329. NEW(label);
  1330. label.SetName("Label");
  1331. NEW(nameAttr); aoc := "name"; nameAttr.SetName(aoc);
  1332. nameAttr.SetValue(s^);
  1333. label.AddAttribute(nameAttr);
  1334. paragraph.AddContent(label);
  1335. END AddLabel;
  1336. END Transformer;
  1337. CellSizes = POINTER TO ARRAY OF LONGINT;
  1338. StringArray = POINTER TO ARRAY OF String;
  1339. CellWrapper = POINTER TO RECORD
  1340. cell : TableCell;
  1341. END;
  1342. TableGrid = POINTER TO ARRAY OF ARRAY OF CellWrapper;
  1343. Table* = OBJECT (VisualComponent)
  1344. VAR
  1345. tableElem : XML.Element;
  1346. parentWidth : LONGINT;
  1347. align- : LONGINT;
  1348. textColor, linkColor, vlinkColor, alinkColor : LONGINT;
  1349. url : String;
  1350. loadLink : WMEvents.EventListener;
  1351. charset : String;
  1352. frameName : String;
  1353. form : Form;
  1354. baseAddress : String;
  1355. baseTarget : String;
  1356. isSubtable : BOOLEAN;
  1357. width : LONGINT;
  1358. relativeWidth : BOOLEAN;
  1359. border : LONGINT;
  1360. rules : BOOLEAN;
  1361. cellspacing : LONGINT;
  1362. relativeCellspacing : BOOLEAN;
  1363. cellpadding : LONGINT;
  1364. relativeCellpadding : BOOLEAN;
  1365. bgColor : LONGINT;
  1366. grid : TableGrid;
  1367. colsCnt : LONGINT;
  1368. rowsCnt : LONGINT;
  1369. minCellWidths, maxCellWidths : CellSizes;
  1370. minTableWidth, maxTableWidth : LONGINT;
  1371. x, y : LONGINT;
  1372. internalWidth, internalHeight : LONGINT;
  1373. PROCEDURE & New*(tableElem : XML.Element; parentWidth : LONGINT; align : LONGINT; textColor, linkColor, vlinkColor, alinkColor : LONGINT; url : String; loadLink : WMEvents.EventListener; charset : String; frameName : String; form : Form; baseAddress : String; baseTarget : String; seq : WMMessages.MsgSequencer; isSubtable : BOOLEAN);
  1374. VAR
  1375. s : String; sequencer: Messages.MsgSequencer;
  1376. BEGIN
  1377. Init;
  1378. IF seq = NIL THEN
  1379. NEW(sequencer, Handle);
  1380. SetSequencer(sequencer);
  1381. ELSE
  1382. SetSequencer(seq);
  1383. END;
  1384. SELF.tableElem := tableElem;
  1385. SELF.parentWidth := parentWidth - 20;
  1386. IF parentWidth < 1 THEN parentWidth := 1 END;
  1387. SELF.textColor := textColor;
  1388. SELF.linkColor := linkColor;
  1389. SELF.vlinkColor := vlinkColor;
  1390. SELF.alinkColor := alinkColor;
  1391. SELF.url := url;
  1392. SELF.loadLink := loadLink;
  1393. SELF.charset := charset;
  1394. SELF.frameName := frameName;
  1395. SELF.form := form;
  1396. SELF.baseAddress := baseAddress;
  1397. SELF.baseTarget := baseTarget;
  1398. SELF.isSubtable := isSubtable;
  1399. (* Get table alignment *)
  1400. s := GetElemAttributeValue(tableElem, "align", TRUE);
  1401. IF s # NIL THEN
  1402. Strings.TrimWS(s^);
  1403. IF s^ = "left" THEN
  1404. SELF.align := alignLeft;
  1405. ELSIF s^ = "center" THEN
  1406. SELF.align := alignCenter;
  1407. ELSIF s^ = "right" THEN
  1408. SELF.align := alignRight;
  1409. ELSIF s^ = "justify" THEN
  1410. SELF.align := alignJustify;
  1411. ELSE
  1412. SELF.align := align;
  1413. END;
  1414. ELSE
  1415. SELF.align := align;
  1416. END;
  1417. (* Get table width *)
  1418. s := GetElemAttributeValue(tableElem, "width", FALSE);
  1419. IF s # NIL THEN
  1420. Strings.TrimWS(s^);
  1421. IF Strings.EndsWith("%", s^) THEN
  1422. relativeWidth := TRUE;
  1423. s := Strings.Substring(0, Strings.Length(s^)-1, s^);
  1424. END;
  1425. Strings.StrToInt(s^, width);
  1426. ELSE
  1427. width := 0;
  1428. END;
  1429. (* Get border width *)
  1430. s := GetElemAttributeValue(tableElem, "border", FALSE);
  1431. IF s # NIL THEN
  1432. Strings.TrimWS(s^);
  1433. Strings.StrToInt(s^, border);
  1434. ELSE
  1435. border := 0;
  1436. END;
  1437. (* rules? *)
  1438. s := GetElemAttributeValue(tableElem, "rules", TRUE);
  1439. IF s # NIL THEN
  1440. Strings.TrimWS(s^);
  1441. rules := (s^ # "none");
  1442. ELSE
  1443. rules := (border > 0);
  1444. END;
  1445. (* Get cellspacing width *)
  1446. s := GetElemAttributeValue(tableElem, "cellspacing", FALSE);
  1447. IF s # NIL THEN
  1448. Strings.TrimWS(s^);
  1449. IF Strings.EndsWith("%", s^) THEN
  1450. relativeCellspacing := TRUE;
  1451. s := Strings.Substring(0, Strings.Length(s^)-1, s^);
  1452. END;
  1453. Strings.StrToInt(s^, cellspacing);
  1454. ELSE
  1455. cellspacing := 0;
  1456. END;
  1457. (* Get cellpadding width *)
  1458. s := GetElemAttributeValue(tableElem, "cellpadding", FALSE);
  1459. IF s # NIL THEN
  1460. Strings.TrimWS(s^);
  1461. IF Strings.EndsWith("%", s^) THEN
  1462. relativeCellpadding := TRUE;
  1463. s := Strings.Substring(0, Strings.Length(s^)-1, s^);
  1464. END;
  1465. Strings.StrToInt(s^, cellpadding);
  1466. ELSE
  1467. cellpadding := 0;
  1468. END;
  1469. (* Get & Set background-color *)
  1470. s := GetElemAttributeValue(tableElem, "bgcolor", TRUE);
  1471. IF s # NIL THEN
  1472. fillColor.Set(GetColor(s) * 0100H + 0FFH);
  1473. END;
  1474. (* makes all tables visible: *)
  1475. (* border := 1; rules := TRUE; *)
  1476. internalWidth := 0; internalHeight := 0;
  1477. BuildCellGrid();
  1478. CalculateMinMaxTableWidth();
  1479. IF ~isSubtable THEN AlignCells(); END;
  1480. END New;
  1481. PROCEDURE DrawBackground*(canvas : WMGraphics.Canvas);
  1482. VAR
  1483. h, w, color, i : LONGINT;
  1484. BEGIN
  1485. DrawBackground^(canvas);
  1486. (* draw border *)
  1487. IF border > 0 THEN
  1488. h := bounds.GetHeight();
  1489. w := bounds.GetWidth();
  1490. color := LONGINT(0808080FFH);
  1491. FOR i := 0 TO border - 1 DO
  1492. canvas.Line(0, 0+i, w-1, 0+i, color, WMGraphics.ModeSrcOverDst);
  1493. canvas.Line(0+i, 0, 0+i, h-1, color, WMGraphics.ModeSrcOverDst);
  1494. canvas.Line(0, h-1-i, w-1, h-1-i, color, WMGraphics.ModeSrcOverDst);
  1495. canvas.Line(w-1-i, 0, w-1-i, h-1, color, WMGraphics.ModeSrcOverDst);
  1496. END;
  1497. END;
  1498. END DrawBackground;
  1499. PROCEDURE BuildCellGrid;
  1500. VAR
  1501. captionCount : LONGINT;
  1502. wantedList : StringArray;
  1503. stopList : StringArray;
  1504. wantedTDTH : StringArray;
  1505. stopAtTable : StringArray;
  1506. newRow : BOOLEAN;
  1507. enum, enum2 : XMLObjects.Enumerator;
  1508. p, p2 : ANY;
  1509. j : LONGINT;
  1510. BEGIN
  1511. NEW(wantedTDTH, 2); wantedTDTH[0] := Strings.NewString("TD"); wantedTDTH[1] := Strings.NewString("TH");
  1512. NEW(stopAtTable, 1); stopAtTable[0] := Strings.NewString("TABLE");
  1513. (* add table caption, if any *)
  1514. captionCount := 0;
  1515. NEW(wantedList, 1); wantedList[0] := Strings.NewString("CAPTION");
  1516. enum := GetElems(tableElem, wantedList, stopAtTable, FALSE);
  1517. WHILE (enum.HasMoreElements()) DO
  1518. p := enum.GetNext();
  1519. AddCell(p(XML.Element), TRUE);
  1520. INC(captionCount);
  1521. END;
  1522. (* add table header, if any *)
  1523. NEW(wantedList, 1); wantedList[0] := Strings.NewString("THEAD");
  1524. enum := GetElems(tableElem, wantedList, stopAtTable, FALSE);
  1525. WHILE (enum.HasMoreElements()) DO
  1526. p := enum.GetNext();
  1527. enum2 := GetElems(p(XML.Element), wantedTDTH, stopAtTable, FALSE);
  1528. newRow := TRUE;
  1529. WHILE (enum2.HasMoreElements()) DO
  1530. p2 := enum2.GetNext();
  1531. AddCell(p2(XML.Element), newRow);
  1532. newRow := FALSE;
  1533. END;
  1534. END;
  1535. (* add rows *)
  1536. NEW(stopList, 5); stopList[0] := Strings.NewString("TABLE"); stopList[1] := Strings.NewString("THEAD"); stopList[2] := Strings.NewString("TFOOT"); stopList[3] := Strings.NewString("TR"); stopList[4] := Strings.NewString("CAPTION");
  1537. newRow := TRUE;
  1538. enum := GetElems(tableElem, wantedTDTH, stopList, FALSE);
  1539. WHILE (enum.HasMoreElements()) DO
  1540. p := enum.GetNext();
  1541. AddCell(p(XML.Element), newRow);
  1542. newRow := FALSE;
  1543. END;
  1544. NEW(wantedList, 1); wantedList[0] := Strings.NewString("TR");
  1545. NEW(stopList, 4); stopList[0] := Strings.NewString("TABLE"); stopList[1] := Strings.NewString("THEAD"); stopList[2] := Strings.NewString("TFOOT"); stopList[3] := Strings.NewString("CAPTION");
  1546. enum := GetElems(tableElem, wantedList, stopList, FALSE);
  1547. WHILE (enum.HasMoreElements()) DO
  1548. p := enum.GetNext();
  1549. enum2 := GetElems(p(XML.Element), wantedTDTH, stopAtTable, FALSE);
  1550. newRow := TRUE;
  1551. WHILE (enum2.HasMoreElements()) DO
  1552. p2 := enum2.GetNext();
  1553. AddCell(p2(XML.Element), newRow);
  1554. newRow := FALSE;
  1555. END;
  1556. END;
  1557. (* add table footer, if any *)
  1558. NEW(wantedList, 1); wantedList[0] := Strings.NewString("TFOOT");
  1559. newRow := TRUE;
  1560. enum := GetElems(tableElem, wantedList, stopAtTable, FALSE);
  1561. WHILE (enum.HasMoreElements()) DO
  1562. p := enum.GetNext();
  1563. enum2 := GetElems(p(XML.Element), wantedTDTH, stopAtTable, FALSE);
  1564. WHILE (enum2.HasMoreElements()) DO
  1565. p2 := enum2.GetNext();
  1566. AddCell(p2(XML.Element), newRow);
  1567. newRow := FALSE;
  1568. END;
  1569. END;
  1570. (* set colspan = colsCnt for each caption *)
  1571. FOR j := 0 TO captionCount - 1 DO
  1572. IF (grid[0, j] # NIL) & (grid[0, j].cell # NIL) THEN
  1573. grid[0, j].cell.colspan := colsCnt;
  1574. END;
  1575. END;
  1576. END BuildCellGrid;
  1577. PROCEDURE AddCell(elem : XML.Element; newRow : BOOLEAN);
  1578. VAR
  1579. tableCell : TableCell;
  1580. i, j : LONGINT;
  1581. PROCEDURE Add(x, y : LONGINT; tableCell : TableCell);
  1582. VAR
  1583. cellWrapper : CellWrapper;
  1584. BEGIN
  1585. IF y > (rowsCnt - 1) THEN
  1586. GrowY(y);
  1587. END;
  1588. WHILE (x < colsCnt) & (grid[x, y] # NIL) DO
  1589. INC(x);
  1590. END;
  1591. IF x > (colsCnt - 1) THEN
  1592. GrowX(x);
  1593. END;
  1594. NEW(cellWrapper);
  1595. cellWrapper.cell := tableCell;
  1596. grid[x, y] := cellWrapper;
  1597. END Add;
  1598. PROCEDURE GrowX(newX : LONGINT);
  1599. VAR
  1600. newInternalWidth : LONGINT;
  1601. newGrid : TableGrid;
  1602. BEGIN
  1603. IF newX > (internalWidth - 1) THEN
  1604. newInternalWidth := internalWidth;
  1605. WHILE newInternalWidth < newX + 1 DO
  1606. INC(newInternalWidth, 10);
  1607. END;
  1608. NEW(newGrid, newInternalWidth, internalHeight);
  1609. FOR i := 0 TO colsCnt - 1 DO
  1610. FOR j := 0 TO rowsCnt - 1 DO
  1611. newGrid[i, j] := grid[i, j];
  1612. END;
  1613. END;
  1614. internalWidth := newInternalWidth;
  1615. grid := newGrid;
  1616. END;
  1617. colsCnt := newX + 1;
  1618. END GrowX;
  1619. PROCEDURE GrowY(newY : LONGINT);
  1620. VAR
  1621. newInternalHeight : LONGINT;
  1622. newGrid : TableGrid;
  1623. BEGIN
  1624. IF newY > (internalHeight - 1) THEN
  1625. newInternalHeight := internalHeight;
  1626. WHILE newInternalHeight < newY + 1 DO
  1627. INC(newInternalHeight, 10);
  1628. END;
  1629. NEW(newGrid, internalWidth, newInternalHeight);
  1630. FOR i := 0 TO colsCnt - 1 DO
  1631. FOR j := 0 TO rowsCnt - 1 DO
  1632. newGrid[i, j] := grid[i, j];
  1633. END;
  1634. END;
  1635. internalHeight := newInternalHeight;
  1636. grid := newGrid;
  1637. END;
  1638. rowsCnt := newY + 1;
  1639. END GrowY;
  1640. BEGIN
  1641. IF rowsCnt = 0 THEN y := -1; newRow := TRUE END; (* init, if first cell added to the grid *)
  1642. IF newRow THEN
  1643. x := 0;
  1644. INC(y);
  1645. ELSE
  1646. INC(x);
  1647. END;
  1648. NEW(tableCell, sequencer, SELF, elem, textColor, linkColor, vlinkColor, alinkColor, url, loadLink, charset, frameName, form, baseAddress, baseTarget);
  1649. AddContent(tableCell);
  1650. FOR i := 0 TO tableCell.colspan - 1 DO
  1651. FOR j := 0 TO tableCell.rowspan - 1 DO
  1652. IF (i = 0) & (j = 0) THEN
  1653. Add(x, y, tableCell);
  1654. ELSE
  1655. Add(x + i, y + j, NIL);
  1656. END;
  1657. END;
  1658. END;
  1659. END AddCell;
  1660. PROCEDURE CalculateMinMaxTableWidth;
  1661. VAR
  1662. i, j, k : LONGINT;
  1663. BEGIN
  1664. NEW(minCellWidths, colsCnt);
  1665. NEW(maxCellWidths, colsCnt);
  1666. (* calculate minimal cell-widths *)
  1667. FOR j := 0 TO rowsCnt - 1 DO
  1668. FOR i := 0 TO colsCnt - 1 DO
  1669. IF (grid[i, j] # NIL) & (grid[i, j].cell # NIL) THEN
  1670. k := (grid[i, j].cell.minWidth - (grid[i, j].cell.colspan - 1) * cellspacing) DIV grid[i, j].cell.colspan;
  1671. IF k > minCellWidths[i] THEN
  1672. minCellWidths[i] := k;
  1673. END;
  1674. END;
  1675. END;
  1676. END;
  1677. (* sum-up minimal cell-widths *)
  1678. minTableWidth := 0;
  1679. FOR i := 0 TO colsCnt - 1 DO
  1680. INC(minTableWidth, minCellWidths[i]);
  1681. END;
  1682. INC(minTableWidth, 2 * border + (colsCnt + 1) * cellspacing);
  1683. (* calculate maximal cell-widths *)
  1684. FOR j := 0 TO rowsCnt - 1 DO
  1685. FOR i := 0 TO colsCnt - 1 DO
  1686. IF (grid[i, j] # NIL) & (grid[i, j].cell # NIL) THEN
  1687. k := (grid[i, j].cell.maxWidth - (grid[i, j].cell.colspan - 1) * cellspacing) DIV grid[i, j].cell.colspan;
  1688. IF k > maxCellWidths[i] THEN
  1689. maxCellWidths[i] := k;
  1690. END;
  1691. END;
  1692. END;
  1693. END;
  1694. (* sum-up maximal cell-widths *)
  1695. maxTableWidth := 0;
  1696. FOR i := 0 TO colsCnt - 1 DO
  1697. INC(maxTableWidth, maxCellWidths[i]);
  1698. END;
  1699. INC(maxTableWidth, 2 * border + (colsCnt + 1) * cellspacing);
  1700. END CalculateMinMaxTableWidth;
  1701. PROCEDURE AlignCells;
  1702. VAR
  1703. cell : TableCell;
  1704. w, h, i, j, k : LONGINT;
  1705. W, D, d : LONGINT;
  1706. tableWidth, tableHeight : LONGINT;
  1707. targetWidth : LONGINT;
  1708. cellWidths, cellHeights : CellSizes;
  1709. fac : REAL;
  1710. leftIndent, topIndent : LONGINT;
  1711. BEGIN
  1712. NEW(cellWidths, colsCnt);
  1713. NEW(cellHeights, rowsCnt);
  1714. (* CALCULATE CELL-WIDTHS *)
  1715. (* if no table-width specified... *)
  1716. IF width = 0 THEN
  1717. IF maxTableWidth <= parentWidth THEN
  1718. (* take max-width *)
  1719. tableWidth := maxTableWidth;
  1720. FOR i := 0 TO colsCnt - 1 DO
  1721. cellWidths[i] := maxCellWidths[i];
  1722. END;
  1723. ELSIF minTableWidth >= parentWidth THEN
  1724. (* take min-width *)
  1725. tableWidth := minTableWidth;
  1726. FOR i := 0 TO colsCnt - 1 DO
  1727. cellWidths[i] := minCellWidths[i];
  1728. END;
  1729. ELSE
  1730. (* calculate width *)
  1731. W := parentWidth - minTableWidth;
  1732. D := maxTableWidth - minTableWidth;
  1733. IF D < 1 THEN D := 1 END;
  1734. tableWidth := 0;
  1735. FOR i := 0 TO colsCnt - 1 DO
  1736. d := maxCellWidths[i] - minCellWidths[i];
  1737. cellWidths[i] := minCellWidths[i] + ENTIER(d * W / D);
  1738. INC(tableWidth, cellWidths[i]);
  1739. END;
  1740. INC(tableWidth, 2 * border + (colsCnt + 1) * cellspacing);
  1741. END;
  1742. ELSE
  1743. (* table-width specified... *)
  1744. targetWidth := width;
  1745. IF relativeWidth THEN
  1746. targetWidth := ENTIER(targetWidth * parentWidth / 100);
  1747. END;
  1748. IF minTableWidth >= targetWidth THEN
  1749. (* take min-width *)
  1750. tableWidth := minTableWidth;
  1751. FOR i := 0 TO colsCnt - 1 DO
  1752. cellWidths[i] := minCellWidths[i];
  1753. END;
  1754. ELSIF maxTableWidth <= targetWidth THEN
  1755. (* take max-width and blow up *)
  1756. fac := targetWidth / maxTableWidth;
  1757. tableWidth := 0;
  1758. FOR i := 0 TO colsCnt - 1 DO
  1759. cellWidths[i] := ENTIER(maxCellWidths[i] * fac);
  1760. INC(tableWidth, cellWidths[i]);
  1761. END;
  1762. INC(tableWidth, 2 * border + (colsCnt + 1) * cellspacing);
  1763. ELSE
  1764. (* calculate width *)
  1765. W := parentWidth - minTableWidth;
  1766. D := maxTableWidth - minTableWidth;
  1767. IF D < 1 THEN D := 1 END;
  1768. tableWidth := 0;
  1769. FOR i := 0 TO colsCnt - 1 DO
  1770. d := maxCellWidths[i] - minCellWidths[i];
  1771. cellWidths[i] := minCellWidths[i] + ENTIER(d * W / D);
  1772. INC(tableWidth, cellWidths[i]);
  1773. END;
  1774. INC(tableWidth, 2 * border + (colsCnt + 1) * cellspacing);
  1775. END;
  1776. END;
  1777. (* SET CELL-WIDTHS *)
  1778. topIndent := border + cellspacing;
  1779. FOR j := 0 TO rowsCnt - 1 DO
  1780. leftIndent := border + cellspacing;
  1781. FOR i := 0 TO colsCnt - 1 DO
  1782. IF (grid[i, j] # NIL) & (grid[i, j].cell # NIL) THEN
  1783. cell := grid[i, j].cell;
  1784. IF (cell.colspan = 1) & (cell.rowspan = 1) THEN
  1785. cell.SetWidth(cellWidths[i]);
  1786. ELSE
  1787. w := 0;
  1788. FOR k := 0 TO cell.colspan - 1 DO
  1789. INC(w, cellWidths[i + k]);
  1790. END;
  1791. INC(w, (cell.colspan - 1) * cellspacing);
  1792. cell.SetWidth(w);
  1793. END;
  1794. END;
  1795. INC(leftIndent, cellWidths[i] + cellspacing);
  1796. END;
  1797. INC(topIndent, cellHeights[j] + cellspacing);
  1798. END;
  1799. (* CALCULATE CELL-HEIGHTS *)
  1800. FOR j := 0 TO rowsCnt - 1 DO
  1801. FOR i := 0 TO colsCnt - 1 DO
  1802. IF (grid[i, j] # NIL) & (grid[i, j].cell # NIL) THEN
  1803. cell := grid[i, j].cell;
  1804. w := 0;
  1805. FOR k := 0 TO cell.colspan - 1 DO
  1806. INC(w, cellWidths[i + k]);
  1807. END;
  1808. INC(w, (cell.colspan - 1) * cellspacing);
  1809. h := (cell.tv.GetHeight(w) + 2 * cellpadding) DIV cell.rowspan;
  1810. IF h < 1 THEN h := 1 END;
  1811. IF h < cell.height THEN h := cell.height END;
  1812. IF h > cellHeights[j] THEN
  1813. cellHeights[j] := h;
  1814. END;
  1815. END;
  1816. END;
  1817. END;
  1818. tableHeight := 0;
  1819. FOR j := 0 TO rowsCnt - 1 DO
  1820. INC(tableHeight, cellHeights[j]);
  1821. END;
  1822. INC(tableHeight, 2 * border + (rowsCnt + 1) * cellspacing);
  1823. (* SET CELL HEIGHTS AND ALIGN CELLS *)
  1824. topIndent := border + cellspacing;
  1825. FOR j := 0 TO rowsCnt - 1 DO
  1826. leftIndent := border + cellspacing;
  1827. FOR i := 0 TO colsCnt - 1 DO
  1828. IF (grid[i, j] # NIL) & (grid[i, j].cell # NIL) THEN
  1829. cell := grid[i, j].cell;
  1830. IF (cell.colspan = 1) & (cell.rowspan = 1) THEN
  1831. cell.bounds.SetHeight(cellHeights[j]);
  1832. ELSE
  1833. h := 0;
  1834. FOR k := 0 TO cell.rowspan - 1 DO
  1835. INC(h, cellHeights[j + k]);
  1836. END;
  1837. INC(h, (cell.rowspan - 1) * cellspacing);
  1838. cell.bounds.SetHeight(h);
  1839. END;
  1840. cell.bounds.SetLeft(leftIndent);
  1841. cell.bounds.SetTop(topIndent);
  1842. END;
  1843. INC(leftIndent, cellWidths[i] + cellspacing);
  1844. END;
  1845. INC(topIndent, cellHeights[j] + cellspacing);
  1846. END;
  1847. (* SET TABLE BOUNDS *)
  1848. bounds.SetWidth(tableWidth);
  1849. bounds.SetHeight(tableHeight);
  1850. END AlignCells;
  1851. PROCEDURE ParentTvWidthChanged*(x : LONGINT);
  1852. BEGIN
  1853. parentWidth := x - 20;
  1854. IF parentWidth < 1 THEN parentWidth := 1 END;
  1855. AlignCells();
  1856. END ParentTvWidthChanged;
  1857. END Table;
  1858. TableCell = OBJECT (VisualComponent)
  1859. VAR
  1860. parentTable : Table;
  1861. transformer : Transformer;
  1862. tv : WMTextView.TextView;
  1863. text : Texts.Text;
  1864. minWidth, maxWidth : LONGINT;
  1865. width, height : LONGINT;
  1866. colspan, rowspan : LONGINT;
  1867. bgImage : WebBrowserComponents.TileImagePanel;
  1868. writer : Streams.Writer;
  1869. textWriter : TextUtilities.TextWriter;
  1870. PROCEDURE & New*(seq : WMMessages.MsgSequencer; parentTable : Table; elem : XML.Element; textColor, linkColor, vlinkColor, alinkColor : LONGINT; url : String; loadLink : WMEvents.EventListener; charset : String; frameName : String; form : Form; baseAddress : String; baseTarget : String);
  1871. VAR
  1872. s : String;
  1873. align : LONGINT;
  1874. xmlDoc : XML.Document;
  1875. bbtDecoder : TextUtilities.BluebottleDecoder;
  1876. rec : WMRectangles.Rectangle;
  1877. bgImageName : String;
  1878. item : EmbeddedObject;
  1879. dummy : LONGINT;
  1880. BEGIN
  1881. Init;
  1882. SetSequencer(seq);
  1883. SELF.parentTable := parentTable;
  1884. takesFocus.Set(FALSE);
  1885. (* Get alignment *)
  1886. s := GetElemAttributeValue(elem, "align", TRUE);
  1887. IF s # NIL THEN
  1888. Strings.TrimWS(s^);
  1889. IF s^ = "center" THEN
  1890. align := alignCenter;
  1891. ELSIF s^ = "right" THEN
  1892. align := alignRight;
  1893. ELSIF s^ = "justify" THEN
  1894. align := alignJustify;
  1895. ELSE
  1896. align := alignLeft;
  1897. END;
  1898. ELSE
  1899. align := alignLeft;
  1900. END;
  1901. (* Get & Set background-color *)
  1902. s := GetElemAttributeValue(elem, "bgcolor", TRUE);
  1903. IF s = NIL THEN
  1904. s := GetElemAttributeValue(elem.GetParent(), "bgcolor", TRUE);
  1905. END;
  1906. IF s # NIL THEN
  1907. fillColor.Set(GetColor(s) * 0100H + 0FFH);
  1908. END;
  1909. (* Get colspan *)
  1910. s := GetElemAttributeValue(elem, "colspan", FALSE);
  1911. IF s # NIL THEN
  1912. Strings.TrimWS(s^);
  1913. Strings.StrToInt(s^, colspan);
  1914. IF colspan < 1 THEN colspan := 1 END;
  1915. ELSE
  1916. colspan := 1;
  1917. END;
  1918. (* Get rowspan *)
  1919. s := GetElemAttributeValue(elem, "rowspan", FALSE);
  1920. IF s # NIL THEN
  1921. Strings.TrimWS(s^);
  1922. Strings.StrToInt(s^, rowspan);
  1923. IF rowspan < 1 THEN rowspan := 1 END;
  1924. ELSE
  1925. rowspan := 1;
  1926. END;
  1927. (* Get width *)
  1928. s := GetElemAttributeValue(elem, "width", FALSE);
  1929. IF s # NIL THEN
  1930. Strings.TrimWS(s^);
  1931. Strings.StrToInt(s^, width);
  1932. END;
  1933. INC(width, 2 * colspan * parentTable.cellpadding + (colspan - 1) * parentTable.cellspacing);
  1934. (* Get height *)
  1935. s := GetElemAttributeValue(elem, "height", FALSE);
  1936. IF s # NIL THEN
  1937. Strings.TrimWS(s^);
  1938. Strings.StrToInt(s^, height);
  1939. END;
  1940. INC(height, 2 * rowspan * parentTable.cellpadding + (rowspan - 1) * parentTable.cellspacing);
  1941. (* Get cell background image (not standard html 4.01) *)
  1942. s := GetElemAttributeValue(elem, "background", FALSE);
  1943. IF s#NIL THEN
  1944. bgImageName := ResolveAddress(baseAddress, s);
  1945. NEW(bgImage, NIL, bgImageName);
  1946. AddContent(bgImage);
  1947. END;
  1948. NEW(transformer, elem, url, 100, loadLink, charset, frameName); (* the initial width is unimportant, because it will be changed soon... *)
  1949. transformer.textColor := textColor;
  1950. transformer.linkColor := linkColor;
  1951. transformer.vlinkColor := vlinkColor;
  1952. transformer.alinkColor := alinkColor;
  1953. transformer.form := form;
  1954. transformer.initAlignment := align;
  1955. transformer.baseAddress := baseAddress;
  1956. transformer.baseTarget := baseTarget;
  1957. transformer.sequencer := seq;
  1958. transformer.isTableContent := TRUE;
  1959. xmlDoc := transformer.Transform();
  1960. NEW(bbtDecoder);
  1961. bbtDecoder.OpenXML(xmlDoc);
  1962. text := bbtDecoder.GetText();
  1963. (* NEW(text);
  1964. NEW(textWriter, text);
  1965. writer := textWriter.GetWriter();
  1966. xmlDoc.Write(writer, 0);
  1967. writer.Update;*)
  1968. NEW(tv);
  1969. tv.SetText(text); (*!?? redundant calls to tv.SetText, implying internal updates ...*)
  1970. tv.onLinkClicked.Add(loadLink);
  1971. AddContent(tv);
  1972. tv.alignment.Set(WMComponents.AlignClient);
  1973. rec.l := parentTable.cellpadding; rec.t := parentTable.cellpadding; rec.r := parentTable.cellpadding; rec.b := parentTable.cellpadding;
  1974. tv.borders.Set(rec);
  1975. tv.showBorder.Set(parentTable.rules);
  1976. tv.firstLine.Set(0);
  1977. (* get minimal cell-width *)
  1978. item := transformer.embeddedObjectsList;
  1979. WHILE item # NIL DO
  1980. IF item.object IS Table THEN
  1981. item.object(Table).bounds.SetWidth(item.object(Table).minTableWidth);
  1982. END;
  1983. item := item.prev;
  1984. END;
  1985. (*tv.SetText(text);*)
  1986. tv.GetMinMaxWidth(minWidth, dummy);
  1987. (*KernelLog.String("TableCell.New: minWidth of this cell: "); KernelLog.Int(minWidth, 0);*)
  1988. INC(minWidth, 2 * colspan * parentTable.cellpadding + (colspan - 1) * parentTable.cellspacing);
  1989. IF width > minWidth THEN minWidth := width END;
  1990. (* get maximal cell-width *)
  1991. item := transformer.embeddedObjectsList;
  1992. WHILE item # NIL DO
  1993. IF item.object IS Table THEN
  1994. item.object(Table).bounds.SetWidth(item.object(Table).maxTableWidth);
  1995. END;
  1996. item := item.prev;
  1997. END;
  1998. tv.SetText(text);
  1999. tv.GetMinMaxWidth(dummy, maxWidth);
  2000. (*KernelLog.String(", maxWidth of this cell: "); KernelLog.Int(maxWidth, 0); KernelLog.Ln;*)
  2001. INC(maxWidth, 2 * colspan * parentTable.cellpadding + (colspan - 1) * parentTable.cellspacing);
  2002. (*SetSequencer(seq); *)(*!??PH*)
  2003. END New;
  2004. PROCEDURE SetWidth(width : LONGINT);
  2005. VAR
  2006. item : EmbeddedObject;
  2007. BEGIN
  2008. bounds.SetWidth(width);
  2009. item := transformer.embeddedObjectsList;
  2010. WHILE item # NIL DO
  2011. IF item.object IS Table THEN
  2012. item.object(Table).ParentTvWidthChanged(width);
  2013. END;
  2014. item := item.prev;
  2015. END;
  2016. tv.SetText(text);
  2017. END SetWidth;
  2018. END TableCell;
  2019. Form = OBJECT
  2020. VAR
  2021. action : String;
  2022. loadLink : WMEvents.EventListener;
  2023. firstComp, lastComp : FormComponent;
  2024. firstRadioButtonGroup, lastRadioButtonGroup : RadioButtonGroup;
  2025. PROCEDURE &Init*(action : String; loadLink : WMEvents.EventListener);
  2026. BEGIN
  2027. SELF.action := action;
  2028. SELF.loadLink := loadLink;
  2029. END Init;
  2030. PROCEDURE Send(sender, par : ANY);
  2031. VAR
  2032. url, s, t : String;
  2033. curr : FormComponent;
  2034. isFirst : BOOLEAN;
  2035. msg : WMTextView.LinkWrapper;
  2036. BEGIN
  2037. url := action;
  2038. isFirst := TRUE;
  2039. curr := firstComp;
  2040. WHILE curr # NIL DO
  2041. IF curr.IsSuccessful() THEN
  2042. s := curr.GetValue();
  2043. s := Utf82UrlEncodedUtf8(s^);
  2044. s := Strings.ConcatToNew("=", s^);
  2045. t := Utf82UrlEncodedUtf8(curr.name^);
  2046. s := Strings.ConcatToNew(t^, s^);
  2047. IF isFirst THEN
  2048. s := Strings.ConcatToNew("?", s^);
  2049. isFirst := FALSE;
  2050. ELSE
  2051. s := Strings.ConcatToNew("&", s^);
  2052. END;
  2053. url := Strings.ConcatToNew(url^, s^);
  2054. END;
  2055. curr := curr.nextComp;
  2056. END;
  2057. NEW(msg);
  2058. msg.link := EncodeLinkData(url, NIL, NIL);
  2059. loadLink(SELF, msg);
  2060. END Send;
  2061. PROCEDURE Reset(sender, par : ANY);
  2062. VAR
  2063. curr : FormComponent;
  2064. BEGIN
  2065. curr := firstComp;
  2066. WHILE curr # NIL DO
  2067. curr.Reset();
  2068. curr := curr.nextComp;
  2069. END;
  2070. END Reset;
  2071. PROCEDURE AddFormComponent(comp : FormComponent);
  2072. BEGIN
  2073. IF firstComp = NIL THEN
  2074. firstComp := comp;
  2075. lastComp := comp;
  2076. ELSE
  2077. lastComp.nextComp := comp;
  2078. lastComp := comp;
  2079. END;
  2080. END AddFormComponent;
  2081. PROCEDURE AddRadioButton(radioButton : FormRadioButton);
  2082. VAR
  2083. curr : RadioButtonGroup;
  2084. BEGIN
  2085. curr := firstRadioButtonGroup;
  2086. WHILE(curr # NIL) & ~Strings.Equal(Strings.LowerCaseInNew(curr.name^), Strings.LowerCaseInNew(radioButton.name^)) DO
  2087. curr := curr.next;
  2088. END;
  2089. IF curr = NIL THEN
  2090. NEW(curr, radioButton.name);
  2091. IF firstRadioButtonGroup = NIL THEN
  2092. firstRadioButtonGroup := curr;
  2093. lastRadioButtonGroup := curr;
  2094. ELSE
  2095. lastRadioButtonGroup.next := curr;
  2096. lastRadioButtonGroup := curr;
  2097. END;
  2098. AddFormComponent(curr);
  2099. END;
  2100. curr.Add(radioButton);
  2101. radioButton.group := curr;
  2102. END AddRadioButton;
  2103. END Form;
  2104. FormComponent = OBJECT
  2105. VAR
  2106. nextComp : FormComponent;
  2107. name : String;
  2108. PROCEDURE IsSuccessful() : BOOLEAN;
  2109. END IsSuccessful;
  2110. PROCEDURE GetValue() : String;
  2111. END GetValue;
  2112. PROCEDURE Reset;
  2113. END Reset;
  2114. END FormComponent;
  2115. FormButton = OBJECT (FormComponent)
  2116. VAR
  2117. button : WMStandardComponents.Button;
  2118. value : String;
  2119. proc : WMEvents.EventListener;
  2120. active : BOOLEAN;
  2121. PROCEDURE &Init*(name : String; value : String; proc : WMEvents.EventListener);
  2122. VAR
  2123. x, y : LONGINT;
  2124. font : WMGraphics.Font;
  2125. BEGIN
  2126. SELF.name := name;
  2127. SELF.value := value;
  2128. SELF.proc := proc;
  2129. NEW(button);
  2130. value := TransformCharEnt(value);
  2131. button.caption.SetAOC(value^);
  2132. font := button.GetFont();
  2133. font.GetStringSize(value^, x, y);
  2134. button.bounds.SetExtents(x + 18, y + 8);
  2135. button.onClick.Add(Click);
  2136. END Init;
  2137. PROCEDURE IsSuccessful() : BOOLEAN;
  2138. BEGIN
  2139. RETURN active & (name # NIL);
  2140. END IsSuccessful;
  2141. PROCEDURE GetValue() : String;
  2142. BEGIN
  2143. IF name # NIL THEN
  2144. RETURN value;
  2145. ELSE
  2146. RETURN NIL;
  2147. END;
  2148. END GetValue;
  2149. PROCEDURE Click(sender, par : ANY);
  2150. BEGIN
  2151. active := TRUE;
  2152. IF proc # NIL THEN proc(sender, par) END;
  2153. active := FALSE;
  2154. END Click;
  2155. END FormButton;
  2156. FormCheckbox = OBJECT (FormComponent)
  2157. VAR
  2158. checkbox : WMStandardComponents.Checkbox;
  2159. value : String;
  2160. init : BOOLEAN;
  2161. PROCEDURE &Init*(name : String; value : String; checked : BOOLEAN);
  2162. BEGIN
  2163. NEW(checkbox);
  2164. checkbox.bounds.SetExtents(12, 12);
  2165. SELF.name := name;
  2166. SELF.value := value;
  2167. init := checked;
  2168. IF checked THEN
  2169. checkbox.state.Set(1);
  2170. ELSE
  2171. checkbox.state.Set(0);
  2172. END;
  2173. END Init;
  2174. PROCEDURE IsSuccessful() : BOOLEAN;
  2175. BEGIN
  2176. RETURN (checkbox.state.Get() = 1) & (name # NIL);
  2177. END IsSuccessful;
  2178. PROCEDURE GetValue() : String;
  2179. BEGIN
  2180. IF name # NIL THEN
  2181. RETURN value;
  2182. ELSE
  2183. RETURN NIL;
  2184. END;
  2185. END GetValue;
  2186. PROCEDURE Reset;
  2187. BEGIN
  2188. IF init THEN
  2189. checkbox.state.Set(1);
  2190. ELSE
  2191. checkbox.state.Set(0);
  2192. END;
  2193. END Reset;
  2194. END FormCheckbox;
  2195. FormTextInput = OBJECT (FormComponent)
  2196. VAR
  2197. editor : WMEditors.Editor;
  2198. init : String;
  2199. PROCEDURE &Init*(name : String; value : String; size : LONGINT; maxlength : LONGINT; isPassword : BOOLEAN);
  2200. BEGIN
  2201. NEW(editor);
  2202. editor.multiLine.Set(FALSE);
  2203. editor.tv.textAlignV.Set(WMGraphics.AlignCenter);
  2204. editor.fillColor.Set(0FFFFFFFFH);
  2205. editor.tv.showBorder.Set(TRUE);
  2206. editor.tv.borders.Set(WMRectangles.MakeRect(3,3,1,1));
  2207. SELF.name := name;
  2208. init := value;
  2209. IF isPassword THEN editor.tv.isPassword.Set(TRUE) END;
  2210. value := TransformCharEnt(value);
  2211. editor.SetAsString(value^);
  2212. editor.bounds.SetExtents(8 * size, 22);
  2213. END Init;
  2214. PROCEDURE IsSuccessful() : BOOLEAN;
  2215. BEGIN
  2216. RETURN name # NIL;
  2217. END IsSuccessful;
  2218. PROCEDURE GetValue() : String;
  2219. VAR
  2220. aoc : ARRAY 1024 OF CHAR;
  2221. BEGIN
  2222. IF name # NIL THEN
  2223. editor.GetAsString(aoc);
  2224. RETURN Strings.NewString(aoc);
  2225. ELSE
  2226. RETURN NIL;
  2227. END;
  2228. END GetValue;
  2229. PROCEDURE Reset;
  2230. BEGIN
  2231. editor.SetAsString(init^);
  2232. END Reset;
  2233. END FormTextInput;
  2234. FormRadioButton = OBJECT
  2235. VAR
  2236. next : FormRadioButton;
  2237. radioButton : WMStandardComponents.Checkbox;
  2238. name : String;
  2239. value : String;
  2240. group : RadioButtonGroup;
  2241. init : BOOLEAN;
  2242. PROCEDURE &Init*(name : String; value : String; checked : BOOLEAN);
  2243. BEGIN
  2244. NEW(radioButton);
  2245. radioButton.bounds.SetExtents(12, 12);
  2246. SELF.name := name;
  2247. SELF.value := value;
  2248. init := checked;
  2249. IF checked THEN
  2250. radioButton.state.Set(1);
  2251. ELSE
  2252. radioButton.state.Set(0);
  2253. END;
  2254. radioButton.onClick.Add(Clicked);
  2255. END Init;
  2256. PROCEDURE Clicked(sender, par : ANY);
  2257. BEGIN
  2258. IF radioButton.state.Get() = 0 THEN
  2259. radioButton.state.Set(1);
  2260. END;
  2261. group.ClearOthers(SELF);
  2262. END Clicked;
  2263. END FormRadioButton;
  2264. RadioButtonGroup = OBJECT (FormComponent)
  2265. VAR
  2266. next : RadioButtonGroup;
  2267. firstB, lastB : FormRadioButton;
  2268. PROCEDURE &Init*(name : String);
  2269. BEGIN
  2270. SELF.name := name;
  2271. END Init;
  2272. PROCEDURE IsSuccessful() : BOOLEAN;
  2273. BEGIN
  2274. RETURN TRUE;
  2275. END IsSuccessful;
  2276. PROCEDURE GetValue() : String;
  2277. VAR
  2278. curr : FormRadioButton;
  2279. BEGIN
  2280. curr := firstB;
  2281. LOOP
  2282. IF (curr = NIL) OR (curr.radioButton.state.Get() = 1) THEN EXIT END;
  2283. curr := curr.next;
  2284. END;
  2285. IF curr = NIL THEN curr := firstB END;
  2286. RETURN curr.value;
  2287. END GetValue;
  2288. PROCEDURE Reset;
  2289. VAR
  2290. curr : FormRadioButton;
  2291. BEGIN
  2292. curr := firstB;
  2293. LOOP
  2294. IF (curr = NIL) OR curr.init THEN EXIT END;
  2295. curr := curr.next;
  2296. END;
  2297. IF curr = NIL THEN curr := firstB END;
  2298. curr.radioButton.state.Set(1);
  2299. ClearOthers(curr);
  2300. END Reset;
  2301. PROCEDURE Add(radioButton : FormRadioButton);
  2302. BEGIN
  2303. IF firstB = NIL THEN
  2304. firstB := radioButton;
  2305. lastB := radioButton;
  2306. ELSE
  2307. lastB.next := radioButton;
  2308. lastB := radioButton;
  2309. END;
  2310. END Add;
  2311. PROCEDURE ClearOthers(exclude : FormRadioButton);
  2312. VAR
  2313. curr : FormRadioButton;
  2314. BEGIN
  2315. curr := firstB;
  2316. WHILE curr # NIL DO
  2317. IF curr # exclude THEN
  2318. curr.radioButton.state.Set(0);
  2319. END;
  2320. curr := curr.next;
  2321. END;
  2322. END ClearOthers;
  2323. END RadioButtonGroup;
  2324. FormMenuItem = OBJECT
  2325. VAR
  2326. caption- : ARRAY 128 OF CHAR;
  2327. value : String;
  2328. PROCEDURE &New*(caption: ARRAY OF CHAR; value : String);
  2329. BEGIN
  2330. COPY(caption, SELF.caption);
  2331. SELF.value := value;
  2332. END New;
  2333. END FormMenuItem;
  2334. FormMenu = OBJECT (FormComponent)
  2335. VAR
  2336. button : WMStandardComponents.Button;
  2337. popup: WMPopups.Popup;
  2338. init : FormMenuItem;
  2339. current : FormMenuItem;
  2340. PROCEDURE &Init*(name : String);
  2341. BEGIN
  2342. SELF.name := name;
  2343. NEW(button);
  2344. button.caption.SetAOC("[ select ]");
  2345. button.bounds.SetExtents(120, 22);
  2346. NEW(popup);
  2347. button.SetExtPointerDownHandler(MenuHandler);
  2348. END Init;
  2349. PROCEDURE MenuHandler(x, y: LONGINT; keys: SET; VAR handled: BOOLEAN);
  2350. BEGIN
  2351. handled := TRUE;
  2352. button.ToWMCoordinates(0, button.bounds.GetHeight(), x, y);
  2353. popup.Popup(x, y);
  2354. END MenuHandler;
  2355. PROCEDURE MenuPopupHandler(sender, data: ANY);
  2356. BEGIN
  2357. IF (data # NIL) & (data IS FormMenuItem) THEN
  2358. popup.Close;
  2359. button.caption.SetAOC(data(FormMenuItem).caption);
  2360. current := data(FormMenuItem);
  2361. END
  2362. END MenuPopupHandler;
  2363. PROCEDURE NewItem(value : String; label : String; selected : BOOLEAN);
  2364. VAR
  2365. item : FormMenuItem;
  2366. s : String;
  2367. BEGIN
  2368. label := TransformCharEnt(label);
  2369. IF value = NIL THEN value := label END;
  2370. s := Strings.ConcatToNew("[ ", label^);
  2371. s := Strings.ConcatToNew(s^, " ]");
  2372. NEW(item, s^, value);
  2373. IF selected THEN
  2374. init := item;
  2375. current := item;
  2376. button.caption.SetAOC(s^);
  2377. END;
  2378. popup.AddParButton(s^, MenuPopupHandler, item);
  2379. END NewItem;
  2380. PROCEDURE IsSuccessful() : BOOLEAN;
  2381. BEGIN
  2382. RETURN current # NIL;
  2383. END IsSuccessful;
  2384. PROCEDURE GetValue() : String;
  2385. BEGIN
  2386. IF name # NIL THEN
  2387. RETURN current.value;
  2388. ELSE
  2389. RETURN NIL;
  2390. END;
  2391. END GetValue;
  2392. PROCEDURE Reset;
  2393. BEGIN
  2394. IF init = NIL THEN
  2395. current := NIL;
  2396. button.caption.SetAOC("[ select ]");
  2397. ELSE
  2398. current := init;
  2399. button.caption.SetAOC(init.caption);
  2400. END;
  2401. END Reset;
  2402. END FormMenu;
  2403. FormHiddenControl = OBJECT (FormComponent)
  2404. VAR
  2405. value : String;
  2406. PROCEDURE &Init*(name : String; value : String);
  2407. BEGIN
  2408. SELF.name := name;
  2409. SELF.value := value;
  2410. END Init;
  2411. PROCEDURE IsSuccessful() : BOOLEAN;
  2412. BEGIN
  2413. RETURN name # NIL;
  2414. END IsSuccessful;
  2415. PROCEDURE GetValue() : String;
  2416. BEGIN
  2417. IF name # NIL THEN
  2418. RETURN value;
  2419. ELSE
  2420. RETURN NIL;
  2421. END;
  2422. END GetValue;
  2423. END FormHiddenControl;
  2424. PROCEDURE EncodeLinkData(link, target, url : String) : String;
  2425. VAR
  2426. s : String;
  2427. inlineLink : BOOLEAN;
  2428. urlLen : LONGINT;
  2429. BEGIN
  2430. ASSERT(link # NIL);
  2431. inlineLink := FALSE;
  2432. IF (url # NIL) & Strings.StartsWith2(url^, link^) THEN
  2433. urlLen := Strings.Length(url^);
  2434. IF (Strings.Length(link^) > urlLen) & (link^[urlLen] = "#") THEN
  2435. inlineLink := TRUE;
  2436. ELSIF (Strings.Length(link^) > (urlLen+1)) & (link^[urlLen] = "/") & (link^[urlLen+1] = "#") THEN
  2437. inlineLink := TRUE;
  2438. END;
  2439. END;
  2440. IF inlineLink THEN
  2441. RETURN Strings.Substring2(Strings.LastIndexOfByte2("#", link^), link^);
  2442. ELSE
  2443. s := target; IF s = NIL THEN s := Strings.NewString("") END;
  2444. s := Strings.ConcatToNew("target=", s^);
  2445. s := Strings.ConcatToNew(s^, ";url=");
  2446. RETURN Strings.ConcatToNew(s^, link^);
  2447. END;
  2448. END EncodeLinkData;
  2449. PROCEDURE Utf82UrlEncodedUtf8*(VAR in : ARRAY OF CHAR) : String;
  2450. VAR
  2451. i, cnt : LONGINT;
  2452. output : String;
  2453. aoc : ARRAY 3 OF CHAR;
  2454. BEGIN
  2455. NEW(output, 3 * Strings.Length(in) + 1);
  2456. cnt := 0;
  2457. FOR i := 0 TO Strings.Length(in)-1 DO
  2458. IF (ORD(in[i])=021H) OR (ORD(in[i])=022H) OR (ORD(in[i])=024H) OR ((ORD(in[i]) >= 027H) & (ORD(in[i]) <= 02EH)) OR
  2459. ((ORD(in[i]) >= 030H) & (ORD(in[i]) <= 039H)) OR ((ORD(in[i]) >= 041H) & (ORD(in[i]) <= 05AH)) OR
  2460. (ORD(in[i])=05FH) OR ((ORD(in[i]) >= 061H) & (ORD(in[i]) <= 07AH)) THEN
  2461. output^[cnt] := in[i];
  2462. INC(cnt);
  2463. ELSIF ORD(in[i])=020H THEN
  2464. output^[cnt] := '+';
  2465. INC(cnt);
  2466. ELSE
  2467. Strings.IntToHexStr(ORD(in[i]), 1, aoc);
  2468. output^[cnt] := '%';
  2469. output^[cnt+1] := aoc[0];
  2470. output^[cnt+2] := aoc[1];
  2471. INC(cnt, 3);
  2472. END;
  2473. END;
  2474. output^[cnt] := 0X;
  2475. RETURN output;
  2476. END Utf82UrlEncodedUtf8;
  2477. PROCEDURE GetElems(root : XML.Element; wanted : StringArray; stopAt : StringArray; checkMe : BOOLEAN) : XMLObjects.Enumerator;
  2478. VAR
  2479. col : XMLObjects.ArrayCollection;
  2480. enum, enum2 : XMLObjects.Enumerator;
  2481. p, p2 : ANY;
  2482. name : String;
  2483. i : LONGINT;
  2484. BEGIN
  2485. NEW(col);
  2486. name := root.GetName();
  2487. IF checkMe THEN
  2488. FOR i := 0 TO LEN(stopAt) - 1 DO
  2489. IF stopAt[i]^ = name^ THEN RETURN col.GetEnumerator() END;
  2490. END;
  2491. FOR i := 0 TO LEN(wanted) - 1 DO
  2492. IF wanted[i]^ = name^ THEN col.Add(root); END;
  2493. END;
  2494. END;
  2495. enum := root.GetContents();
  2496. WHILE enum.HasMoreElements() DO
  2497. p := enum.GetNext();
  2498. IF p IS XML.Element THEN
  2499. enum2 := GetElems(p(XML.Element), wanted, stopAt, TRUE);
  2500. WHILE enum2.HasMoreElements() DO
  2501. p2 := enum2.GetNext();
  2502. col.Add(p2);
  2503. END;
  2504. END;
  2505. END;
  2506. RETURN col.GetEnumerator();
  2507. END GetElems;
  2508. PROCEDURE GetCharsetConverter(charset : ARRAY OF CHAR) : CharsetConvProc;
  2509. BEGIN
  2510. Strings.TrimWS(charset);
  2511. Strings.LowerCase(charset);
  2512. IF charset = "iso8859-1" THEN
  2513. RETURN Iso2Utf8;
  2514. ELSIF charset = "utf-8" THEN
  2515. RETURN Utf82Utf8;
  2516. ELSIF charset = "gb2312" THEN
  2517. RETURN Gb23122Utf8;
  2518. ELSE
  2519. RETURN Iso2Utf8;
  2520. END;
  2521. END GetCharsetConverter;
  2522. PROCEDURE Iso2Utf8(VAR input : ARRAY OF CHAR) : String;
  2523. VAR
  2524. dyn : DynamicStrings.DynamicString;
  2525. dynPos : LONGINT;
  2526. temp : ARRAY 5 OF CHAR;
  2527. i, j, len : LONGINT;
  2528. BEGIN
  2529. NEW(dyn);
  2530. dynPos := 0;
  2531. FOR i := 0 TO Strings.Length(input)-1 DO
  2532. IF ORD(input[i]) >= 128 THEN
  2533. len := 0;
  2534. IF UTF8Strings.EncodeChar(ORD(input[i]), temp, len) THEN
  2535. FOR j := 0 TO len-1 DO
  2536. dyn.Put(temp[j], dynPos);
  2537. INC(dynPos);
  2538. END;
  2539. ELSE
  2540. dyn.Put('*', dynPos);
  2541. INC(dynPos);
  2542. END;
  2543. ELSE
  2544. dyn.Put(input[i], dynPos);
  2545. INC(dynPos);
  2546. END;
  2547. END;
  2548. RETURN dyn.ToArrOfChar();
  2549. END Iso2Utf8;
  2550. PROCEDURE Utf82Utf8(VAR input : ARRAY OF CHAR) : String;
  2551. BEGIN
  2552. RETURN Strings.NewString(input);
  2553. END Utf82Utf8;
  2554. PROCEDURE Gb23122Utf8(VAR input : ARRAY OF CHAR) : String;
  2555. BEGIN
  2556. RETURN WMCharCodes.GB2312ToUTF8(Strings.NewString(input));
  2557. END Gb23122Utf8;
  2558. PROCEDURE GetColor(s : String) : LONGINT;
  2559. VAR
  2560. aoc : ARRAY 17 OF CHAR;
  2561. i : LONGINT; res: WORD;
  2562. BEGIN
  2563. IF s#NIL THEN
  2564. IF (s^[0]='#') THEN
  2565. Strings.Copy(s^, 1, Strings.Length(s^)-1, aoc);
  2566. Strings.HexStrToInt(aoc, i, res);
  2567. RETURN i;
  2568. ELSIF (s[0] >= "0") & (s[0] <="9") OR (CAP(s[0]) >= "A") & (CAP(s[0])<="F") THEN
  2569. Strings.Copy(s^, 0, Strings.Length(s^), aoc);
  2570. Strings.HexStrToInt(aoc, i, res);
  2571. RETURN i;
  2572. ELSIF s^="black" THEN RETURN 0000000H;
  2573. ELSIF s^="silver" THEN RETURN 0C0C0C0H;
  2574. ELSIF s^="gray" THEN RETURN 0808080H;
  2575. ELSIF s^="white" THEN RETURN 0FFFFFFH;
  2576. ELSIF s^="maroon" THEN RETURN 0800000H;
  2577. ELSIF s^="red" THEN RETURN 0FF0000H;
  2578. ELSIF s^="purple" THEN RETURN 0800080H;
  2579. ELSIF s^="fuchsia" THEN RETURN 0FF00FFH;
  2580. ELSIF s^="green" THEN RETURN 0008000H;
  2581. ELSIF s^="lime" THEN RETURN 000FF00H;
  2582. ELSIF s^="olive" THEN RETURN 0808000H;
  2583. ELSIF s^="yellow" THEN RETURN 0FFFF00H;
  2584. ELSIF s^="navy" THEN RETURN 0000080H;
  2585. ELSIF s^="blue" THEN RETURN 00000FFH;
  2586. ELSIF s^="teal" THEN RETURN 0008080H;
  2587. ELSIF s^="aqua" THEN RETURN 000FFFFH;
  2588. ELSE RETURN 0;
  2589. END;
  2590. END;
  2591. RETURN 0;
  2592. END GetColor;
  2593. PROCEDURE StringIsWhiteSpace(VAR txt : ARRAY OF CHAR) : BOOLEAN;
  2594. VAR
  2595. i : LONGINT;
  2596. BEGIN
  2597. FOR i := 0 TO Strings.Length(txt)-1 DO
  2598. IF ORD(txt[i]) > 32 THEN RETURN FALSE END;
  2599. END;
  2600. RETURN TRUE;
  2601. END StringIsWhiteSpace;
  2602. PROCEDURE StringHasNewLine(VAR txt : ARRAY OF CHAR) : BOOLEAN;
  2603. VAR
  2604. i : LONGINT;
  2605. BEGIN
  2606. FOR i := 0 TO Strings.Length(txt)-1 DO
  2607. IF (ORD(txt[i]) = 10) OR (ORD(txt[i]) = 13) THEN RETURN TRUE END;
  2608. END;
  2609. RETURN FALSE;
  2610. END StringHasNewLine;
  2611. PROCEDURE ReplaceWhiteSpaces(VAR txt : String) : String;
  2612. VAR
  2613. dyn : DynamicStrings.DynamicString;
  2614. dynPos : LONGINT;
  2615. i : LONGINT;
  2616. ch : CHAR;
  2617. putYet : BOOLEAN;
  2618. BEGIN
  2619. TrimLineBreak(txt^);
  2620. NEW(dyn);
  2621. dynPos := 0;
  2622. putYet := FALSE;
  2623. FOR i := 0 TO Strings.Length(txt^)-1 DO
  2624. ch := txt^[i];
  2625. IF (ch = 020X) OR (ch = 9X) OR (ch = 0DX) OR (ch = 0AX) THEN
  2626. IF ~putYet THEN
  2627. dyn.Put(' ', dynPos);
  2628. INC(dynPos);
  2629. putYet := TRUE;
  2630. END;
  2631. ELSE
  2632. dyn.Put(ch, dynPos);
  2633. INC(dynPos);
  2634. putYet := FALSE;
  2635. END;
  2636. END;
  2637. RETURN dyn.ToArrOfChar();
  2638. END ReplaceWhiteSpaces;
  2639. PROCEDURE TrimLineBreak(VAR string : ARRAY OF CHAR);
  2640. VAR i,j: LONGINT;
  2641. BEGIN
  2642. j := 0;
  2643. WHILE (ORD(string[j]) = 10) OR (ORD(string[j]) = 13) DO INC(j) END;
  2644. IF (j > 0) THEN
  2645. i := 0;
  2646. WHILE (string[j] # 0X) DO
  2647. string[i] := string[j];
  2648. INC(i); INC(j)
  2649. END;
  2650. string[i] := 0X
  2651. END;
  2652. i := Strings.Length(string)-1;
  2653. WHILE (i >= 0) & ((ORD(string[i]) = 10) OR (ORD(string[i]) = 13)) DO DEC(i) END;
  2654. string[i+1] := 0X;
  2655. END TrimLineBreak;
  2656. PROCEDURE ResolveAddress*(baseAddress : String; url : String) : String;
  2657. VAR
  2658. slashPos, colonPos, upCnt : SIZE;
  2659. BEGIN
  2660. (* if url is absolute address, return it *)
  2661. IF Strings.StartsWith2("http://", url^) OR Strings.StartsWith2("file://", url^) THEN
  2662. RETURN url;
  2663. END;
  2664. (* if url is anchor in the same page, return 'baseAddress+url' *)
  2665. IF Strings.StartsWith2("#", url^) THEN
  2666. RETURN Strings.ConcatToNew(baseAddress^, url^);
  2667. END;
  2668. (* if url starts with "/", return ... *)
  2669. IF url^[0] = '/' THEN
  2670. slashPos := Strings.LastIndexOfByte2("/", baseAddress^);
  2671. IF Strings.StartsWith2("file://", baseAddress^) THEN
  2672. IF slashPos > 6 THEN
  2673. baseAddress := Strings.Substring(0, slashPos, baseAddress^);
  2674. ELSE
  2675. colonPos := Strings.IndexOfByte(":", 7, baseAddress^);
  2676. IF colonPos = -1 THEN
  2677. baseAddress := Strings.Substring(0, slashPos, baseAddress^);
  2678. ELSE
  2679. baseAddress := Strings.Substring(0, colonPos+1, baseAddress^);
  2680. url := Strings.Substring2(1, url^);
  2681. END;
  2682. END;
  2683. ELSIF Strings.StartsWith2("http://", baseAddress^) THEN
  2684. IF slashPos > 6 THEN
  2685. baseAddress := Strings.Substring(0, slashPos, baseAddress^);
  2686. END;
  2687. (* else baseAddress==server w/h terminating "/" *)
  2688. ELSE
  2689. KernelLog.String("unknown protocol: "); KernelLog.String(baseAddress^); KernelLog.Ln;
  2690. (* an assertion that will fail.... *)
  2691. ASSERT(Strings.StartsWith2("file://", baseAddress^));
  2692. END;
  2693. RETURN Strings.ConcatToNew(baseAddress^, url^);
  2694. END;
  2695. (* make sure baseAddress ends with "/" *)
  2696. IF baseAddress^[Strings.Length(baseAddress^) - 1] # '/' THEN
  2697. slashPos := Strings.LastIndexOfByte2("/", baseAddress^);
  2698. IF Strings.StartsWith2("file://", baseAddress^) THEN
  2699. baseAddress := Strings.Substring(0, slashPos+1, baseAddress^);
  2700. ELSIF Strings.StartsWith2("http://", baseAddress^) THEN
  2701. IF slashPos > 6 THEN
  2702. baseAddress := Strings.Substring(0, slashPos+1, baseAddress^);
  2703. ELSE
  2704. baseAddress := Strings.ConcatToNew(baseAddress^, "/");
  2705. END;
  2706. ELSE
  2707. KernelLog.String("unknown protocol: "); KernelLog.String(baseAddress^); KernelLog.Ln;
  2708. (* an assertion that will fail.... *)
  2709. ASSERT(Strings.StartsWith2("file://", baseAddress^));
  2710. END;
  2711. END;
  2712. (* count and cut "../" on url *)
  2713. upCnt := 0;
  2714. WHILE (Strings.Pos("../", url^) = 0) & (Strings.Length(url^) > 3) DO
  2715. INC(upCnt);
  2716. url := Strings.Substring2(3, url^);
  2717. END;
  2718. (* cut "./" on url *)
  2719. WHILE (Strings.Pos("./", url^) = 0) & (Strings.Length(url^) > 2) DO
  2720. url := Strings.Substring2(2, url^);
  2721. END;
  2722. (* go up upCnt directories *)
  2723. WHILE (upCnt > 0) & (Strings.LastIndexOfByte("/", Strings.Length(baseAddress^) - 1, baseAddress^) # -1) DO
  2724. baseAddress := Strings.Substring(0, Strings.LastIndexOfByte("/", Strings.Length(baseAddress^) - 2, baseAddress^) + 1, baseAddress^);
  2725. DEC(upCnt);
  2726. END;
  2727. RETURN Strings.ConcatToNew(baseAddress^, url^);
  2728. END ResolveAddress;
  2729. PROCEDURE GetElemAttributeValue*(elem : XML.Element; key : ARRAY OF CHAR; lowerCase : BOOLEAN) : String;
  2730. VAR
  2731. enum: XMLObjects.Enumerator;
  2732. p : ANY;
  2733. s : String;
  2734. BEGIN
  2735. enum := elem.GetAttributes();
  2736. WHILE (enum.HasMoreElements()) DO
  2737. p := enum.GetNext();
  2738. IF p IS XML.Attribute THEN
  2739. s := p(XML.Attribute).GetName();
  2740. s := Strings.NewString(s^);
  2741. Strings.LowerCase(s^);
  2742. IF s^ = key THEN
  2743. s := p(XML.Attribute).GetValue();
  2744. s := Strings.NewString(s^);
  2745. IF lowerCase THEN Strings.LowerCase(s^); END;
  2746. RETURN s;
  2747. END;
  2748. END;
  2749. END;
  2750. RETURN NIL;
  2751. END GetElemAttributeValue;
  2752. PROCEDURE MapFontSize(font : String; size : LONGINT) : LONGINT;
  2753. BEGIN
  2754. IF font^ = "Oberon" THEN
  2755. IF size=1 THEN RETURN 8;
  2756. ELSIF size=2 THEN RETURN 10;
  2757. ELSIF size=3 THEN RETURN 12;
  2758. ELSIF size=4 THEN RETURN 14;
  2759. ELSIF size=5 THEN RETURN 16;
  2760. ELSIF size=6 THEN RETURN 20;
  2761. ELSIF size=7 THEN RETURN 24;
  2762. ELSE RETURN 0 END;
  2763. ELSE
  2764. IF size=1 THEN RETURN 11;
  2765. ELSIF size=2 THEN RETURN 12;
  2766. ELSIF size=3 THEN RETURN 15;
  2767. ELSIF size=4 THEN RETURN 18;
  2768. ELSIF size=5 THEN RETURN 24;
  2769. ELSIF size=6 THEN RETURN 30;
  2770. ELSIF size=7 THEN RETURN 48;
  2771. ELSE RETURN 0 END;
  2772. END;
  2773. END MapFontSize;
  2774. PROCEDURE MapBaselineShift(size : LONGINT) : LONGINT;
  2775. BEGIN
  2776. IF size=1 THEN RETURN 2;
  2777. ELSIF size=2 THEN RETURN 3;
  2778. ELSIF size=3 THEN RETURN 3;
  2779. ELSIF size=4 THEN RETURN 4;
  2780. ELSIF size=5 THEN RETURN 5;
  2781. ELSIF size=6 THEN RETURN 6;
  2782. ELSIF size=7 THEN RETURN 10;
  2783. ELSE RETURN 0 END;
  2784. END MapBaselineShift;
  2785. (* returns the best matching existing font out of a list containing font-names and generic families *)
  2786. PROCEDURE GetExistingFontName(f : String) : String;
  2787. VAR
  2788. fonts, temp : String;
  2789. pos : LONGINT;
  2790. font : ARRAY 32 OF CHAR;
  2791. PROCEDURE Get(f : ARRAY OF CHAR; alternatives : BOOLEAN) : String;
  2792. VAR
  2793. i, j, last : LONGINT;
  2794. BEGIN
  2795. Strings.Trim(f, ' ');
  2796. Strings.Trim(f, '"');
  2797. Strings.Trim(f, "'");
  2798. last := Strings.Length(f)-1;
  2799. FOR i := 0 TO last DO
  2800. IF f[i]=' ' THEN
  2801. FOR j := i TO last-1 DO
  2802. f[j] := f[j+1];
  2803. END;
  2804. DEC(last);
  2805. END;
  2806. END;
  2807. f[last+1] := 0X;
  2808. IF FontExists(f) THEN RETURN Strings.NewString(f); END;
  2809. IF f="serif" THEN RETURN Strings.NewString(serif);
  2810. ELSIF f="sans-serif" THEN RETURN Strings.NewString(sansSerif);
  2811. ELSIF f="cursive" THEN RETURN Strings.NewString(cursive);
  2812. ELSIF f="fantasy" THEN RETURN Strings.NewString(fantasy);
  2813. ELSIF f="monospace" THEN RETURN Strings.NewString(monospace);
  2814. END;
  2815. IF alternatives THEN
  2816. RETURN NIL;
  2817. ELSE
  2818. RETURN Strings.NewString(defaultFont);
  2819. END;
  2820. END Get;
  2821. BEGIN
  2822. fonts := Strings.NewString(f^);
  2823. LOOP
  2824. pos := Strings.Pos(',', fonts^);
  2825. IF pos = -1 THEN
  2826. RETURN Get(fonts^, FALSE);
  2827. ELSE
  2828. Strings.Copy(fonts^, 0, pos, font);
  2829. IF (pos+1) > (Strings.Length(fonts^)-1) THEN RETURN Get(font, FALSE); END;
  2830. temp := Get(font, TRUE);
  2831. IF temp#NIL THEN RETURN temp; END;
  2832. temp := Strings.NewString(fonts^);
  2833. Strings.Copy(temp^, pos+1, Strings.Length(fonts^)-(pos+1), fonts^);
  2834. END;
  2835. END;
  2836. END GetExistingFontName;
  2837. PROCEDURE FontExists(f : ARRAY OF CHAR) : BOOLEAN;
  2838. VAR
  2839. font : WMGraphics.Font;
  2840. BEGIN
  2841. font := WMGraphics.GetFont(f, 12, {0});
  2842. RETURN (f = font.name);
  2843. END FontExists;
  2844. PROCEDURE IntToABCString(val : LONGINT; upperCase : BOOLEAN) : String;
  2845. VAR
  2846. i, j, offset : LONGINT;
  2847. aoc : ARRAY 5 OF CHAR;
  2848. PROCEDURE GetChar(i : LONGINT) : CHAR;
  2849. BEGIN
  2850. IF i = 0 THEN
  2851. RETURN '0';
  2852. ELSE
  2853. RETURN CHR(offset+i);
  2854. END;
  2855. END GetChar;
  2856. BEGIN
  2857. IF upperCase THEN offset := 64 ELSE offset := 96; END;
  2858. val := val MOD (26*26);
  2859. i := val DIV 26;
  2860. j := val MOD 26;
  2861. IF i = 0 THEN
  2862. aoc := " . ";
  2863. aoc[0] := GetChar(j);
  2864. ELSE
  2865. aoc := " . ";
  2866. aoc[0] := GetChar(i);
  2867. aoc[1] := GetChar(j);
  2868. END;
  2869. RETURN Strings.NewString(aoc);
  2870. END IntToABCString;
  2871. PROCEDURE IntToRomanString(val : LONGINT; uppercase : BOOLEAN) : String;
  2872. VAR
  2873. dyn : DynamicStrings.DynamicString;
  2874. aoc : ARRAY 3 OF CHAR;
  2875. s : String;
  2876. BEGIN
  2877. IF val = 0 THEN RETURN Strings.NewString("0. "); END;
  2878. NEW(dyn);
  2879. WHILE val > 0 DO
  2880. IF val >= 1000 THEN
  2881. aoc := "M"; dyn.Append(aoc); val := val - 1000;
  2882. ELSIF val >= 900 THEN
  2883. aoc := "CM"; dyn.Append(aoc); val := val - 900;
  2884. ELSIF val >= 500 THEN
  2885. aoc := "D"; dyn.Append(aoc); val := val - 500;
  2886. ELSIF val >= 400 THEN
  2887. aoc := "CD"; dyn.Append(aoc); val := val - 400;
  2888. ELSIF val >= 100 THEN
  2889. aoc := "C"; dyn.Append(aoc); val := val - 100;
  2890. ELSIF val >= 90 THEN
  2891. aoc := "XC"; dyn.Append(aoc); val := val - 90;
  2892. ELSIF val >= 50 THEN
  2893. aoc := "L"; dyn.Append(aoc); val := val - 50;
  2894. ELSIF val >= 40 THEN
  2895. aoc := "XL"; dyn.Append(aoc); val := val - 40;
  2896. ELSIF val >= 10 THEN
  2897. aoc := "X"; dyn.Append(aoc); val := val - 10;
  2898. ELSIF val >= 9 THEN
  2899. aoc := "IX"; dyn.Append(aoc); val := val - 9;
  2900. ELSIF val >= 5 THEN
  2901. aoc := "V"; dyn.Append(aoc); val := val - 5;
  2902. ELSIF val >= 4 THEN
  2903. aoc := "IV"; dyn.Append(aoc); val := val - 4;
  2904. ELSIF val >= 1 THEN
  2905. aoc := "I"; dyn.Append(aoc); val := val - 1;
  2906. END;
  2907. END;
  2908. aoc := ". "; dyn.Append(aoc);
  2909. s := dyn.ToArrOfChar();
  2910. IF ~uppercase THEN Strings.LowerCase(s^); END;
  2911. RETURN s;
  2912. END IntToRomanString;
  2913. PROCEDURE TransformCharEnt*(in : String) : String;
  2914. VAR
  2915. ent : ARRAY 32 OF CHAR;
  2916. i, j : LONGINT;
  2917. rep, s1, s2 : String;
  2918. ds: DynamicStrings.DynamicString;
  2919. BEGIN
  2920. i:=0;
  2921. LOOP
  2922. IF in^[i]='&' THEN
  2923. j:=i+1;
  2924. LOOP
  2925. IF j >= LEN(in^)-1 THEN EXIT END;
  2926. IF in^[j]=';' THEN
  2927. Strings.Copy(in^, i+1, j-i-1, ent);
  2928. rep := GetCharEnt(ent);
  2929. IF rep#NIL THEN
  2930. NEW(ds);
  2931. ds.FromArrOfChar(in);
  2932. s1 := ds.Extract(0, i);
  2933. s2 := ds.Extract(j+1, LEN(in^)-j-1);
  2934. NEW(ds);
  2935. ds.Append(s1^);
  2936. ds.Append(rep^);
  2937. ds.Append(s2^);
  2938. in := ds.ToArrOfChar();
  2939. i:=i+LEN(rep^)-2;
  2940. END;
  2941. EXIT;
  2942. END;
  2943. INC(j);
  2944. END;
  2945. END;
  2946. INC(i);
  2947. IF i>LEN(in^)-3 THEN EXIT END;
  2948. END;
  2949. RETURN in;
  2950. END TransformCharEnt;
  2951. PROCEDURE GetCharEnt(VAR ent : ARRAY OF CHAR) : String;
  2952. VAR
  2953. temp : String;
  2954. aoc : ARRAY 5 OF CHAR;
  2955. res, len : LONGINT; suc: WORD;
  2956. BEGIN
  2957. res := 0;
  2958. IF ent[0] = '#' THEN
  2959. temp := Strings.Substring2(1, ent);
  2960. IF Strings.Length(temp^) > 0 THEN
  2961. IF (temp^[0] = 'x') OR (temp^[0] = 'X') THEN
  2962. temp := Strings.Substring2(1, ent);
  2963. Strings.HexStrToInt(temp^, res, suc);
  2964. IF suc # 0 THEN res := 160 END;
  2965. ELSE
  2966. Strings.StrToInt(temp^, res);
  2967. END;
  2968. ELSE
  2969. res := 160;
  2970. END;
  2971. ELSIF ent = "nbsp" THEN res := 160;
  2972. ELSIF ent = "auml" THEN res := 228;
  2973. ELSIF ent = "ouml" THEN res := 246;
  2974. ELSIF ent = "uuml" THEN res := 252;
  2975. ELSIF ent = "Auml" THEN res := 196;
  2976. ELSIF ent = "Ouml" THEN res := 214;
  2977. ELSIF ent = "Uuml" THEN res := 220;
  2978. ELSIF ent = "quot" THEN res := 34;
  2979. ELSIF ent = "copy" THEN res := 169;
  2980. ELSIF ent = "euro" THEN res := 8364;
  2981. ELSIF ent = "iexcl" THEN res := 161;
  2982. ELSIF ent = "cent" THEN res := 162;
  2983. ELSIF ent = "pound" THEN res := 163;
  2984. ELSIF ent = "curren" THEN res := 164;
  2985. ELSIF ent = "yen" THEN res := 165;
  2986. ELSIF ent = "brvbar" THEN res := 166;
  2987. ELSIF ent = "sect" THEN res := 167;
  2988. ELSIF ent = "uml" THEN res := 168;
  2989. ELSIF ent = "ordf" THEN res := 170;
  2990. ELSIF ent = "laquo" THEN res := 171;
  2991. ELSIF ent = "not" THEN res := 172;
  2992. ELSIF ent = "shy" THEN res := 173;
  2993. ELSIF ent = "reg" THEN res := 174;
  2994. ELSIF ent = "macr" THEN res := 175;
  2995. ELSIF ent = "deg" THEN res := 176;
  2996. ELSIF ent = "plusmn" THEN res := 177;
  2997. ELSIF ent = "sup2" THEN res := 178;
  2998. ELSIF ent = "sup3" THEN res := 179;
  2999. ELSIF ent = "acute" THEN res := 180;
  3000. ELSIF ent = "micro" THEN res := 181;
  3001. ELSIF ent = "para" THEN res := 182;
  3002. ELSIF ent = "middot" THEN res := 183;
  3003. ELSIF ent = "cedil" THEN res := 184;
  3004. ELSIF ent = "sup1" THEN res := 185;
  3005. ELSIF ent = "ordm" THEN res := 186;
  3006. ELSIF ent = "raquo" THEN res := 187;
  3007. ELSIF ent = "frac14" THEN res := 188;
  3008. ELSIF ent = "frac12" THEN res := 189;
  3009. ELSIF ent = "frac34" THEN res := 190;
  3010. ELSIF ent = "iquest" THEN res := 191;
  3011. ELSIF ent = "Agrave" THEN res := 192;
  3012. ELSIF ent = "Aacute" THEN res := 193;
  3013. ELSIF ent = "Acirc" THEN res := 194;
  3014. ELSIF ent = "Atilde" THEN res := 195;
  3015. ELSIF ent = "Aring" THEN res := 197;
  3016. ELSIF ent = "AElig" THEN res := 198;
  3017. ELSIF ent = "Ccedil" THEN res := 199;
  3018. ELSIF ent = "Egrave" THEN res := 200;
  3019. ELSIF ent = "Eacute" THEN res := 201;
  3020. ELSIF ent = "Ecirc" THEN res := 202;
  3021. ELSIF ent = "Euml" THEN res := 203;
  3022. ELSIF ent = "Igrave" THEN res := 204;
  3023. ELSIF ent = "Iacute" THEN res := 205;
  3024. ELSIF ent = "Icirc" THEN res := 206;
  3025. ELSIF ent = "Iuml" THEN res := 207;
  3026. ELSIF ent = "ETH" THEN res := 208;
  3027. ELSIF ent = "Ntilde" THEN res := 209;
  3028. ELSIF ent = "Ograve" THEN res := 210;
  3029. ELSIF ent = "Oacute" THEN res := 211;
  3030. ELSIF ent = "Ocirc" THEN res := 212;
  3031. ELSIF ent = "Otilde" THEN res := 213;
  3032. ELSIF ent = "times" THEN res := 215;
  3033. ELSIF ent = "Oslash" THEN res := 216;
  3034. ELSIF ent = "Ugrave" THEN res := 217;
  3035. ELSIF ent = "Uacute" THEN res := 218;
  3036. ELSIF ent = "Ucirc" THEN res := 219;
  3037. ELSIF ent = "Yacute" THEN res := 221;
  3038. ELSIF ent = "THORN" THEN res := 222;
  3039. ELSIF ent = "szlig" THEN res := 223;
  3040. ELSIF ent = "agrave" THEN res := 224;
  3041. ELSIF ent = "aacute" THEN res := 225;
  3042. ELSIF ent = "acirc" THEN res := 226;
  3043. ELSIF ent = "atilde" THEN res := 227;
  3044. ELSIF ent = "aring" THEN res := 229;
  3045. ELSIF ent = "aelig" THEN res := 230;
  3046. ELSIF ent = "ccedil" THEN res := 231;
  3047. ELSIF ent = "egrave" THEN res := 232;
  3048. ELSIF ent = "eacute" THEN res := 233;
  3049. ELSIF ent = "ecirc" THEN res := 234;
  3050. ELSIF ent = "euml" THEN res := 235;
  3051. ELSIF ent = "igrave" THEN res := 236;
  3052. ELSIF ent = "iacute" THEN res := 237;
  3053. ELSIF ent = "icirc" THEN res := 238;
  3054. ELSIF ent = "iuml" THEN res := 239;
  3055. ELSIF ent = "eth" THEN res := 240;
  3056. ELSIF ent = "ntilde" THEN res := 241;
  3057. ELSIF ent = "ograve" THEN res := 242;
  3058. ELSIF ent = "oacute" THEN res := 243;
  3059. ELSIF ent = "ocirc" THEN res := 244;
  3060. ELSIF ent = "otilde" THEN res := 245;
  3061. ELSIF ent = "divide" THEN res := 247;
  3062. ELSIF ent = "oslash" THEN res := 248;
  3063. ELSIF ent = "ugrave" THEN res := 249;
  3064. ELSIF ent = "uacute" THEN res := 250;
  3065. ELSIF ent = "ucirc" THEN res := 251;
  3066. ELSIF ent = "yacute" THEN res := 253;
  3067. ELSIF ent = "thorn" THEN res := 254;
  3068. ELSIF ent = "yuml" THEN res := 255;
  3069. ELSIF ent = "fnof" THEN res := 402;
  3070. ELSIF ent = "Alpha" THEN res := 913;
  3071. ELSIF ent = "Beta" THEN res := 914;
  3072. ELSIF ent = "Gamma" THEN res := 915;
  3073. ELSIF ent = "Delta" THEN res := 916;
  3074. ELSIF ent = "Epsilon" THEN res := 917;
  3075. ELSIF ent = "Zeta" THEN res := 918;
  3076. ELSIF ent = "Eta" THEN res := 919;
  3077. ELSIF ent = "Theta" THEN res := 920;
  3078. ELSIF ent = "Iota" THEN res := 921;
  3079. ELSIF ent = "Kappa" THEN res := 922;
  3080. ELSIF ent = "Lambda" THEN res := 923;
  3081. ELSIF ent = "Mu" THEN res := 924;
  3082. ELSIF ent = "Nu" THEN res := 925;
  3083. ELSIF ent = "Xi" THEN res := 926;
  3084. ELSIF ent = "Omicron" THEN res := 927;
  3085. ELSIF ent = "Pi" THEN res := 928;
  3086. ELSIF ent = "Rho" THEN res := 929;
  3087. ELSIF ent = "Sigma" THEN res := 931;
  3088. ELSIF ent = "Tau" THEN res := 932;
  3089. ELSIF ent = "Upsilon" THEN res := 933;
  3090. ELSIF ent = "Phi" THEN res := 934;
  3091. ELSIF ent = "Chi" THEN res := 935;
  3092. ELSIF ent = "Psi" THEN res := 936;
  3093. ELSIF ent = "Omega" THEN res := 937;
  3094. ELSIF ent = "alpha" THEN res := 945;
  3095. ELSIF ent = "beta" THEN res := 946;
  3096. ELSIF ent = "gamma" THEN res := 947;
  3097. ELSIF ent = "delta" THEN res := 948;
  3098. ELSIF ent = "epsilon" THEN res := 949;
  3099. ELSIF ent = "zeta" THEN res := 950;
  3100. ELSIF ent = "eta" THEN res := 951;
  3101. ELSIF ent = "theta" THEN res := 952;
  3102. ELSIF ent = "iota" THEN res := 953;
  3103. ELSIF ent = "kappa" THEN res := 954;
  3104. ELSIF ent = "lambda" THEN res := 955;
  3105. ELSIF ent = "mu" THEN res := 956;
  3106. ELSIF ent = "nu" THEN res := 957;
  3107. ELSIF ent = "xi" THEN res := 958;
  3108. ELSIF ent = "omicron" THEN res := 959;
  3109. ELSIF ent = "pi" THEN res := 960;
  3110. ELSIF ent = "rho" THEN res := 961;
  3111. ELSIF ent = "sigmaf" THEN res := 962;
  3112. ELSIF ent = "sigma" THEN res := 963;
  3113. ELSIF ent = "tau" THEN res := 964;
  3114. ELSIF ent = "upsilon" THEN res := 965;
  3115. ELSIF ent = "phi" THEN res := 966;
  3116. ELSIF ent = "chi" THEN res := 967;
  3117. ELSIF ent = "psi" THEN res := 968;
  3118. ELSIF ent = "omega" THEN res := 969;
  3119. ELSIF ent = "thetasym" THEN res := 977;
  3120. ELSIF ent = "upsih" THEN res := 978;
  3121. ELSIF ent = "piv" THEN res := 982;
  3122. ELSIF ent = "bull" THEN res := 8226;
  3123. ELSIF ent = "hellip" THEN res := 8230;
  3124. ELSIF ent = "prime" THEN res := 8242;
  3125. ELSIF ent = "Prime" THEN res := 8243;
  3126. ELSIF ent = "oline" THEN res := 8254;
  3127. ELSIF ent = "frasl" THEN res := 8260;
  3128. ELSIF ent = "weierp" THEN res := 8472;
  3129. ELSIF ent = "image" THEN res := 8465;
  3130. ELSIF ent = "real" THEN res := 8476;
  3131. ELSIF ent = "trade" THEN res := 8482;
  3132. ELSIF ent = "alefsym" THEN res := 8501;
  3133. ELSIF ent = "larr" THEN res := 8592;
  3134. ELSIF ent = "uarr" THEN res := 8593;
  3135. ELSIF ent = "rarr" THEN res := 8594;
  3136. ELSIF ent = "darr" THEN res := 8595;
  3137. ELSIF ent = "harr" THEN res := 8596;
  3138. ELSIF ent = "crarr" THEN res := 8629;
  3139. ELSIF ent = "lArr" THEN res := 8656;
  3140. ELSIF ent = "uArr" THEN res := 8657;
  3141. ELSIF ent = "rArr" THEN res := 8658;
  3142. ELSIF ent = "dArr" THEN res := 8659;
  3143. ELSIF ent = "hArr" THEN res := 8660;
  3144. ELSIF ent = "forall" THEN res := 8704;
  3145. ELSIF ent = "part" THEN res := 8706;
  3146. ELSIF ent = "exist" THEN res := 8707;
  3147. ELSIF ent = "empty" THEN res := 8709;
  3148. ELSIF ent = "nabla" THEN res := 8711;
  3149. ELSIF ent = "isin" THEN res := 8712;
  3150. ELSIF ent = "notin" THEN res := 8713;
  3151. ELSIF ent = "ni" THEN res := 8715;
  3152. ELSIF ent = "prod" THEN res := 8719;
  3153. ELSIF ent = "sum" THEN res := 8721;
  3154. ELSIF ent = "minus" THEN res := 8722;
  3155. ELSIF ent = "lowast" THEN res := 8727;
  3156. ELSIF ent = "radic" THEN res := 8730;
  3157. ELSIF ent = "prop" THEN res := 8733;
  3158. ELSIF ent = "infin" THEN res := 8734;
  3159. ELSIF ent = "ang" THEN res := 8736;
  3160. ELSIF ent = "and" THEN res := 8743;
  3161. ELSIF ent = "or" THEN res := 8744;
  3162. ELSIF ent = "cap" THEN res := 8745;
  3163. ELSIF ent = "cup" THEN res := 8746;
  3164. ELSIF ent = "int" THEN res := 8747;
  3165. ELSIF ent = "there4" THEN res := 8756;
  3166. ELSIF ent = "sim" THEN res := 8764;
  3167. ELSIF ent = "cong" THEN res := 8773;
  3168. ELSIF ent = "asymp" THEN res := 8776;
  3169. ELSIF ent = "ne" THEN res := 8800;
  3170. ELSIF ent = "equiv" THEN res := 8801;
  3171. ELSIF ent = "le" THEN res := 8804;
  3172. ELSIF ent = "ge" THEN res := 8805;
  3173. ELSIF ent = "sub" THEN res := 8834;
  3174. ELSIF ent = "sup" THEN res := 8835;
  3175. ELSIF ent = "nsub" THEN res := 8836;
  3176. ELSIF ent = "sube" THEN res := 8838;
  3177. ELSIF ent = "supe" THEN res := 8839;
  3178. ELSIF ent = "oplus" THEN res := 8853;
  3179. ELSIF ent = "otimes" THEN res := 8855;
  3180. ELSIF ent = "perp" THEN res := 8869;
  3181. ELSIF ent = "sdot" THEN res := 8901;
  3182. ELSIF ent = "lceil" THEN res := 8968;
  3183. ELSIF ent = "rceil" THEN res := 8969;
  3184. ELSIF ent = "lfloor" THEN res := 8970;
  3185. ELSIF ent = "rfloor" THEN res := 8971;
  3186. ELSIF ent = "lang" THEN res := 9001;
  3187. ELSIF ent = "rang" THEN res := 9002;
  3188. ELSIF ent = "loz" THEN res := 9674;
  3189. ELSIF ent = "spades" THEN res := 9824;
  3190. ELSIF ent = "clubs" THEN res := 9827;
  3191. ELSIF ent = "hearts" THEN res := 9829;
  3192. ELSIF ent = "diams" THEN res := 9830;
  3193. ELSIF ent = "amp" THEN res := 38;
  3194. ELSIF ent = "lt" THEN res := 60;
  3195. ELSIF ent = "gt" THEN res := 62;
  3196. ELSIF ent = "OElig" THEN res := 338;
  3197. ELSIF ent = "oelig" THEN res := 339;
  3198. ELSIF ent = "Scaron" THEN res := 352;
  3199. ELSIF ent = "scaron" THEN res := 353;
  3200. ELSIF ent = "Yuml" THEN res := 376;
  3201. ELSIF ent = "circ" THEN res := 710;
  3202. ELSIF ent = "tilde" THEN res := 732;
  3203. ELSIF ent = "ensp" THEN res := 8194;
  3204. ELSIF ent = "emsp" THEN res := 8195;
  3205. ELSIF ent = "thinsp" THEN res := 8201;
  3206. ELSIF ent = "zwnj" THEN res := 8204;
  3207. ELSIF ent = "zwj" THEN res := 8205;
  3208. ELSIF ent = "lrm" THEN res := 8206;
  3209. ELSIF ent = "rlm" THEN res := 8207;
  3210. ELSIF ent = "ndash" THEN res := 8211;
  3211. ELSIF ent = "mdash" THEN res := 8212;
  3212. ELSIF ent = "lsquo" THEN res := 8216;
  3213. ELSIF ent = "rsquo" THEN res := 8217;
  3214. ELSIF ent = "sbquo" THEN res := 8218;
  3215. ELSIF ent = "ldquo" THEN res := 8220;
  3216. ELSIF ent = "rdquo" THEN res := 8221;
  3217. ELSIF ent = "bdquo" THEN res := 8222;
  3218. ELSIF ent = "dagger" THEN res := 8224;
  3219. ELSIF ent = "Dagger" THEN res := 8225;
  3220. ELSIF ent = "permil" THEN res := 8240;
  3221. ELSIF ent = "lsaquo" THEN res := 8249;
  3222. ELSIF ent = "rsaquo" THEN res := 8250;
  3223. ELSE RETURN NIL;
  3224. END;
  3225. IF UTF8Strings.EncodeChar(res, aoc, len) THEN
  3226. RETURN Strings.NewString(aoc);
  3227. ELSE
  3228. RETURN Strings.NewString("*");
  3229. END;
  3230. END GetCharEnt;
  3231. BEGIN
  3232. IF FontExists(defSerif) THEN serif := defSerif; ELSE serif := defaultFont END;
  3233. IF FontExists(defSansSerif) THEN sansSerif := defSansSerif; ELSE sansSerif := defaultFont END;
  3234. IF FontExists(defCursive) THEN cursive := defCursive; ELSE cursive := defaultFont END;
  3235. IF FontExists(defFantasy) THEN fantasy := defFantasy; ELSE fantasy := defaultFont END;
  3236. IF FontExists(defMonospace) THEN monospace := defMonospace; ELSE monospace := defaultFont END;
  3237. END HTMLTransformer.