1.red 60 KB

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