summaryrefslogtreecommitdiff
path: root/support/lametex/doc/hacks.tex
blob: 596124a97be52ca8c2294811d42723146a8eeb87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
% hacks.tex
%
% \begin{stealth}
% \pspage{page_kludge.ps}
% \setlength{\textwidth}{8.1 in}
% \setlength{\oddsidemargin}{-.8 in}
% \end{stealth}

\chapter{Including Your Own PostScript Hacks}

Let's face it. This manual is nice, but let's get into the nitty
gritty of the examples presented here and maybe I can show you how to
do some cool stuff with LameTeX. If you have questions, we can chat in
person over mail. Here goes.

\section{How to Use Include Files To Do Stuff}
This manual can be formatted by running either LaTeX or LameTeX on the
file {\tt lametex\_doc.tex}. There are a lot of other files, but {\tt
lametex\_doc.tex} includes them using the LaTeX command
$\backslash$include.

While reading this section on examples, you will probably want to run
LameTeX over just one chapter, not all of them. If you edit the file
{\tt lametex\_doc.tex} you can ``comment out'' everything you don't
want. For example, if you wanted to run LameTeX over the chapter on
pages, you could edit the file so that it looked like:

$\backslash$documentstyle[10pt]\{report\} \\
$\backslash$setlength\{$\backslash$textwidth\}\{6 in\} \\
$\backslash$setlength\{$\backslash$textheight\}\{9 in\} \\
$\backslash$setlength\{$\backslash$topmargin\}\{0 in\} \\
$\backslash$setlength\{$\backslash$oddsidemargin\}\{0.25 in\} \\

\% $\backslash$begin\{stealth\} $\backslash$includeps\{icons.ps\}
$\backslash$end\{stealth\} \\
$\backslash$begin\{document\} \\
\% $\backslash$include\{titlepage\} \\
\% $\backslash$include\{introduction\} \\
\% $\backslash$include\{starting\} \\
\% $\backslash$include\{stealth\}  \\
$\backslash$include\{pages\} \\
\% $\backslash$include\{normality\} \\
\% $\backslash$include\{hacks\} \\
\% $\backslash$include\{future\} \\
\% $\backslash$include\{errors\} \\
\% $\backslash$include\{commands\} \\
$\backslash$end\{document\} \\

Notice how all the chapters, except for pages.tex, have been placed in
comments using the '\%' character. This means that both LaTeX and
LameTeX will ignore them.

\section{White Text Hack}

Look in titlepage.tex, just before where it says ``Copyright 1992''.
Here is a demonstration of changing the color of the text so that it
is white instead of black. This is done using the special LameTeX
stealth commands $\backslash$stealth and $\backslash$postscript.

All the stealth commands are located inside comments so that the
normal LaTeX won't see them. So I have to start a stealth environment,
because without that none of the other commands I type inside the
comments will be interpreted.

Then I start a postscript environment. From that point on, everything
in the file gets dumped directly to the postscript output. So ``1
setgray'' gets included directly in the PostScript output file. This
is the PostScript command to paint things white, not black.

Naturally after the one line has been painted white, I must put the
default color back to black or else my whole document will be in
white! The $\backslash$stealth and $\backslash$postscript environments
are special because they don't as scope delimiters for internal
changes.

So if you did a boldface in a Huge environment you'd expect that when
the Huge environment ended, that the boldface would go away. The
``scope'' of boldface was limited to the Huge environment.
$\backslash$stealth and $\backslash$postscript don't limit scope like
that.

Here's a trick to try out. Try placing the words ``Copyright 1992''
before the ``1 setgray'' line and the words ``Jonathan Monsarrat''
afterwards. What happens? Does ``Copyright 1992'' come out in white or
black?

The answer is that is comes out in white, and if you refer to the
Page chapter I can show you why. LameTeX is trying to center this line
on the page. To do that it needs to know how long this line is. So
instead of printing out the words one at a time, LameTeX stores the
words in a big list, and then prints them at the end once the line has
been completed. LameTeX always does this.

