acnprint.red 53 KB

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