ntmprint.red 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887
  1. % ----------------------------------------------------------------------
  2. % $Id: tmprint.red,v 1.10 2004/11/20 20:50:14 seidl Exp $
  3. % ----------------------------------------------------------------------
  4. % Copyright (c) 2003-2004 A. Dolzmann, A. Seidl, and T. Sturm
  5. % changes by A C Norman, 2005
  6. % ----------------------------------------------------------------------
  7. %
  8. %
  9. % $Log: tmprint.red,v $
  10. % Revision 1.10 2004/11/20 20:50:14 seidl
  11. % Linelength hack established again, only if Texmacs runs. Removed
  12. % centering and curly brackets from fancy-out-header and -trailer.
  13. % New switch promptnumbers, turned off only if Texmacs is running.
  14. %
  15. % Revision 1.9 2004/11/19 00:52:26 seidl
  16. % This and all earlier entries in change log discarded, because major
  17. % hacks most of the way through have happened since.
  18. %
  19. % Revision 1.1 2003/11/11 11:08:57 sturm
  20. % Inital check-in.
  21. % This is the original version by Andrey Grozin as obtained from fmprint.red
  22. % via patching.
  23. %
  24. % ----------------------------------------------------------------------
  25. module tmprint; % Output module for TeXmacs interface
  26. % Fancy output package for symbolic expressions.
  27. % using TEX as intermediate language. The exact details here are tuned
  28. % to work with TeXmacs, which reuires something close to but not 100%
  29. % identical to standard LaTeX.
  30. % Author: Herbert Melenk, using ideas of maprin.red (A.C.H, A.C.N).
  31. % Copyright (c) 1993 RAND, Konrad-Zuse-Zentrum. All rights reserved.
  32. % Significant subsequent updates by A Grozin, T Sturm,
  33. % A Dolzman, A Seidl and A Norman, 2003-2005
  34. % switches
  35. %
  36. % ON FANCY enable algebraic output processing by this module
  37. % ON PROMPTNUMBER enable the default REDUCE prompt scheme. This
  38. % switch is so that numbering can be disabled.
  39. % ON REDFRONT_MODE adjustments that help with the REDFRONT interface
  40. %
  41. % ON FANCY_LOWER case-fold stuff
  42. % properties used in this module:
  43. %
  44. % fancy-prifn print function for an operator
  45. %
  46. % fancy-pprifn print function for an operator including current
  47. % operator precedence for infix printing
  48. %
  49. % fancy-prtch string for infix printing of an operator
  50. %
  51. % fancy-special-symbol
  52. % print expression for a non-indexed item
  53. % string with TEX expression "\alpha"
  54. % or (now depracated!)
  55. % number referring ASCII symbol code
  56. %
  57. % fancy-infix-symbol special-symbol for infix operators
  58. %
  59. % fancy-prefix-symbol special symbol for prefix operators
  60. %
  61. create!-package('(tmprint),nil);
  62. fluid '(
  63. !*list
  64. !*nat
  65. !*revpri
  66. p!*!*
  67. tablevel!*
  68. sumlevel!*
  69. outputhandler!*
  70. outputhandler!-stack!*
  71. posn!*
  72. long!*
  73. obrkp!* % outside-brackets-p
  74. );
  75. global '(charassoc!* ofl!*);
  76. switch list,revpri;
  77. % Global variables initialized in this section.
  78. fluid '(
  79. fancy!-switch!-on!*
  80. fancy!-switch!-off!*
  81. !*fancy!-mode
  82. fancy!-line!*
  83. fancy!-page!*
  84. !*fancy!-lower % control of conversion to lower case
  85. );
  86. fancy!-switch!-on!* := int2id 16$
  87. fancy!-switch!-off!* := int2id 17$
  88. !*fancy!-lower := nil; % case fold things to lower case if TRUE
  89. global '(fancy_lower_digits fancy_print_df);
  90. share fancy_lower_digits; % T, NIL or ALL.
  91. if null fancy_lower_digits then fancy_lower_digits:=t;
  92. share fancy_print_df; % PARTIAL, TOTAL, INDEXED.
  93. if null fancy_print_df then fancy_print_df := 'partial;
  94. switch fancy;
  95. put('fancy,'simpfg,
  96. '((t (fmp!-switch t))
  97. (nil (fmp!-switch nil)) ));
  98. % Some comments about outputhandler!*.
  99. %
  100. % maprin and terpri* are high level entries into the math printing code,
  101. % and mathprint is an even hight level entrypoint that calls the two
  102. % of them. Each of them check outputhandler!* and call via it.
  103. % If outputhandler!* is nil then terpri!* does its work directly, while
  104. % maprin calls maprint(u,0).
  105. %
  106. % At present outputhandler!* is used by tmprint (and friends) and by the
  107. % openmath print code (which quite unnecessarily and unreasonably redefined
  108. % the function ONOFF as part of the way it gets outputhandler!* set).
  109. %
  110. % Note however that the main REDUCE supervisor (begin1) calls begin11 to
  111. % process an expression, and that then uses assgnpri to display any
  112. % algebraic-mode output. "assgnpri" has a final argument that can have values
  113. % 'first, nil, 'last or 'only and those control whether terpri!* is called
  114. % so that multiple items can be displayed on one line (when necessary, eg
  115. % with a WRITE statement).
  116. %
  117. % Note also that !*tex and the function vecp (and to a lesser extent the
  118. % sprifn property) subvert things, so the avector and tri packages may not be
  119. % compatible with tmprint, and excalc/fide/rlfi may not get the sprifn benefit
  120. % via it. Also !*fort is incompatible.
  121. % scope/coddom.red defined dm!-print in a way that is not tmprint-aware or
  122. % friendly.
  123. % MANY MANY packages call prin2!* clearly expecting use of it and terpri!*
  124. % to cooperate.
  125. % tps/tpseval.red, rataprx/decrep.red, hephys/physop.red and others access
  126. % posn!* directly.
  127. % rprint, prettyprint, some rlisp88 do so too but might be less expected to
  128. % work well with tmprint - but the whole issue of Lisp-style (as distinct
  129. % from algebraic) output needs review.
  130. % factor!-trace is output-position sensitive.
  131. %
  132. % Hah another nasty. alg/intro.red redefined typerr (from rlisp/lpri.red),
  133. % at least having the decency to comment that it is doing so, and presumably
  134. % to produce a REDUCE rather than an RLISP variant. It adds stuff to pline!*
  135. % and updates posn!* in the hope that terpri!* (which it then calls) will
  136. % notice, but in the tmprint case this leads to lossage. Probably prin2!*
  137. % needs redirection via outputhandler!*.
  138. symbolic procedure fmp!-switch mode;
  139. if mode then <<
  140. if outputhandler!* neq 'fancy!-output then <<
  141. outputhandler!-stack!* := outputhandler!* . outputhandler!-stack!*;
  142. outputhandler!* := 'fancy!-output >>;
  143. % with CSL I want to be able to switch texmacs mode on and off dynamically,
  144. % so I switch off prompt numbering as I enter texmacs mode and put it
  145. % back on on the way out.
  146. if member('csl,lispsystem!*) and
  147. member('texmacs,lispsystem!*) then off1 'promptnumbers >>
  148. else <<
  149. if outputhandler!* = 'fancy!-output then <<
  150. outputhandler!* := car outputhandler!-stack!*;
  151. outputhandler!-stack!* := cdr outputhandler!-stack!* >>
  152. % With CSL I want to have tmprint loaded as part of the initial lisp image,
  153. % and I want to call fmp!-switch early on based on whether I believe I should
  154. % use the CSL internal display mode or an external viewer such as Texmacs.
  155. % I thus want to be able to say "do not use fancy mode" rather explicitly
  156. % from there whether or not it happened to be enabled in the system that
  157. % saved the image file. So I really do not want this rederr call! I switch
  158. % promptnumbers back on here for the case when Texmacs fancy printing is
  159. % not wanted but the prompt colouring stuff from this file is activated (eg
  160. % because redfront is in use, or Texmacs but without the fancy option?). I
  161. % believe that mostly with CSL prompts are handled by CSL itself and so
  162. % the promptnumbering flag is not relevant uless it has been set up for
  163. % external Texmacs use...
  164. else if not member('csl, lispsystem!*) then
  165. rederr "FANCY is not current output handler";
  166. if member('csl, lispsystem!*) then on1 'promptnumbers >>;
  167. % The next two functions provide abstraction for conversion between
  168. % strings and lists of character objects.
  169. !#if (memq 'csl lispsystem!*)
  170. % Under CSL the eventual state will be that IF output is going directly
  171. % to a window that can support maths display then I will send stuff there
  172. % so it gets displayed using the CSL embedded code. If on the other hand
  173. % output is going to a pipe or a file or basically anything other than
  174. % directly to the screen I will issue the codes that texmacs likes to see.
  175. %
  176. % Convert a list of character objects into a string.
  177. % (The function list!-to!-string already exists...)
  178. % Convert a string into a list of character objects.
  179. smacro procedure string!-to!-list a;
  180. explode2 a;
  181. % Print a string without ANY conversion or adjustment, so if the string
  182. % has control characters etc in it they get transmitted unchanged. Well
  183. % let me express some reservations about what might happen if the string
  184. % contains tabs and newlines - the lower level system IO code might
  185. % interpret same...
  186. smacro procedure raw!-print!-string s;
  187. prin2 s;
  188. % Print the character whose code is n.
  189. smacro procedure writechar n;
  190. tyo n; % Like "prin2 int2id n"
  191. % Convert a symbol or string to characters but ensure that all
  192. % output characters are folded to lower case.
  193. % CSL already has explode2lc;
  194. !#else
  195. smacro procedure list!-to!-string a;
  196. compress ('!" . append(a, '(!")));
  197. smacro procedure string!-to!-list a;
  198. explode2 a;
  199. % I do not know if this has to be like this in PSL, but it reflects
  200. % what was in the code.
  201. symbolic procedure raw!-print!-string s;
  202. for each x in string!-to!-list s do prin2 x;
  203. % writechar already exists in PSL.
  204. symbolic procedure explode2lc s;
  205. explode2 s where !*lower = t;
  206. !#endif
  207. symbolic procedure fancy!-tex s;
  208. % test output: print tex string.
  209. << prin2 fancy!-switch!-on!*;
  210. raw!-print!-string s;
  211. prin2t fancy!-switch!-off!*
  212. >>;
  213. symbolic procedure fancy!-out!-item(it);
  214. if atom it then prin2 it else
  215. if eqcar(it,'ascii) then writechar(cadr it) else
  216. if eqcar(it,'tab) then
  217. for i:=1:cdr it do prin2 " "
  218. else
  219. if eqcar(it,'bkt) then
  220. begin
  221. scalar b;
  222. % The structure introduced for brackets has a couple of filelds that are
  223. % not used here and which are thus redundant. In fact all I seem to need is
  224. % the character itself, and it is not clear that any cases other than
  225. % "{" "}" "(" and ")" are ever used. So perhaps this could all be simplified
  226. % away!
  227. b:=caddr it;
  228. if b memq '( !( !{ ) then prin2 "\left" else prin2 "\right";
  229. if b member '(!{ !}) then prin2 "\";
  230. prin2 b;
  231. end
  232. else rederr "unknown print item";
  233. symbolic procedure set!-fancymode bool;
  234. if bool neq !*fancy!-mode then
  235. << !*fancy!-mode:=bool;
  236. % fancy!-page only becomes relevant in *list mode when material is passed
  237. % to texmacs ion several chunks. The tab at the start of a line looks to me
  238. % as if it is another think that texmacs should organize if that layout is
  239. % best, and it ought not to be done here...
  240. fancy!-page!*:=nil;
  241. fancy!-line!*:= '((tab . 1));
  242. sumlevel!* := tablevel!* := 1
  243. >>;
  244. !#if (memq 'csl lispsystem!*)
  245. fluid '(!*standard!-output!* !*math!-output!* !*spool!-output!*);
  246. !#endif
  247. symbolic procedure fancy!-output(mode,l);
  248. % Interface routine.
  249. % ACN does not understand the "posn!*>2" filter here. To avoid some
  250. % bad consequences it was having for my new screen/log-file stuff it now only
  251. % applies in maprin mode not terpri mode, but it would be nice if somebody
  252. % could explain to me just why it was needed in the first case at all. I can
  253. % imagine that if "on fancy" is acticated when there is still some partly-
  254. % printed expression (in non-fancy mode) buffered up the terpri!* to flush it
  255. % may need special care. But if that is what it is about I would suggest that
  256. % treatment be applied in fmp!-switch not here...
  257. %
  258. % Well now ACN partially understands it, and knows that it is broken in the
  259. % face or some error recovery, eg if the input ("a"+1) is presented to
  260. % REDUCE. It will be adjusted sometime later when the rest of the code has
  261. % stabilised again.
  262. %
  263. %
  264. if ofl!* or (mode='maprin and posn!*>2) or not !*nat then <<
  265. % not terminal handler or current output line non-empty.
  266. if mode = 'maprin then maprin l
  267. else if mode = 'prin2!* then prin2!* l
  268. else terpri!*(l) >> where outputhandler!* = nil
  269. else
  270. % I want to do some more magic for CSL here. In CSL the system can be launched
  271. % or run-time configured so that a transcript of screen output goes to a
  272. % file, the "log file". In the CSL sources the handle for this file is known
  273. % as "spool_file". It does not look sensible to me that TeX-ified maths
  274. % should go there even if that is what best goes to the screen. Thus I think I
  275. % want fancy mode in CSL with a spool_file enabled to do something rather like
  276. %
  277. % wrs math-output-destination;
  278. % fancy!-maprin0 expression;
  279. % wrs spool_file;
  280. % maprin0 expression;
  281. % wrs undivided standard output;
  282. %
  283. % Rather than using "wrs" here I will re-bind the CSL variable
  284. % *standard-output*. This achieves a similar effect but guarantees that
  285. % the regular situation is restored if there is ANY sort of exit from the
  286. % maths display code - eg a user-generated interrupt. It I had used wrs then
  287. % I could perhaps have restored things using errorset, but this feels easier.
  288. % Also this little section of code is pretty CSL-specific since it is
  289. % working with the CSL-embedded display code, so I do not feel bad about
  290. % going beyond Standard Lisp.
  291. %
  292. % A further wrinkle on this wants to be that garbage collector and diagnostic
  293. % output always goes to the undivided standard output in the normal way, and
  294. % this output to the "math-output" stream can never be interrupted by any
  295. % such. If a section of maths display is not completed then the maths output
  296. % will find that it has a fancy_header but no fancy_trailer, and any request
  297. % for user input or any error exit will force terminate it leaving a visibly
  298. % incomplete fragment (which the display code can detect and ignore).
  299. %
  300. % Note that the risk of error or garbage collection during maths display is
  301. % not actually terribly high since all that is done between the generation
  302. % of header & trailer is a load of calls to fancy!-out!-item, ie ready
  303. % prepared sequences of items get printed. Also the normal maprin just buffers
  304. % things up and only displays them when terpri!* is called. So I can afford to
  305. % use both fancy!-maprin0 and maprin and then fuss about destinations a bit
  306. % more at terpri!* time. In this regard observe that because I have got here
  307. % I know I on in "on nat" mode. In that case setting pline!* to nil has the
  308. % effect of discarding any built-up layout.
  309. << set!-fancymode t;
  310. if mode = 'maprin then <<
  311. !#if (memq 'csl lispsystem!*)
  312. % math!-display 1 will not do anything, but returns true if a spool_file
  313. % is active.
  314. if getd 'math!-display and
  315. math!-display 0 and
  316. math!-display 1 then <<
  317. maprin l where outputhandler!* = nil >>;
  318. !#endif
  319. fancy!-maprin0 l >>
  320. else if mode = 'prin2!* then <<
  321. !#if (memq 'csl lispsystem!*)
  322. if getd 'math!-display and
  323. math!-display 0 and
  324. math!-display 1 then <<
  325. prin2!* l where outputhandler!* = nil >>;
  326. !#endif
  327. fancy!-prin2 l >>
  328. else <<
  329. !#if (memq 'csl lispsystem!*)
  330. if getd 'math!-display and
  331. math!-display 0 and
  332. math!-display 1 then <<
  333. terpri!* l where outputhandler!* = nil
  334. where !*standard!-output!* = !*spool!-output!* >>;
  335. !#endif
  336. fancy!-flush() >> >>;
  337. symbolic procedure fancy!-out!-header();
  338. <<
  339. if posn()>0 then terpri();
  340. prin2 int2id 2;
  341. prin2 "latex:\black$\displaystyle "
  342. >>;
  343. symbolic procedure fancy!-out!-trailer();
  344. <<
  345. prin2 "$";
  346. prin2 int2id 5
  347. >>;
  348. !#if (memq 'csl lispsystem!*)
  349. symbolic procedure fancy!-flush();
  350. begin
  351. scalar ll;
  352. ll := linelength 30000;
  353. fancy!-terpri!*();
  354. if getd 'math!-display and math!-display 0 then <<
  355. math!-display 2; % clear out any previous junk
  356. for each line in reverse fancy!-page!* do
  357. if line and not eqcar(car line,'tab) then <<
  358. for each it in reverse line do fancy!-out!-item it;
  359. terpri() >>;
  360. math!-display 3 >> where !*standard!-output!*=!*math!-output!*
  361. else for each line in reverse fancy!-page!* do
  362. if line and not eqcar(car line,'tab) then <<
  363. fancy!-out!-header();
  364. for each it in reverse line do fancy!-out!-item it;
  365. fancy!-out!-trailer() >>;
  366. set!-fancymode nil;
  367. linelength ll
  368. end;
  369. !#else
  370. symbolic procedure fancy!-flush();
  371. begin
  372. scalar ll, !*lower; % Rebinding *lower is needed for PSL here
  373. ll := linelength 30000;
  374. fancy!-terpri!*();
  375. for each line in reverse fancy!-page!* do
  376. if line and not eqcar(car line,'tab) then <<
  377. fancy!-out!-header();
  378. for each it in reverse line do fancy!-out!-item it;
  379. fancy!-out!-trailer() >>;
  380. set!-fancymode nil;
  381. linelength ll
  382. end;
  383. !#endif
  384. %---------------- primitives -----------------------------------
  385. % fancy-princ outputs an item without any adjustment. It is used in cases
  386. % that are known to be simple. Well actually it just dumps out something
  387. % that fancy!-out!-item will deal with, so tabs and brackets may be
  388. % passed as more complicated stuff than mere strings.
  389. symbolic procedure fancy!-princ u;
  390. fancy!-line!* := u . fancy!-line!*;
  391. % fancy!-special!-symbol should normally be given a string, and in that
  392. % case it just displays it. If given an integer (n) it generates the
  393. % output "\symb{n}" and somebody needs to know the numeric codes that
  394. % texmacs accepts.
  395. symbolic procedure fancy!-special!-symbol u;
  396. if numberp u then <<
  397. fancy!-princ "\symb{";
  398. fancy!-princ u;
  399. fancy!-princ "}" >>
  400. else fancy!-princ u;
  401. % fancy!-prin2 outputs an item, but it does a variety of "clever" things.
  402. % (a) numbers go through code that MAY at some stage need to do special
  403. % things with very large ones.
  404. % (b) If an identifier is of the form xxx123 (say, with digits at the
  405. % end) they are lowered.
  406. % (c) An identifier that is more than one character long has \mathrm
  407. % added.
  408. % (d) Strings with " " or "_" within them get "\" escapes added.
  409. symbolic procedure fancy!-prin2 u;
  410. begin scalar str,id, longname;
  411. if atom u and eqcar(explode2 u,'!\) then <<
  412. fancy!-line!* := u . fancy!-line!*;
  413. return >>
  414. else if numberp u then <<
  415. % The behaviour here seems really odd to me but appears to match what the
  416. % version of tmprint in the development tree at the end of April 2005
  417. % does... I suspect that either ALL numbers should be set in \mathrm or
  418. % none should be.
  419. if u >= 10 or u < 0 then
  420. fancy!-line!* := '!} . u . '!\mathrm!{ . fancy!-line!*
  421. else fancy!-line!* := u . fancy!-line!*;
  422. return >>;
  423. str := stringp u;
  424. id := idp u and not digit u;
  425. u:= if atom u then <<
  426. if !*fancy!-lower then explode2lc u
  427. else explode2 u >>
  428. else {u};
  429. if id then <<
  430. u:=fancy!-lower!-digits fancy!-esc u;
  431. if car u = '!\mathrm!{ then longname := t >>
  432. else if car u neq '!\ and cdr u then <<
  433. fancy!-line!* := '!\mathrm!{ . fancy!-line!*;
  434. longname := t >>;
  435. for each x in u do <<
  436. if str and (x='! or x='!_)
  437. then fancy!-line!* := '!\ . fancy!-line!*;
  438. fancy!-line!* :=
  439. (if id and !*fancy!-lower then red!-char!-downcase x else x) .
  440. fancy!-line!* >>;
  441. if longname then fancy!-line!* := "}" . fancy!-line!*
  442. end;
  443. symbolic procedure fancy!-last!-symbol();
  444. if fancy!-line!* then car fancy!-line!*;
  445. charassoc!* :=
  446. '((!A . !a) (!B . !b) (!C . !c) (!D . !d) (!E . !e) (!F . !f)
  447. (!G . !g) (!H . !h) (!I . !i) (!J . !j) (!K . !k) (!L . !l)
  448. (!M . !m) (!N . !n) (!O . !o) (!P . !p) (!Q . !q) (!R . !r)
  449. (!S . !s) (!T . !t) (!U . !u) (!V . !v) (!W . !w) (!X . !x)
  450. (!Y . !y) (!Z . !z));
  451. symbolic procedure red!-char!-downcase u;
  452. (if x then cdr x else u) where x = atsoc(u,charassoc!*);
  453. symbolic procedure fancy!-prin2number u;
  454. % we print a number eventually causing a line break
  455. % for very big numbers. Well the issue of line-breaks in the texmacs
  456. % interface is a messy one... I think that the model to be used is that
  457. % ALL linebreak decisions must be left to texmacs itself and so NO
  458. % line-breaking will be done by this code... However it is possible that
  459. % that will not work well and it may be necessary to render big values
  460. % eg as (d1*10^n1 + d2*10^n2 + ... + dj).
  461. fancy!-prin2number1 (if atom u then explode2 u else u);
  462. symbolic procedure fancy!-prin2number1 u;
  463. for each c in u do
  464. fancy!-princ c;
  465. % Put escape chars in front of any underscores.
  466. symbolic procedure fancy!-esc u;
  467. if not('!_ memq u) then u else
  468. (if car u eq '!_ then '!\ . w else w)
  469. where w = car u . fancy!-esc cdr u;
  470. % This is going to split a name of the form abc123 into
  471. % something like abc_{123}. Well it takes a list of characters
  472. % as its argument and any string of digits within that should be
  473. % lowered, so eg abc123xyz789 becomes abc_{123}xyz_{789}
  474. % however as a yet more messy step, if a string of non-digits is a
  475. % special word it gets mapped onto the corresponding symbol, so
  476. % eg alpha, infinity etc het mapped onto \alpha, \infty...
  477. symbolic procedure fancy!-lower!-digits1 u;
  478. begin
  479. scalar r, w, w1, longname;
  480. u := reverse u;
  481. while u do <<
  482. % Collect the next word (without any digits in it)
  483. while u and not digit car u do <<
  484. w := car u . w;
  485. u := cdr u >>;
  486. if w then <<
  487. w1 := intern compress w;
  488. if stringp (w1 := get(w1, 'fancy!-special!-symbol)) then
  489. w := explode2 w1;
  490. longname := car w neq '!\ and cdr w;
  491. r := append(w, r) >>;
  492. % now process and string of digits
  493. if u and digit car u then <<
  494. r := '!} . r;
  495. while u and digit car u do <<
  496. r := car u . r;
  497. u := cdr u >>;
  498. r := '!_ . '!{ . r >> >>;
  499. % Each time around the loop the next character must be either
  500. % a digit or not a digit, and in either case I make progress.
  501. if longname then r := '!\mathrm!{ . r;
  502. return r;
  503. end;
  504. % This procedure judges whether to rewrite a symbol as a susbcripted
  505. % item. It will detect cases of a name that starts with one or more
  506. % non-digits, has at least one digit, and from the location onwards
  507. % consists only of digits. It is used in the default case when
  508. % fancy_lower_digits is neither NIL nor ALL.
  509. symbolic procedure fancy!-lower!-digitstrail u;
  510. begin
  511. % an empty name or one starting with a digit should not be lowered
  512. if null u or digit car u then return nil;
  513. u := cdr u;
  514. % trim any initial non-digits
  515. while u and not digit car u do u := cdr u;
  516. % if nothing is left we do not have even a potential subscript
  517. if null u then return nil;
  518. % scan to check that all the rest is made up of digits, and if so
  519. % declare TRUE.
  520. while u and digit car u do u := cdr u;
  521. return null u
  522. end;
  523. symbolic procedure fancy!-lower!-digits u;
  524. (if null m then u
  525. else if m = 'all or
  526. fancy!-lower!-digitstrail u then
  527. fancy!-lower!-digits1 u
  528. else if null cdr u then u
  529. else '!\mathrm!{ . u
  530. ) where m=fancy!-mode fancy_lower_digits;
  531. % fancy!-terpri!* is only used in two cases...
  532. % (a) At the end of formatting an expression just prior to outputting it.
  533. % In this case it just moves fancy!-line to fancy!-page.
  534. % (b) in *list mode to create a page built up of several lines.
  535. symbolic procedure fancy!-terpri!*();
  536. <<
  537. if fancy!-line!* then
  538. fancy!-page!* := fancy!-line!* . fancy!-page!*;
  539. fancy!-line!*:= {'tab . tablevel!*};
  540. >>;
  541. symbolic procedure fancy!-mode u;
  542. if eqcar(u,'!*sq) then reval u
  543. else u;
  544. %---------------- central formula converter --------------------
  545. % This is just used at the top level, and it arranges that a number
  546. % printed there is never put as \mathrm even though it might be anywhere
  547. % else!
  548. % The behaviour here seems really odd to me but appears to match what the
  549. % version of tmprint in the development tree at the end of April 2005
  550. % does... I suspect that either ALL numbers should be set in \mathrm or
  551. % none should be.
  552. % NB and WARNING here. !*lower in CSL just and only has an effect of
  553. % case-folding INPUT, while (possibly) in PSL it may case-fold OUTPUT.
  554. % re-binding it to NIL here switches off one of these effects if it
  555. % happened to be active...
  556. symbolic procedure fancy!-maprin0 u;
  557. if numberp u then fancy!-princ u
  558. else fancy!-maprint(u,0) where !*lower=nil;
  559. symbolic procedure fancy!-maprin1 u;
  560. fancy!-maprint(u,0) where !*lower=nil;
  561. symbolic procedure fancy!-maprint(l,p!*!*);
  562. % Print expression l at bracket level p!*!* without terminating
  563. % print line. Special cases are handled by:
  564. % pprifn: a print function that includes bracket level as 2nd arg.
  565. % prifn: a print function with one argument.
  566. (begin scalar p,x;
  567. p := p!*!*; % p!*!* needed for (expt a (quotient ...)) case.
  568. if null l then return nil;
  569. if atom l then return fancy!-maprint!-atom(l,p);
  570. if not atom car l then return fancy!-maprint(car l,p);
  571. l := fancy!-convert(l,nil);
  572. if (x:=get(car l,'fancy!-reform)) then
  573. return fancy!-maprint(apply1(x,l),p)
  574. else if (x := get(car l,'fancy!-pprifn)) then
  575. return apply2(x,l,p)
  576. else if (x := get(car l,'fancy!-prifn)) then
  577. return apply1(x,l)
  578. else if get(car l,'print!-format) then
  579. return fancy!-print!-format(l,p);
  580. % eventually convert expression to a different form
  581. % for printing.
  582. l := fancy!-convert(l,'infix);
  583. % printing operators with integer argument in index form.
  584. if flagp(car l,'print!-indexed) then <<
  585. fancy!-prefix!-operator(car l);
  586. fancy!-print!-indexlist cdr l >>
  587. else if x := get(car l,'infix) then <<
  588. p := not(x>p);
  589. if p then fancy!-in!-brackets
  590. {'fancy!-inprint,mkquote car l,x,mkquote cdr l}
  591. else fancy!-inprint(car l,x,cdr l) >>
  592. else <<
  593. fancy!-prefix!-operator(car l);
  594. obrkp!* := nil;
  595. fancy!-print!-function!-arguments cdr l >>
  596. end ) where obrkp!*=obrkp!*;
  597. symbolic procedure fancy!-convert(l,m);
  598. % special converters.
  599. if eqcar(l,'expt) and cadr l= 'e and
  600. ( m='infix or treesizep(l,20) )
  601. then {'exp,caddr l}
  602. else l;
  603. symbolic procedure fancy!-print!-function!-arguments u;
  604. % u is a parameter list for a function.
  605. fancy!-in!-brackets
  606. u and {'fancy!-inprint, mkquote '!*comma!*,0,mkquote u};
  607. symbolic procedure fancy!-maprint!-atom(l,p);
  608. begin
  609. scalar x;
  610. if (x:=get(l,'fancy!-special!-symbol)) then
  611. fancy!-special!-symbol x
  612. else if vectorp l then <<
  613. fancy!-princ "[";
  614. l:=for i:=0:upbv l collect getv(l,i);
  615. fancy!-inprint(",",0,l);
  616. fancy!-princ "]" >>
  617. else if not numberp l or (not (l<0) or p<=get('minus,'infix)) then
  618. fancy!-prin2 l
  619. else fancy!-in!-brackets {'fancy!-prin2,mkquote l}
  620. end;
  621. put('print_indexed,'psopfn,'(lambda(u)(flag u 'print!-indexed)));
  622. symbolic procedure fancy!-print!-indexlist l;
  623. fancy!-print!-indexlist1(l,'!_,nil);
  624. symbolic procedure fancy!-print!-indexlist1(l,op,sep);
  625. % print index or exponent lists, with or without separator.
  626. begin scalar obrkp!*;
  627. fancy!-princ op;
  628. fancy!-princ "{";
  629. fancy!-inprint(sep or 'times,0,l);
  630. fancy!-princ "}"
  631. end;
  632. symbolic procedure fancy!-print!-one!-index i;
  633. begin
  634. scalar obrkp!*;
  635. fancy!-princ "_{";
  636. fancy!-inprint('times,0,{i});
  637. fancy!-princ "}"
  638. end;
  639. symbolic procedure fancy!-in!-brackets u;
  640. % put form into parentheses.
  641. % u: form to be evaluated,
  642. begin
  643. fancy!-prin2 "\left(";
  644. eval u;
  645. fancy!-prin2 "\right)"
  646. end;
  647. symbolic procedure fancy!-in!-braces u;
  648. % put form into braces.
  649. % u: form to be evaluated,
  650. begin
  651. fancy!-prin2 "\left\{";
  652. eval u;
  653. fancy!-prin2 "\right\}"
  654. end;
  655. symbolic procedure fancy!-exptpri(l,p);
  656. begin scalar !*list,pp,q,w1,w2;
  657. pp := not((q:=get('expt,'infix))>p); % Need to parenthesize
  658. w1 := cadr l; w2 := caddr l;
  659. if eqcar(w2,'quotient) and cadr w2 = 1
  660. and (fixp caddr w2 or liter caddr w2) then
  661. return fancy!-sqrtpri!*(w1,caddr w2);
  662. if eqcar(w2,'quotient) and eqcar(cadr w2,'minus)
  663. then w2 := list('minus,list(car w2,cadadr w2,caddr w2))
  664. else w2 := negnumberchk w2;
  665. fancy!-maprint(w1,q);
  666. fancy!-princ "^";
  667. if eqcar(w2,'quotient) and fixp cadr w2 and fixp caddr w2 then <<
  668. fancy!-princ "{";
  669. fancy!-inprint('!/,0,cdr w2);
  670. fancy!-princ "}" >>
  671. else fancy!-maprint!-tex!-bkt(w2,0,nil)
  672. end;
  673. put('expt,'fancy!-pprifn,'fancy!-exptpri);
  674. symbolic procedure fancy!-inprint(op,p,l);
  675. (begin scalar x,y;
  676. % print product of quotients using *.
  677. if op = 'times and
  678. eqcar(car l,'quotient) and
  679. cdr l and
  680. eqcar(cadr l,'quotient) then op:='!*;
  681. if op eq 'plus and !*revpri then l := reverse l;
  682. if not get(op,'alt) then <<
  683. if op eq 'not then <<
  684. fancy!-oprin op;
  685. return fancy!-maprint(car l,get('not,'infix)) >>;
  686. if op eq 'setq and
  687. not atom (x := car reverse l) and
  688. idp car x and
  689. (y := getrtype x) and
  690. (y := get(get(y,'tag),'fancy!-setprifn)) then
  691. return apply2(y,car l,x);
  692. if not atom car l and
  693. idp caar l and
  694. ((x := get(caar l,'fancy!-prifn))
  695. or (x := get(caar l,'fancy!-pprifn))) and
  696. (get(x,op) eq 'inbrackets) then <<
  697. % to avoid mix up of indices and exponents.
  698. fancy!-in!-brackets
  699. {'fancy!-maprint,mkquote car l,p} >>;
  700. fancy!-maprint(car l, p);
  701. l := cdr l >>;
  702. if !*list and obrkp!* and memq(op,'(plus minus)) then
  703. <<sumlevel!*:=sumlevel!*+1;
  704. tablevel!* := tablevel!* #+ 1>>;
  705. fancy!-inprint1(op,p,l)
  706. end) where tablevel!*=tablevel!*, sumlevel!*=sumlevel!*;
  707. symbolic procedure fancy!-inprint1(op,p,l);
  708. % main line (top level) infix printing, allow line break;
  709. begin scalar lop;
  710. for each v in l do <<
  711. lop := op;
  712. if op='plus and eqcar(v,'minus) then <<
  713. lop := 'minus;
  714. v:= cadr v>>;
  715. fancy!-oprin lop;
  716. fancy!-maprint(negnumberchk v, p) >>
  717. end;
  718. symbolic procedure fancy!-inprintlist(op,p,l);
  719. % inside algebraic list
  720. begin scalar fst,v;
  721. loop:
  722. if null l then return nil;
  723. v := car l; l:= cdr l;
  724. if fst then
  725. << fancy!-princ "\,";
  726. fancy!-oprin op;
  727. fancy!-princ "\,";
  728. >>;
  729. fancy!-maprin(v,0);
  730. fst := t;
  731. goto loop;
  732. end;
  733. put('times,'fancy!-prtch,"\*");
  734. symbolic procedure fancy!-oprin op;
  735. begin scalar x;
  736. if (x:=get(op,'fancy!-prtch)) then fancy!-princ x
  737. else if (x:=get(op,'fancy!-infix!-symbol)) then fancy!-princ x
  738. else if null(x:=get(op,'prtch)) then fancy!-prin2 op
  739. else <<
  740. % The issue of "*list" style printing and a texmacs interface is something
  741. % that is probably cause for worry. Eg the line-breaks in *list mode may
  742. % really mess up texmacs wrt its ability to understand the whole expression.
  743. if !*list and obrkp!* and
  744. op memq '(plus minus) and
  745. sumlevel!*=2 then fancy!-terpri!*();
  746. fancy!-prin2 x >>
  747. end;
  748. put('alpha,'fancy!-special!-symbol,"\alpha");
  749. put('beta,'fancy!-special!-symbol,"\beta");
  750. put('gamma,'fancy!-special!-symbol,"\gamma");
  751. put('delta,'fancy!-special!-symbol,"\delta");
  752. put('epsilon,'fancy!-special!-symbol,"\varepsilon");
  753. put('zeta,'fancy!-special!-symbol,"\zeta");
  754. put('eta,'fancy!-special!-symbol,"\eta");
  755. put('theta,'fancy!-special!-symbol,"\theta");
  756. put('iota,'fancy!-special!-symbol,"\iota");
  757. put('kappa,'fancy!-special!-symbol,"\varkappa");
  758. put('lambda,'fancy!-special!-symbol,"\lambda");
  759. put('mu,'fancy!-special!-symbol,"\mu");
  760. put('nu,'fancy!-special!-symbol,"\nu");
  761. put('xi,'fancy!-special!-symbol,"\xi");
  762. put('pi,'fancy!-special!-symbol,"\pi");
  763. put('rho,'fancy!-special!-symbol,"\rho");
  764. put('sigma,'fancy!-special!-symbol,"\sigma");
  765. put('tau,'fancy!-special!-symbol,"\tau");
  766. put('upsilon,'fancy!-special!-symbol,"\upsilon");
  767. put('phi,'fancy!-special!-symbol,"\phi");
  768. put('chi,'fancy!-special!-symbol,"\chi");
  769. put('psi,'fancy!-special!-symbol,"\psi");
  770. put('omega,'fancy!-special!-symbol,"\omega");
  771. !#if (memq 'csl lispsystem!*)
  772. deflist('(
  773. % Many of these are just the same glyphs as ordinary upper case letters,
  774. % and so for compatibility with external viewers I map those ones onto
  775. % letters with the "\mathit" qualifier to force the font.
  776. (!Alpha "\mathit{A}") (!Beta "\mathit{B}") (!Chi "\Chi ")
  777. (!Delta "\Delta ") (!Epsilon "\mathit{E}") (!Phi "\Phi ")
  778. (!Gamma "\Gamma ") (!Eta "\mathit{H}") (!Iota "\mathit{I}")
  779. (!vartheta "\vartheta") (!Kappa "\Kappa ") (!Lambda "\Lambda ")
  780. (!Mu "\mathit{M}") (!Nu "\mathit{N}") (!O "\mathit{O}")
  781. (!Pi "\Pi ") (!Theta "\Theta ") (!Rho "\mathit{R}")
  782. (!Sigma "\Sigma ") (!Tau "\Tau ") (!Upsilon "\Upsilon ")
  783. (!Omega "\Omega ") (!Xi "\Xi ") (!Psi "\Psi ")
  784. (!Zeta "\mathit{Z}") (!varphi "\varphi ")
  785. ),'fancy!-special!-symbol);
  786. !#else
  787. % In an earlier version some items here were specified as ascii codes, eg
  788. % A as 65 rather than "A". I can not see any way that this matters, but
  789. % note it here in case (eg) font choice actually depends on it. Certainly
  790. % you should observe that in the CSL case I use a math-italic font
  791. % explicitly...
  792. if 'a neq '!A then deflist('(
  793. (!Alpha "A") (!Beta "B") (!Chi "\Chi") (!Delta "\Delta")
  794. (!Epsilon "E")(!Phi "\Phi") (!Gamma "\Gamma")(!Eta "H")
  795. (!Iota "I") (vartheta "\vartheta")(!Kappa "K")(!Lambda "\Lambda")
  796. (!Mu "M")(!Nu "N")(!O "O")(!Pi "\Pi")(!Theta "\Theta")
  797. (!Rho "R")(!Sigma "\Sigma")(!Tau "\Tau")(!Upsilon "\Upsilon")
  798. (!Omega "\Omega") (!Xi "\Xi")(!Psi "\Psi")(!Zeta "Z")
  799. (varphi "\varphi")
  800. ),'fancy!-special!-symbol);
  801. !#endif
  802. put('infinity,'fancy!-special!-symbol,"\infty ");
  803. put('partial!-df,'fancy!-special!-symbol,"\partial ");
  804. put('empty!-set,'fancy!-special!-symbol,"\emptyset ");
  805. put('not,'fancy!-special!-symbol,"\neg ");
  806. put('not,'fancy!-infix!-symbol,"\neg ");
  807. put('leq,'fancy!-infix!-symbol,"\leq ");
  808. put('geq,'fancy!-infix!-symbol,"\geq ");
  809. put('neq,'fancy!-infix!-symbol,"\neq ");
  810. put('intersection,'fancy!-infix!-symbol,"\cap ");
  811. put('union,'fancy!-infix!-symbol,"\cup ");
  812. put('member,'fancy!-infix!-symbol,"\in ");
  813. put('and,'fancy!-infix!-symbol,"\wedge ");
  814. put('or,'fancy!-infix!-symbol,"\vee ");
  815. put('when,'fancy!-infix!-symbol,"|");
  816. put('!*wcomma!*,'fancy!-infix!-symbol,",\,");
  817. put('replaceby,'fancy!-infix!-symbol,"\Rightarrow ");
  818. put('!~,'fancy!-functionsymbol,"\forall ");
  819. % The following definitions allow for more natural printing of
  820. % conditional expressions within rule lists.
  821. symbolic procedure fancy!-condpri(u,p);
  822. begin
  823. if p>0 then fancy!-princ "\left(";
  824. while (u := cdr u) do <<
  825. if not(caar u eq 't) then <<
  826. fancy!-princ "if\ ";
  827. fancy!-maprin0 caar u;
  828. fancy!-princ "\,then\," >>;
  829. fancy!-maprin0 cadar u;
  830. if cdr u then <<
  831. fancy!-princ "\,else\," >> >>;
  832. if p>0 then fancy!-prin2 "\right)"
  833. end;
  834. put('cond,'fancy!-pprifn,'fancy!-condpri);
  835. symbolic procedure fancy!-revalpri u;
  836. fancy!-maprin0 fancy!-unquote cadr u;
  837. symbolic procedure fancy!-unquote u;
  838. if eqcar(u,'list) then for each x in cdr u collect
  839. fancy!-unquote x
  840. else if eqcar(u,'quote) then cadr u
  841. else u;
  842. put('aeval,'fancy!-prifn,'fancy!-revalpri);
  843. put('aeval!*,'fancy!-prifn,'fancy!-revalpri);
  844. put('reval,'fancy!-prifn,'fancy!-revalpri);
  845. put('reval!*,'fancy!-prifn,'fancy!-revalpri);
  846. put('aminusp!:,'fancy!-prifn,'fancy!-patpri);
  847. put('aminusp!:,'fancy!-pat,'(lessp !&1 0));
  848. symbolic procedure fancy!-patpri u;
  849. begin scalar p;
  850. p:=subst(fancy!-unquote cadr u,'!&1,
  851. get(car u,'fancy!-pat));
  852. return fancy!-maprin0 p
  853. end;
  854. symbolic procedure fancy!-boolvalpri u;
  855. fancy!-maprin0 cadr u;
  856. put('boolvalue!*,'fancy!-prifn,'fancy!-boolvalpri);
  857. symbolic procedure fancy!-quotpri u;
  858. begin
  859. fancy!-princ "\frac";
  860. fancy!-maprint!-tex!-bkt(cadr u,0,t);
  861. fancy!-maprint!-tex!-bkt(caddr u,0,nil);
  862. end;
  863. symbolic procedure fancy!-maprint!-tex!-bkt(u,p,m);
  864. % Produce expression with tex brackets {...} if
  865. % necessary. Ensure that {} unit is in same formula.
  866. % If m=t brackets will be inserted in any case.
  867. begin
  868. if not m and (numberp u and 0<=u and u <=9 or liter u) then
  869. return fancy!-prin2 u;
  870. fancy!-princ "{";
  871. fancy!-maprint(u,p);
  872. fancy!-princ "}"
  873. end;
  874. put('quotient,'fancy!-prifn,'fancy!-quotpri);
  875. %-----------------------------------------------------------
  876. %
  877. % support for print format property
  878. %
  879. %-----------------------------------------------------------
  880. % only specfn/ratalgo.red (for pochammer) even tries to use this, so
  881. % I somewhat vote for removing it.
  882. %symbolic procedure print_format(f,pat);
  883. % % Assign a print pattern p to the operator form f.
  884. % put(car f, 'print!-format, (cdr f . pat) . get(car f, 'print!-format));
  885. %
  886. %symbolic operator print_format;
  887. %
  888. %symbolic procedure fancy!-print!-format(u,p);
  889. % begin scalar fmt,fmtl,a;
  890. % fmtl:=get(car u,'print!-format);
  891. % l:
  892. % fmt := car fmtl; fmtl := cdr fmtl;
  893. % if length(car fmt) neq length cdr u then goto l;
  894. % a:=pair(car fmt,cdr u);
  895. % return fancy!-print!-format1(cdr fmt,p,a);
  896. % end;
  897. %
  898. %symbolic procedure fancy!-print!-format1(u,p,a);
  899. % begin scalar x,y,pl,bkt,obkt,q;
  900. % if eqcar(u,'list) then u:= cdr u;
  901. % while u do
  902. % <<x:=car u; u:=cdr u;
  903. % if eqcar(x,'list) then x:=cdr x;
  904. % obkt := bkt; bkt:=nil;
  905. % if obkt then fancy!-princ "{";
  906. % if pairp x then fancy!-print!-format1(x,p,a)
  907. % else if memq(x,'(!( !) !, !. !|)) then
  908. % <<if x eq '!( then <<pl:=p.pl; p:=0>> else
  909. % if x eq '!) then <<p:=car pl; pl:=cdr pl>>;
  910. % fancy!-prin2 x >>
  911. % else if x eq '!_ or x eq '!^ then <<bkt:=t;fancy!-prin2 x>>
  912. % else if q:=assoc(x,a) then fancy!-maprint(cdr q,p)
  913. % else fancy!-maprint(x,p);
  914. % if obkt then fancy!-princ "}" >>
  915. % end;
  916. %
  917. %-----------------------------------------------------------
  918. %
  919. % some operator specific print functions
  920. %
  921. %-----------------------------------------------------------
  922. symbolic procedure fancy!-prefix!-operator u;
  923. % Print as function, but with a special character.
  924. begin scalar sy;
  925. sy := get(u,'fancy!-functionsymbol) or
  926. get(u,'fancy!-special!-symbol);
  927. if sy then fancy!-special!-symbol sy
  928. else fancy!-prin2 u
  929. end;
  930. put('sqrt,'fancy!-prifn,'fancy!-sqrtpri);
  931. symbolic procedure fancy!-sqrtpri(u);
  932. fancy!-sqrtpri!*(cadr u,2);
  933. symbolic procedure fancy!-sqrtpri!*(u,n);
  934. begin
  935. fancy!-princ "\sqrt";
  936. if n neq 2 then <<
  937. fancy!-princ "[\,";
  938. fancy!-prin2 n;
  939. fancy!-princ "]" >>;
  940. fancy!-maprint!-tex!-bkt(u,0,t);
  941. end;
  942. symbolic procedure fancy!-sub(l,p);
  943. % Prints expression in an exponent notation.
  944. if get('expt,'infix)<=p then
  945. fancy!-in!-brackets {'fancy!-sub,mkquote l,0}
  946. else
  947. begin scalar eqs;
  948. l:=cdr l;
  949. while cdr l do <<eqs:=append(eqs,{car l}); l:=cdr l>>;
  950. l:=car l;
  951. fancy!-maprint(l,get('expt,'infix));
  952. fancy!-princ "|_{";
  953. fancy!-inprint('!*comma!*,0,eqs);
  954. fancy!-princ "}"
  955. end;
  956. put('sub,'fancy!-pprifn,'fancy!-sub);
  957. put('factorial,'fancy!-pprifn,'fancy!-factorial);
  958. symbolic procedure fancy!-factorial(u,n);
  959. begin
  960. if atom cadr u then fancy!-maprint(cadr u,9999)
  961. else fancy!-in!-brackets {'fancy!-maprint,mkquote cadr u,0};
  962. fancy!-princ "!";
  963. end;
  964. put('binomial,'fancy!-prifn,'fancy!-binomial);
  965. symbolic procedure fancy!-binomial u;
  966. begin
  967. fancy!-princ "\left(\begin{matrix}";
  968. fancy!-maprint(cadr u,0);
  969. fancy!-princ "\\";
  970. fancy!-maprint(caddr u,0);
  971. fancy!-princ "\end{matrix}\right)"
  972. end;
  973. symbolic procedure fancy!-intpri(u,p);
  974. if p>get('times,'infix) then
  975. fancy!-in!-brackets {'fancy!-intpri,mkquote u,0}
  976. else
  977. begin
  978. % I bet that the test here is not really wanted for TeXmacs...
  979. if fancy!-height(cadr u,1.0) > 3 then fancy!-princ "\Int "
  980. else fancy!-princ "\int ";
  981. fancy!-maprint(cadr u,0);
  982. fancy!-princ "\,d\,";
  983. fancy!-maprint(caddr u,0)
  984. end;
  985. % It may well be that if TeXmacs does all the layout that this is no longer
  986. % needed.
  987. symbolic procedure fancy!-height(u,h);
  988. % estimate the height of an expression.
  989. if atom u then h
  990. else if car u = 'minus then fancy!-height(cadr u,h)
  991. else if car u = 'plus or car u = 'times then
  992. eval('max. for each w in cdr u collect fancy!-height(w,h))
  993. else if car u = 'expt then
  994. fancy!-height(cadr u,h) + fancy!-height(caddr u,h*0.8)
  995. else if car u = 'quotient then
  996. fancy!-height(cadr u,h) + fancy!-height(caddr u,h)
  997. else if get(car u,'simpfn) then fancy!-height(cadr u,h)
  998. else h;
  999. put('int,'fancy!-pprifn,'fancy!-intpri);
  1000. symbolic procedure fancy!-sumpri!*(u,p,mode);
  1001. if p>get('minus,'infix) then
  1002. fancy!-in!-brackets {'fancy!-sumpri!*,mkquote u,0,mkquote mode}
  1003. else
  1004. begin scalar w,lo,hi,var;
  1005. var := caddr u;
  1006. if cdddr u then lo:=cadddr u;
  1007. if lo and cddddr u then hi := car cddddr u;
  1008. w:=if lo then {'equal,var,lo} else var;
  1009. if mode = 'sum then fancy!-princ "\sum" % big SIGMA
  1010. else if mode = 'prod then fancy!-princ "\prod"; % big PI
  1011. fancy!-princ "_{";
  1012. if w then fancy!-maprint(w,0);
  1013. fancy!-princ "}";
  1014. if hi then <<
  1015. fancy!-princ "^";
  1016. fancy!-maprint!-tex!-bkt(hi,0,nil) >>;
  1017. fancy!-princ "\,";
  1018. fancy!-maprint(cadr u,0)
  1019. end;
  1020. symbolic procedure fancy!-sumpri(u,p); fancy!-sumpri!*(u,p,'sum);
  1021. put('sum,'fancy!-pprifn,'fancy!-sumpri);
  1022. put('infsum,'fancy!-pprifn,'fancy!-sumpri);
  1023. symbolic procedure fancy!-prodpri(u,p); fancy!-sumpri!*(u,p,'prod);
  1024. put('prod,'fancy!-pprifn,'fancy!-prodpri);
  1025. symbolic procedure fancy!-limpri(u,p);
  1026. if p>get('minus,'infix) then
  1027. fancy!-in!-brackets {'fancy!-sumpri,mkquote u,0}
  1028. else
  1029. begin scalar lo,var;
  1030. var := caddr u;
  1031. if cdddr u then lo:=cadddr u;
  1032. fancy!-princ "\lim_{";
  1033. fancy!-maprint(var,0);
  1034. fancy!-princ "\rightarrow";
  1035. fancy!-maprint(lo,0);
  1036. fancy!-princ "}";
  1037. fancy!-maprint(cadr u,0)
  1038. end;
  1039. put('limit,'fancy!-pprifn,'fancy!-limpri);
  1040. symbolic procedure fancy!-listpri(u);
  1041. if null cdr u then fancy!-maprint('empty!-set,0)
  1042. else fancy!-in!-braces
  1043. {'fancy!-inprintlist,mkquote '!*wcomma!*,0,mkquote cdr u};
  1044. put('list,'fancy!-prifn,'fancy!-listpri);
  1045. put('!*sq,'fancy!-reform,'fancy!-sqreform);
  1046. symbolic procedure fancy!-sqreform u;
  1047. prepsq!* sqhorner!* cadr u;
  1048. put('df,'fancy!-pprifn,'fancy!-dfpri);
  1049. % 9-Dec-93: 'total repaired
  1050. symbolic procedure fancy!-dfpri(u,l);
  1051. (if flagp(cadr u,'print!-indexed) or
  1052. pairp cadr u and flagp(caadr u,'print!-indexed)
  1053. then fancy!-dfpriindexed(u,l)
  1054. else if m = 'partial then fancy!-dfpri0(u,l,'partial!-df)
  1055. else if m = 'total then fancy!-dfpri0(u,l,'!d)
  1056. else if m = 'indexed then fancy!-dfpriindexed(u,l)
  1057. else rederr "unknown print mode for DF")
  1058. where m=fancy!-mode fancy_print_df;
  1059. symbolic procedure fancy!-partialdfpri(u,l);
  1060. fancy!-dfpri0(u,l,'partial!-df);
  1061. symbolic procedure fancy!-dfpri0(u,l,symb);
  1062. if null cddr u then fancy!-maprin0 {'times,symb,cadr u}
  1063. else if l >= get('expt,'infix) then % brackets if exponented
  1064. fancy!-in!-brackets {'fancy!-dfpri0,mkquote u,0,mkquote symb}
  1065. else
  1066. begin scalar x,d,q; integer n,m;
  1067. u:=cdr u;
  1068. q:=car u;
  1069. u:=cdr u;
  1070. while u do
  1071. <<x:=car u; u:=cdr u;
  1072. if u and numberp car u then
  1073. <<m:=car u; u := cdr u>> else m:=1;
  1074. n:=n+m;
  1075. d:= append(d,{symb,if m=1 then x else {'expt,x,m}});
  1076. >>;
  1077. fancy!-maprin0
  1078. {'quotient, {'times,
  1079. if n=1 then symb else {'expt,symb,n},q},
  1080. 'times . d};
  1081. end;
  1082. symbolic procedure fancy!-dfpriindexed(u,l);
  1083. if null cddr u then fancy!-maprin0{'times,'partial!-df,cadr u} else
  1084. begin
  1085. fancy!-maprin0 cadr u;
  1086. fancy!-print!-indexlist fancy!-dfpriindexedx(cddr u,nil)
  1087. end;
  1088. symbolic procedure fancy!-dfpriindexedx(u,p);
  1089. if null u then nil else
  1090. if numberp car u then
  1091. append(for i:=2:car u collect p,fancy!-dfpriindexedx(cdr u,p))
  1092. else car u . fancy!-dfpriindexedx(cdr u,car u);
  1093. put('!:rd!:,'fancy!-prifn,'fancy!-rdprin);
  1094. symbolic procedure fancy!-rdprin u;
  1095. begin scalar digits; integer dotpos,xp;
  1096. u:=rd!:explode u;
  1097. digits := car u; xp := cadr u; dotpos := caddr u;
  1098. return fancy!-rdprin1(digits,xp,dotpos);
  1099. end;
  1100. symbolic procedure fancy!-rdprin1(digits,xp,dotpos);
  1101. begin scalar str;
  1102. if xp>0 and dotpos+xp<length digits-1 then <<
  1103. dotpos := dotpos+xp;
  1104. xp:=0 >>;
  1105. % build character string from number.
  1106. for i:=1:dotpos do <<
  1107. str := car digits . str;
  1108. digits := cdr digits;
  1109. if null digits then digits:='(!0) >>;
  1110. str := '!. . str;
  1111. for each c in digits do str :=c.str;
  1112. if not (xp=0) then <<
  1113. str:='!e . str;
  1114. for each c in explode2 xp do str:=c.str >>;
  1115. fancy!-prin2number1 reversip str
  1116. end;
  1117. put('!:cr!:,'fancy!-pprifn,'fancy!-cmpxprin);
  1118. put('!:cr!:,'fancy!-pprifn,'fancy!-cmpxprin);
  1119. symbolic procedure fancy!-cmpxprin(u,l);
  1120. begin scalar rp,ip;
  1121. rp:=reval {'repart,u}; ip:=reval {'impart,u};
  1122. return fancy!-maprint(
  1123. if ip=0 then rp else
  1124. if rp=0 then {'times,ip,'!i} else
  1125. {'plus,rp,{'times,ip,'!i}},l);
  1126. end;
  1127. symbolic procedure fancy!-dn!:prin u;
  1128. begin scalar lst; integer dotpos,ex;
  1129. lst := bfexplode0x (cadr u, cddr u);
  1130. ex := cadr lst;
  1131. dotpos := caddr lst;
  1132. lst := car lst;
  1133. return fancy!-rdprin1 (lst,ex,dotpos)
  1134. end;
  1135. put ('!:dn!:, 'fancy!-prifn, 'fancy!-dn!:prin);
  1136. fmp!-switch t;
  1137. endmodule;
  1138. %-------------------------------------------------------
  1139. module fancy_matrix; % Matrix printing routines.
  1140. fluid '(obrkp!*);
  1141. symbolic procedure fancy!-setmatpri(u,v);
  1142. fancy!-matpri1(cdr v,u);
  1143. put('mat,'fancy!-setprifn,'fancy!-setmatpri);
  1144. symbolic procedure fancy!-matpri u;
  1145. fancy!-matpri1(cdr u,nil);
  1146. put('mat,'fancy!-prifn,'fancy!-matpri);
  1147. symbolic procedure fancy!-matpri1(u,x);
  1148. % Prints a matrix canonical form U with name X.
  1149. fancy!-matpri2(u,x,nil);
  1150. symbolic procedure fancy!-matpri2(u,x,bkt);
  1151. % Tries to print matrix as compact block.
  1152. % The specfn code uses bkt="{}" rathen than the usual default of "()".
  1153. begin scalar fl,fmat,row,elt;
  1154. integer cols,rows,maxpos;
  1155. rows := length u;
  1156. cols := length car u;
  1157. if x then <<
  1158. fancy!-maprint(x,0);
  1159. % I think I might use princ on the next line, but the current code renders
  1160. % ":=" within \mathrm... ???
  1161. fancy!-prin2 ":=" >>;
  1162. fl := fancy!-line!*;
  1163. fmat := for each row in u collect
  1164. for each elt in row collect <<
  1165. fancy!-line!*:=nil;
  1166. fancy!-maprint(elt,0);
  1167. fancy!-line!* >>;
  1168. fancy!-line!* := fl;
  1169. % TEX header
  1170. fancy!-princ bldmsg("\left%w\begin{matrix}",
  1171. if bkt then car bkt else "(");
  1172. % join elements.
  1173. while fmat do
  1174. <<row := car fmat; fmat:=cdr fmat;
  1175. while row do
  1176. <<elt:=car row; row:=cdr row;
  1177. fancy!-line!* := append(elt,fancy!-line!*);
  1178. if row then fancy!-line!* :='!& . fancy!-line!*
  1179. else if fmat then
  1180. fancy!-line!* := "\\". fancy!-line!* >> >>;
  1181. fancy!-princ bldmsg("\end{matrix}\right%w",
  1182. if bkt then cdr bkt else ")")
  1183. end;
  1184. put('taylor!*,'fancy!-reform,'Taylor!*print1);
  1185. endmodule;
  1186. module fancy_specfn;
  1187. put('sin,'fancy!-prifn,'fancy!-sin);
  1188. put('cos,'fancy!-prifn,'fancy!-cos);
  1189. put('tan,'fancy!-prifn,'fancy!-tan);
  1190. put('cot,'fancy!-prifn,'fancy!-cot);
  1191. put('sec,'fancy!-prifn,'fancy!-sec);
  1192. put('csc,'fancy!-prifn,'fancy!-csc);
  1193. put('asin,'fancy!-prifn,'fancy!-asin);
  1194. put('acos,'fancy!-prifn,'fancy!-acos);
  1195. put('atan,'fancy!-prifn,'fancy!-atan);
  1196. put('sinh,'fancy!-prifn,'fancy!-sinh);
  1197. put('cosh,'fancy!-prifn,'fancy!-cosh);
  1198. put('tanh,'fancy!-prifn,'fancy!-tanh);
  1199. put('coth,'fancy!-prifn,'fancy!-coth);
  1200. put('exp,'fancy!-prifn,'fancy!-exp);
  1201. put('log,'fancy!-prifn,'fancy!-log);
  1202. put('ln,'fancy!-prifn,'fancy!-ln);
  1203. put('max,'fancy!-prifn,'fancy!-max);
  1204. put('min,'fancy!-prifn,'fancy!-min);
  1205. %put('repart,'fancy!-prifn,'fancy!-repart);
  1206. %put('impart,'fancy!-prifn,'fancy!-impart);
  1207. symbolic procedure fancy!-sin(u);
  1208. begin
  1209. fancy!-princ "\sin";
  1210. fancy!-print!-function!-arguments cdr u;
  1211. end;
  1212. symbolic procedure fancy!-cos(u);
  1213. begin
  1214. fancy!-princ "\cos";
  1215. fancy!-print!-function!-arguments cdr u;
  1216. end;
  1217. symbolic procedure fancy!-tan(u);
  1218. begin
  1219. fancy!-princ "\tan";
  1220. fancy!-print!-function!-arguments cdr u;
  1221. end;
  1222. symbolic procedure fancy!-cot(u);
  1223. begin
  1224. fancy!-princ "\cot";
  1225. fancy!-print!-function!-arguments cdr u;
  1226. end;
  1227. symbolic procedure fancy!-sec(u);
  1228. begin
  1229. fancy!-princ "\sec";
  1230. fancy!-print!-function!-arguments cdr u;
  1231. end;
  1232. symbolic procedure fancy!-csc(u);
  1233. begin
  1234. fancy!-princ "\csc";
  1235. fancy!-print!-function!-arguments cdr u;
  1236. end;
  1237. symbolic procedure fancy!-asin(u);
  1238. begin
  1239. fancy!-princ "\arcsin";
  1240. fancy!-print!-function!-arguments cdr u;
  1241. end;
  1242. symbolic procedure fancy!-acos(u);
  1243. begin
  1244. fancy!-princ "\arccos";
  1245. fancy!-print!-function!-arguments cdr u;
  1246. end;
  1247. symbolic procedure fancy!-atan(u);
  1248. begin
  1249. fancy!-princ "\arctan";
  1250. fancy!-print!-function!-arguments cdr u;
  1251. end;
  1252. symbolic procedure fancy!-sinh(u);
  1253. begin
  1254. fancy!-princ "\sinh";
  1255. fancy!-print!-function!-arguments cdr u;
  1256. end;
  1257. symbolic procedure fancy!-cosh(u);
  1258. begin
  1259. fancy!-princ "\cosh";
  1260. fancy!-print!-function!-arguments cdr u;
  1261. end;
  1262. symbolic procedure fancy!-tanh(u);
  1263. begin
  1264. fancy!-princ "\tanh";
  1265. fancy!-print!-function!-arguments cdr u;
  1266. end;
  1267. symbolic procedure fancy!-coth(u);
  1268. begin
  1269. fancy!-princ "\coth";
  1270. fancy!-print!-function!-arguments cdr u;
  1271. end;
  1272. symbolic procedure fancy!-exp(u);
  1273. begin
  1274. fancy!-princ "\exp";
  1275. fancy!-print!-function!-arguments cdr u;
  1276. end;
  1277. symbolic procedure fancy!-log(u);
  1278. begin
  1279. fancy!-princ "\log";
  1280. fancy!-print!-function!-arguments cdr u;
  1281. end;
  1282. symbolic procedure fancy!-ln(u);
  1283. begin
  1284. fancy!-princ "\ln";
  1285. fancy!-print!-function!-arguments cdr u;
  1286. end;
  1287. symbolic procedure fancy!-max(u);
  1288. begin
  1289. fancy!-princ "\max";
  1290. fancy!-print!-function!-arguments cdr u;
  1291. end;
  1292. symbolic procedure fancy!-min(u);
  1293. begin
  1294. fancy!-princ "\min";
  1295. fancy!-print!-function!-arguments cdr u;
  1296. end;
  1297. symbolic procedure fancy!-repart(u);
  1298. begin
  1299. fancy!-princ "\Re";
  1300. fancy!-print!-function!-arguments cdr u;
  1301. end;
  1302. symbolic procedure fancy!-impart(u);
  1303. begin
  1304. fancy!-princ "\Im";
  1305. fancy!-print!-function!-arguments cdr u;
  1306. end;
  1307. put('besseli,'fancy!-prifn,'fancy!-bessel);
  1308. put('besselj,'fancy!-prifn,'fancy!-bessel);
  1309. put('bessely,'fancy!-prifn,'fancy!-bessel);
  1310. put('besselk,'fancy!-prifn,'fancy!-bessel);
  1311. % NB here are some places where ASCII codes are used...
  1312. put('besseli,'fancy!-functionsymbol,'(ascii 73));
  1313. put('besselj,'fancy!-functionsymbol,'(ascii 74));
  1314. put('bessely,'fancy!-functionsymbol,'(ascii 89));
  1315. put('besselk,'fancy!-functionsymbol,'(ascii 75));
  1316. symbolic procedure fancy!-bessel(u);
  1317. begin
  1318. fancy!-prefix!-operator car u;
  1319. fancy!-print!-one!-index cadr u;
  1320. fancy!-print!-function!-arguments cddr u
  1321. end;
  1322. % Hypergeometric functions.
  1323. put('hypergeometric,'fancy!-prifn,'fancy!-hypergeometric);
  1324. symbolic procedure fancy!-hypergeometric u;
  1325. begin scalar a1,a2,a3;
  1326. a1 :=cdr cadr u;
  1327. a2 := cdr caddr u;
  1328. a3 := cadddr u;
  1329. fancy!-princ "{}";
  1330. fancy!-print!-one!-index length a1;
  1331. fancy!-princ "F";
  1332. fancy!-print!-one!-index length a2;
  1333. fancy!-princ "\left(\left.";
  1334. fancy!-print!-indexlist1(a1,"^",'!*comma!*);
  1335. fancy!-print!-indexlist1(a2,"_",'!*comma!*);
  1336. fancy!-princ "\,\right|\,";
  1337. fancy!-maprin(a3,0);
  1338. fancy!-princ "\right)"
  1339. end;
  1340. % hypergeometric({1,2,u/w,v},{5,6},sqrt x);
  1341. put('meijerg,'fancy!-prifn,'fancy!-meijerG);
  1342. symbolic procedure fancy!-meijerG u;
  1343. begin scalar a1,a2,a3;
  1344. integer n,m,p,q;
  1345. a1 :=cdr cadr u;
  1346. a2 := cdr caddr u;
  1347. a3 := cadddr u;
  1348. m:=length cdar a2;
  1349. n:=length cdar a1;
  1350. a1 := append(cdar a1 , cdr a1);
  1351. a2 := append(cdar a2 , cdr a2);
  1352. p:=length a1; q:=length a2;
  1353. fancy!-princ "G";
  1354. fancy!-print!-indexlist1({m,n},"^",nil);
  1355. fancy!-print!-indexlist1({p,q},"_",nil);
  1356. fancy!-princ "\left(";
  1357. fancy!-maprin(a3,0);
  1358. fancy!-princ "\left|";
  1359. fancy!-print!-indexlist1(a1,"^",'!*comma!*);
  1360. fancy!-print!-indexlist1(a2,"_",'!*comma!*);
  1361. fancy!-princ "\right.\right)"
  1362. end;
  1363. % meijerg({{},1},{{0}},x);
  1364. % Now a few things that can be useful for testing this code...
  1365. algebraic operator texsym, texbox, texfbox, texstring;
  1366. % texsym(!Longleftarrow) should generate \Longleftarrow (etc). This
  1367. % might plausibly be useful while checking that the interface can render
  1368. % all TeX built-in keywords properly. Furthermore I allow extra args, so
  1369. % that eg texsym(stackrel,f,texsym(longrightarrow)) turns into
  1370. % \stackrel{f}{\longrightarrow}
  1371. put('texsym,'fancy!-prifn,'fancy!-texsym);
  1372. symbolic procedure fancy!-texsym u;
  1373. begin
  1374. if null u then return;
  1375. fancy!-princ list!-to!-string ('!\ . explode2 cadr u);
  1376. u := cddr u;
  1377. while u do <<
  1378. fancy!-line!* := "{" . fancy!-line!*;
  1379. fancy!-maprint(car u, 0);
  1380. fancy!-line!* := "}" . fancy!-line!*;
  1381. u := cdr u >>
  1382. end;
  1383. % texstring("arbitrary tex stuff",...)
  1384. % where atoms (eg strings and words) are just passed to tex but
  1385. % more complicated items go through fancy!-maprint.
  1386. put('texstring,'fancy!-prifn,'fancy!-texstring);
  1387. symbolic procedure fancy!-texstring u;
  1388. for each s in cdr u do <<
  1389. if not atom s then fancy!-maprint(s, 0)
  1390. else <<
  1391. if not stringp s then s := list!-to!-string explode2 s;
  1392. fancy!-line!* := s . fancy!-line!* >> >>;
  1393. % texbox(h) is a box of given height (in points)
  1394. % texbox(h, d) is a box of given height and depth
  1395. % height is amount above the reference line, depth is amount
  1396. % below.
  1397. % textbox(h, d, c) is a box of given size with some specified content
  1398. % All these draw a frame around the space used so you can see what is
  1399. % goin on.
  1400. % The idea that this may be useful when checking how layouts cope with
  1401. % various sizes of content, eg big delimiters, square root signs etc. So I
  1402. % can test with "for i := 10:40 do write sqrt(texbox(i))" etc.
  1403. % to test sqrt with arguments of height 10, 11, ... to 40 points. Note that
  1404. % certainly with the CSL version the concept of a "point" is a bit vauge!
  1405. % However if I were to imagine that my screen was at 75 pixels per inch I
  1406. % could with SOME reason interpret point as meaning pixel, and that is
  1407. % what I will do. At present what I might do about hard-copy output is
  1408. % pretty uncertain. If height and depth are given as 0 and there is a
  1409. % content them the content will define the box size.
  1410. put('texbox,'fancy!-prifn,'fancy!-texbox);
  1411. symbolic procedure fancy!-texbox u;
  1412. begin
  1413. scalar height, depth, contents;
  1414. contents := nil;
  1415. u := cdr u;
  1416. height := car u;
  1417. u := cdr u;
  1418. if u then <<
  1419. depth := car u;
  1420. u := cdr u;
  1421. if u then contents := car u >>;
  1422. if not numberp height then height:=0;
  1423. if not numberp depth then depth:=0;
  1424. if height=0 and depth=0 and null content then height:=10;
  1425. fancy!-princ "\fbox{";
  1426. if height neq 0 or depth neq 0 then << % insert a rule
  1427. fancy!-line!* := "\rule" . fancy!-line!*;
  1428. if depth neq 0 then <<
  1429. fancy!-line!* := "[-" . fancy!-line!*;
  1430. fancy!-line!* := depth . fancy!-line!*;
  1431. fancy!-line!* := "pt]" . fancy!-line!* >>;
  1432. fancy!-line!* := "{0pt}{" . fancy!-line!*;
  1433. fancy!-line!* := (height+depth) . fancy!-line!*;
  1434. fancy!-line!* := "pt}" . fancy!-line!* >>;
  1435. if contents then fancy!-maprint(contents, 0)
  1436. else fancy!-line!* := "\rule{10pt}{0pt}" . fancy!-line!*;
  1437. fancy!-princ "}"
  1438. end;
  1439. % texfbox is a simplified version of texbox, and just draws a box around the
  1440. % expression it is given.
  1441. put('texfbox,'fancy!-prifn,'fancy!-texfbox);
  1442. symbolic procedure fancy!-texfbox u;
  1443. begin
  1444. fancy!-princ "\fbox{";
  1445. fancy!-maprint(cadr u, 0);
  1446. fancy!-princ "}"
  1447. end;
  1448. endmodule;
  1449. module promptcolor;
  1450. % Adapted from Prompt coloring for redfront.
  1451. fluid '(lispsystem!*);
  1452. fluid '(promptstring!* tm_switches!* tm_switches!-this!-sl!* lessspace!*);
  1453. fluid '(!*promptnumbers);
  1454. switch promptnumbers;
  1455. !#if (member 'csl lispsystem!*)
  1456. % With CSL I want tmprint loaded all the time and so making this decision
  1457. % when texmacs is LOADED is not useful.
  1458. procedure texmacsp;
  1459. % Texmacs predicate. Returns [t] iff Texmacs is running.
  1460. if getenv("TEXMACS_REDUCE_PATH") then t;
  1461. if texmacsp () then % We don't want prompt numbers in a Texmacs worksheet
  1462. off1 'promptnumbers
  1463. else
  1464. on1 'promptnumbers;
  1465. !#endif
  1466. tm_switches!* := {!*msg,!*output};
  1467. off1 'msg;
  1468. off1 'output;
  1469. procedure tm_bprompt();
  1470. % Begin of prompt.
  1471. {int2id 2,'c,'h,'a,'n,'n,'e,'l,'!:,'p,'r,'o,'m,'p,'t,int2id 5,
  1472. int2id 2,'l,'a,'t,'e,'x,'!:,'!\,'b,'r,'o,'w,'n,'! ,
  1473. '!R,'e,'d,'u,'c,'e};
  1474. procedure tm_eprompt();
  1475. % End of prompt
  1476. {'!\ ,int2id 5};
  1477. % This always gets a list of the characters that make up the prompt...
  1478. procedure tm_coloredp(ec);
  1479. eqcar(ec, car tm_bprompt());
  1480. procedure tm_nconcn(l);
  1481. % Taken from rltools.
  1482. if cdr l then nconc(car l,tm_nconcn cdr l) else car l;
  1483. symbolic procedure tm_prunelhead(l, l1);
  1484. if null l or null l1 then l else tm_prunelhead(cdr l, cdr l1);
  1485. procedure tm_pruneltail(l,l1);
  1486. reversip tm_prunelhead(reversip l,l1);
  1487. procedure tm_pslp();
  1488. 'psl memq lispsystem!*;
  1489. if tm_pslp() then <<
  1490. tm_switches!-this!-sl!* := {!*usermode};
  1491. off1 'usermode
  1492. >>;
  1493. procedure tm_color(c);
  1494. % Color prompt. This will handle EITHER an identifier OR a string, and
  1495. % it returns the same sort of object. It wraps tm_bprompt() and
  1496. % tm_eprompt() around the text it is passed.
  1497. begin scalar ec, sf;
  1498. if stringp c then <<
  1499. ec := string!-to!-list c;
  1500. sf := t >>
  1501. else ec := explode2 c; % Original code has explode not explode2 here.
  1502. ec := '! . ec; % add space
  1503. if not !*promptnumbers then % strip numbers from prompt
  1504. while memq(car ec,'(! !0 !1 !2 !3 !4 !5 !6 !7 !8 !9)) do
  1505. ec := cdr ec;
  1506. ec := append(tm_bprompt(), append(ec, tm_eprompt()));
  1507. ec := list!-to!-string ec;
  1508. if sf then return ec
  1509. else return intern ec
  1510. end;
  1511. procedure tm_uncolor(c);
  1512. % Uncolor prompt.
  1513. begin scalar ec, sf;
  1514. if stringp c then <<
  1515. ec := string!-to!-list c;
  1516. sf := t >>
  1517. else ec := explode2 c; % cf explode?
  1518. if not tm_coloredp ec then return c;
  1519. ec := tm_prunelhead(ec, tm_bprompt());
  1520. if car ec eq '! then ec := cdr ec; % strip space
  1521. ec := tm_pruneltail(ec, tm_eprompt());
  1522. ec := list!-to!-string ec;
  1523. if sf then return ec
  1524. else return intern ec
  1525. end;
  1526. procedure tm_setpchar!-psl(c);
  1527. begin scalar w;
  1528. w := tm_setpchar!-orig c;
  1529. promptstring!* := tm_color promptstring!*;
  1530. return tm_uncolor w
  1531. end;
  1532. !#if (memq 'csl lispsystem!*)
  1533. switch redfront_mode;
  1534. % I do not think there is any merit in even defining this if I am not
  1535. % using CSL.
  1536. procedure tm_setpchar!-csl(c);
  1537. % With CSL in many cases the system does prompt colouring at a lower level
  1538. % in the code, so the stuff here is not necessary. However if CSL is used
  1539. % with an external redfront of texmacs interface I will want to activate
  1540. % this special stuff. So I provide a switch redfront_mode that controls
  1541. % what I do. I expect to run with this module loaded almost all of the time
  1542. % which is why I want a control via switch rather than through just
  1543. % "load tmprint". I note that if CSL is loaded from a script that attaches it
  1544. % to redfront of som eother interface that the invocation can use
  1545. % -D*redfront_mode
  1546. % to preset the switch, which ought to be a small enough burden to be
  1547. % tolerable!
  1548. if !*redfront_mode or
  1549. member('texmacs, lispsystem!*) then
  1550. tm_uncolor tm_setpchar!-orig tm_color c
  1551. else tm_setpchar!-orig c;
  1552. !#endif
  1553. % In due course I rather hope to be able to avoid uses of copyd and the
  1554. % style of function redefinition (in terms of its oiriginal version) used
  1555. % here.
  1556. copyd('tm_setpchar!-orig,'setpchar);
  1557. if tm_pslp() then
  1558. copyd('setpchar,'tm_setpchar!-psl)
  1559. else
  1560. copyd('setpchar,'tm_setpchar!-csl);
  1561. procedure tm_yesp!-psl(u);
  1562. begin scalar ifl,ofl,x,y;
  1563. if ifl!* then <<
  1564. ifl := ifl!* := {car ifl!*,cadr ifl!*,curline!*};
  1565. rds nil >>;
  1566. if ofl!* then <<
  1567. ofl:= ofl!*;
  1568. wrs nil >>;
  1569. if null !*lessspace then terpri();
  1570. if atom u then prin2 u
  1571. else lpri u;
  1572. if null !*lessspace then terpri();
  1573. y := setpchar "?";
  1574. x := yesp1();
  1575. setpchar y;
  1576. if ofl then wrs cdr ofl;
  1577. if ifl then rds cadr ifl;
  1578. cursym!* := '!*semicol!*;
  1579. return x
  1580. end;
  1581. if tm_pslp() then <<
  1582. remflag('(yesp),'lose);
  1583. copyd('tm_yesp!-orig,'yesp);
  1584. copyd('yesp,'tm_yesp!-psl);
  1585. flag('(yesp),'lose) >>;
  1586. % Color PSL prompts, in case user falls through:
  1587. procedure tm_compute!-prompt!-string(count,level);
  1588. tm_color tm_compute!-prompt!-string!-orig(count,level);
  1589. if tm_pslp() then <<
  1590. copyd('tm_compute!-prompt!-string!-orig,'compute!-prompt!-string);
  1591. copyd('compute!-prompt!-string,'tm_compute!-prompt!-string) >>;
  1592. procedure tm_break_prompt();
  1593. <<
  1594. prin2 "break["; prin2 breaklevel!*; prin2 "]";
  1595. promptstring!* := tm_color promptstring!*
  1596. >>;
  1597. if tm_pslp() then <<
  1598. remflag('(break_prompt),'lose);
  1599. copyd('break_prompt,'tm_break_prompt);
  1600. flag('(break_prompt),'lose) >>;
  1601. if tm_pslp() then
  1602. onoff('usermode,car tm_switches!-this!-sl!*);
  1603. onoff('msg,car tm_switches!*);
  1604. onoff('output,cadr tm_switches!*);
  1605. crbuf!* := nil;
  1606. inputbuflis!* := nil;
  1607. lessspace!* := t;
  1608. statcounter := 0;
  1609. endmodule;
  1610. end;