So in the modified version I asked you to make, first a procedure to
get the correct font is put on the word list. Then ``Copyright'' is
added to the word list. Then ``1992'' is added. So far, nothing has
been printed. Then the ``1 setgray'' gets executed. Then ``Jonathan''
and ``Monsarrat'' get added to the word list. Finally we reach the end
of the line, and when the whole line prints out, all four words are in
white because of the ``1 setgray'' command.

The word list, as well as having words and
commands on it, can also have numbers. A number on a word list means
to move over an amount horizontaly. The $\backslash$hspace command and
others add in horizontal whitespace in this way.

\section{The Dagger Hack}

LameTeX is written for PostScript version 1 because I wanted it to
work on all PostScript printers. I love PostScript but it was very
awkward to work with. For one thing, PostScript 1 doesn't have very
good memory management tools. If you're not careful, even a simple
hack like piping a thousand words through a small program and printing
them will take up a lot of memory, because each word is stored in a
string, and that string is never deleted, not even when the string is
printed and cannot be accessed.

Fortunately, there is a workaround. LameTeX uses the PostScript
commands {\tt save} and {\tt restore} to do memory cleanup. If it
didn't, it would use up so much memory that your document could not
print out if it were long.  The {\tt save} command takes a snapshot of
the current state of computer (or printer) memory and the {\tt
restore} command erases the current state and returns the computer (or
printer) to exactly the state it was in whe the last {\tt save}
command was executed.

This happens at the beginning and end of each page, as mentioned in
the chapter on Pages.

Now here's an interesting question for you. I have this immense
picture of a dagger that I want to include in my PostScript page. I
want text to flow around the dagger. What should I do?

Look in {\tt stealth.tex} and {\tt page\_dagger.ps} to find the
answer. If I were to place the huge Dagger routine outside of a
save-restore block, then it would hang around in memory forever, even
if I didn't intend to use that particular picture any more in my
document. This would be unclean. What I really want to do is to insert
the Dagger picture, including the definition - because the definition
takes up a lot of room too as well as variables - inside the StartPage
routine.

The StartPage routine gets called after the save and before the
restore. So whatever garbage I throw into memory drawing the dagger
will neatly get erased at the end of the page.

Also there is the matter of the path defined in PageShape. The dagger
itself is some 200 lines of curveto commands! This is way too much
curviness and way too detailed for something as macroscopic as placing
text. So I have drawn an irregular polygon around the dagger. The
polygon works just as well for the simple blocky task of placing text
around the dagger. Plus it is a lot simpler because it is made
entirely of straight lines.

You can view this path by uncommenting the line where it says
``Uncomment me'' in {\tt page\_dagger.ps}.

Actually the description of the dagger itself gets thrown into
the In-Between Page space that is not cleaned up, because the
StartPage routine is defined along with the page itself in the
In-Between Page space.

One way to get around this I have implemented for {\tt
page\_demon.ps}. That is to have the page description just contain a
small bounding box, just like the description for the dagger. The
actual drawing of the fancy demon I include in normality.tex, once on
each of the three pages. Why would I include the file three times?
Doesn't that make my PostScript file bigger?

Yes, that is certainly true. But the demon hack is immense, some 25K
of raw PostScript code. I really don't want to define a PostScript
routine to draw all of that. If I use the include function, the
routines that draw the get demon are executed without ever being
saved. So it's OK to have a very big PostScript file as long as the
file is a long stream of commands. You start getting into trouble when
you define procedures with long streams of commands.

Unfortunately, this does indeed mean that I have to ``guess'' where to
place the $\backslash$include{demon.ps} command, once for each of the
three pages.

\section{The Titlebar Hack}

The best thing about LameTeX is that if you want to do some pretty
radical stuff, LameTeX says ``OK! Let's go for it!'', whereas TeX and
LaTeX would probably say ``B-B-But, why would you want to do that?
That wouldn't be... (trumpet flare) {\em professional!}''

Here's a great example. On the title page there are two big hacks, 
/Weird-Stuff and /Title. Both of these PostScript programs take a
string off of the stack and display it in an unusual way.

Using these two programs is as simple as starting a stealth
environment, starting a postscript environment, and then just
inserting the commands!

NOTE: Notice how the LameTeX title has holes in it! An omen? A sign of
portent about the program itself?

Also note that of course I put all of the major graphics coding into
the StartPage routine, including the definitions, so that when they
are no longer needed these definitions will be erased. The definitions
persist between the save and restore, and since all the printed text
on the page comes between the save and restore, I can still call these
routines from the LameTeX document as long as I do it before the
restore command associated with the EndPage.

\section{Page Number Hack}
This hack is the logical opposite of the dagger hack. With the dagger
hack, I wanted to stuff a lot of PostScript code into the /StartPage
routine, get it to draw some stuff, and then destroy it.

With the page number, I want the page number to be preserved across
pages. It would be a crime if I changed page number 2 to 3, and then
when the restore command came along it reverted back to 2! So instead
of placing this code in /StartPage, it goes in /EndPage instead.

The /EndPage routine gets called {\em after} the restore from the
previous page and {\em before} the save from the next page. It's
in-between pages, and any variables changed here, like pagenumber,
will remain around. Also the InitPage routine gets called before the
first save is done for the page, so it is in-between pages also.

Here's another quirk to inbetween-pages. When you're on a page, a
special dictionary is used called formatdict. A dictionary is just a
place to store variables in PostScript. These variables are accessed
directly like normal variables when you're on a page. But in-between,
you need a special way to get at the variables. One exception:
InitPage does have access to the variables directly, which is how it
sets formatdict variables like BM and evenodd without using dictionaries.

For example, if I want the bottommargin, I can't just say
``bottommargin'' to put the bottommargin onto the stack. I have to say
``formatdict /bottommargin get'', which does the same thing. If you
are a PostScript expert, you'll know what I say when I note that I do
this to keep plenty of room open in the generic user dictionary.

\section{The Format Dictionary}

The most important variables in the format dictionary are:

\begin{description}

\item[baselineskip] The number of lines to skip between lines.

\item[bottommargin] The margin at the bottom of the page.  The LaTeX
words textheight and textwidth don't mean anything to LameTeX. They
get translated into left, right, top, and bottom margins on the
assumption that the textheight and textwidth commands apply to a
normal-sized 8.5x11 inch paper.

\item[bslot] The X coordinate of the left hand side of the current line.

\item[coords] A very complex representation of the page path.

\item[eslot] The X coordinate of the right hand side of the current line.

\item[justify] An integer, can be 102 (or 'f') for full justify, 99
(or 'c') for centered, 114 (or 'r') for flush right, or 108 (or 'l')
for flush left.

\item[leftmargin] The margin at the left hand side of the page. There
is no distinction between evensidemargin and oddsidemargin.

\item[newfontcmd] The command of the ``currently used font'', which
doesn't really have to be a font command at all.

\item[para] Whether the end of this line will mark a new paragraph.

\item[parindent] The amount of indentation for the first line of each
paragraph.

\item[parskip] The amount of vertical space to skip in-between paragraphs.

\item[rightmargin] The margin at the right hand side of the page.
The LaTeX words textheight and textwidth don't mean anything to
LameTeX. They get translated into left, right, top, and bottom margins
on the assumption that the textheight and textwidth commands apply to
a normal-sized 8.5x11 inch paper.

\item[savetype] The currently saved state, saved by the save command.

\item[topmargin] The margin at the top of the page.

\item[vspace] The amount of vertical space to skip for the next paragraph.

\item[welem] The number of elements in the word list.

\item[wlen] The total length of all the words in the word list,
including a single space between each word.

\item[wlist] The word list itself. Feel free to mess around with it.
Please make sure to set ``welem'', ``wlen'', and ``woids'' to
appropriate values or it'll break! The correct way to add stuff to
wlist is put doing an indexed get and put into the array. The maximum
length of wlist is 100 elements. It's defined at the top of format.ps
if you want to change it.

\item[woids] The number of elements in the word list that are actually words.

\item[xpos] The current X position.

\item[ypos] The current Y position of this line.

\end{description}

\section{The Icon Hack}

Notice how each page description has a different definition for
LeftMarginIcon. This is because each page is a little different and
"where to put icons in the left margin" varies a little.

So putting the little Wizard in the text is as simple as starting a
stealth environment, starting a postscript environment, and called the
/LeftMarginIcon routine to display the Wizard.

Notice that the LeftMarginIcon uses one (or two) formatdict variables:
ypos (and maybe bpos). Because the LeftMarginIcon routine is being
called from inside the page, there is no need to do a fancy dictionary
lookupt to get their values.

\section{Doing it Yourself in PostScript}

If you want to schlep a word onto the wordlist, say ``(elephantine)
NW'' which is the PostScript command that puts the word
``elephantine'' onto the word list. A space will automatically be
added for you. Do {\em not} put a space in your words.  Instead use
two PostScript calls. For example, do {\em not} say ``(ice cream)
NW''. Instead say ``(ice) NW (cream) NW''.

If you have a really long sentence, then you can just say ``(ice cream)
Parse''. Parse is a PostScript routine that will break a string up by
spacing into ``(ice) NW (cream) NW''.

If you want to schlep some horizontal whitespace onto the wordlist,
you can use the LaTeX $\backslash$hspace command. If you really want
to do it in postscript, then ``54.0 HSpace'' is the PostScript command
to add 54 points of horizontal space to the word list. There are 72
points in an inch.

Also, naturally you can gronk the value of any of the variables in the
fontdict directly. Grok-p? Keep in mind that if you change them in
PostScript instead of in LameTeX, then LameTeX will ``lose track'' of
them and may not reset them for you. You will have to put them back to
their original values yourself.

\section{Using $\backslash$pscmd to Do It When You Want It}

the white-painting applied to the whole line, not just parts of it.
You couldn't paint just part of a line white.

Well, here's how. I'm going to tell you twice. This section is the
easy slick way. The next section tells you the {\em same thing}, if
you want to get your hands dirty, which I encourage.

Anyway, for the easy way, take a look at {\tt example5.tex}.

Here I define a command /Smiley that alternately either draws a picture
without changing the currentpoint, or calls READJUST. 

Sometimes LameTeX will be building a line made out of 10 point type
when suddenly the user wants to get 30 point type. Well, since the
line started on this 10 point line, all the 30 point letters are too
tall and will overwrite the previous line just above the current line!
There is a PostScript command that LameTeX calls automatically when
such oopses occur. That's /READJUST. It takes a vertical length to
skip from the stack, in points. There are 72 points in an inch. I have
some command ``in'' defined somewhere that just multiplies any number
by 72 to convert it into points.

You can call /READJUST yourself no problem. For example, I do it here
in example5.tex to make the line tall enough to accept the smiley
face.

Don't forget! At the end of every page, everything gets wiped by the
PostScript {\tt restore} routine. Here Smiley is defined On-Page in
the middle of page 1. On page 2 it would be undefined. If you want
your routine to hang around for page two, you either need to define it
In-Between Pages (the bad wicked way) or define it in /StartPage (the
good way of lightness and being).

Notice that the $\backslash$pscmd command in placed inside braces.
This delimits what is now the ``Smiley'' environment. For example, if
Smiley had changed the font, the font change would have remained in
effect until the end-brace delimiter. The way this is implemented is
really for fonts, and being able to add your own PostScript functions
is not something I had envisioned at first. I will fix this later, but
for the time being realize that your function Smiley, if it not
delimited, will be executed at the beginning of each new line. Also,
any font changes like italics or boldface will kill your Smiley
environment. Try taking out the braces around the $\backslash$pscmd
and you will see what I mean.

I hope you can see how you could use this to include really big
pictures, not just small smiley faces. You get to have complete
control over how big the picture is, by passing its width and height
to READJUST. Alternately, you can modify the wlist array directly if
you want something special. In later versions, the READJUST command
will be able to handle non-rectangular boundaries just like pages do.

There is no way to do this currently unless you modify the Page on the
fly by defining the ``current page'' as something new (including the
box around the Smiley'' and forcing a re-assessment of the dimensions
of the page.

Here are the rules for a routine that you use with $\backslash$pscmd:

\begin{enumerate}
\item When your routine is called, the currentpoint will be set to
where the next word would normally be placed. Make sure that the
currentpoint is defined when your routine is finished. You can
accomplish this neatly by just doing a Postscript ``gsave'' at the
beginning of your routine and a ``grestore'' afterwards.

\item Don't forget that you have access to the entire word list and
format dictionary.

\item When your routine gets called, either false or true will be on
the stack. The value will be ``false'' if LameTeX is building the word
list and ``true'' if LameTeX is printing the word list. You gotta
either use this or pop if off the stack by making the first command in
your PostScript routine be ``pop''.

\item When you split up a word, like by saying {\tt Will you be my
SWEET$\backslash$pscmd{/drawheart}HEART?} LameTeX will make an attempt
to put Sweet and Heart all in the same word. It won't try really hard
though. There is no concept of ``glue'' in LameTeX. I gotta add this
sometime soon. So if a pagebreak occurs, or a line break, LameTeX will
gladly put SWEET at the end of one line and HEART at the beginning of
another. Oops!

\end{enumerate}

\section{Behind the Scenes of $\backslash$pscmd}

Remember the ``Word List''? You too can schlep things onto the word
list. This is exactly what the $\backslash$pscmd does, but if for some
reason it doesn't work or you want to try fiddling with the PostScript
code directly, it's simple. Here's how.

The most interesting part is schlepping a command onto the word list.
Take a look at example3.tex.

To schlep a command onto the word list, I have to first register the
command by placing it onto the end of the {\bf fontnames} array. From
now on I just refer to this command by its number which I store in the
variable FUNKYnum.

The actual syntax for schlepping a command onto the world list is to
say ``[ FUNKYnum false ] NewFont'', where FUNKYnum is an index to my
function in the {\bf fontnames} array, and the boolean is false if I
want LameTeX to add a space after this NewFont command. If the boolean
is false then LameTeX puts no space between a word before the NewFont
command and a word afterwards.

The line ``[ temp false ] NewFont'' is important. Once I have started
playing God with the LameTeX PostScript code, I should remember to put
the font back to the way it was.

I hope it's obvious that the routine would't have to be a
Font-changing routine at all. It could be any routine. Here are some
things to keep in mind though. Remember the flow chart from the
chapter on pages? The routine will be executed {\em twice}, once when
the word list is being compiled, and once when the word list is being
printed.

\section{The Wigglies Hack: using SHOWIT}

I have written a PostScript hack called {\tt format.ps} that does all
the major formatting for LameTeX. The command that it uses to show
words is the SHOWIT routine, which is defined as follows: ``/SHOWIT\{
show \} bind def''.

Feel free to redefine this routine if you want to change the way the
words look in any way. The routine will be called with the
currentpoint set to the appropriate place and the string to be printed
on the stack.

I wrote a cool hack based on this. Try it out with example4.tex. And
don't forget: {\bf When you play God with LameTeX's PostScript output,
be sure to put things back!} When I have finished hacking up SHOWIT
with my own definition, I put it back by saying ``/SHOWIT \{ show \}
bind def''.

You can't do this stuff with TeX macros! (Although you could argue I
suppose that only a loony would try...)

\section{Forcing Word Positions with NW}

NW is defined as follows: ``/NW { NextWord } bind def''. NextWord is
the routine that is called repeatedly, once for each word, to place
the words in the word list. Feel free to modify this routine too if
you want to perform some operation to the strings before they get
included in the word list.

\section{The Skew Page Hack}

Look in the files {\tt starting.tex} and {\tt page\_skew.ps} for an
example of diagonal text. LameTeX is not really capable of placing
text in any way except horizontally (unless you redefine the SHOWIT
and NW routines). So therefore, in order to get diagonal text, the
page must be slanted. So although it looks to the user like the text
is slanted and the page is an upright rectangle, to LameTeX it appears
as if the page is a very wide page in the shape of a diamond on its
end. And the text appears horizontally.

\section{The Checkerboard Hack}

Check out {\tt example6.tex}. Here is an example of two virtual pages
being placed on a single physical 8.5x11 inch piece of paper, using a
variable flip to determine which virtual page comes ``next''. I hope
you can see that it wouldn't be hard to define several virtual pages
on a single physical page (like for making index cards or mailing labels).

\section{Bugs?}

There are no bugs in LameTeX.

% Replace the current small margins with the wider margins.
% \begin{stealth}
% \setlength{\textwidth}{6 in}
% \setlength{\oddsidemargin}{0.25 in}
% \end{stealth}