home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / m / makedrawf / Doc / ManualT < prev    next >
Text File  |  1997-04-29  |  77KB  |  1,948 lines

  1. [[ Note: This text-only version of the manual was produced by hand from
  2.    the Impression version. It is therefore likely that there are lots of
  3.    infelicities in the formatting; in particular, font changes have been
  4.    lost. If a sentence doesn’t seem to make any sense, see whether it’s
  5.    any better if you pretend some of the words in it are in italics. :-) ]]
  6.  
  7. Contents
  8. ========
  9.  
  10. Introduction
  11.   Legal rubbish
  12.   Who am I?
  13.   How to read this manual
  14.  
  15. How to use mkdrawf
  16.   Errors
  17.  
  18. How to get mkdrawf
  19.  
  20. An introduction to drawfiles
  21.   Object type 0: font table
  22.   Object type 1: text
  23.   Object type 2: path
  24.   Object type 5: sprite
  25.   Object type 6: group
  26.   Object type 7: tagged
  27.   Object type 9: text area
  28.   Object type 10: text column
  29.   Object type 11: options
  30.   Object type 12: transformed text
  31.   Object type 13: transformed sprite
  32.   Object type 16: JPEG image
  33.  
  34. The drawfile description language I
  35.   Tokens
  36.   Numbers
  37.   Comments
  38.   Braces
  39.   Numbers
  40.   Comments
  41.   Braces
  42.   Points, dimensions and things
  43.   Colours
  44.   Keywords and special keywords
  45.   Token lists
  46.  
  47. The drawfile description language II
  48.   Global variables
  49.   Macros
  50.   Macro parameters and local variables
  51.   Arithmetic and things
  52.   String operations
  53.   Conversions
  54.   Conditionals
  55.   Iteration
  56.   File inclusion
  57.   Units
  58.  
  59. The drawfile description language III
  60.   The format of an object description
  61.   Bounding boxes
  62.   The Header pseudo-object
  63.   The FontTable object
  64.   The Text object
  65.   The Path object
  66.   The Sprite object
  67.   The Group object
  68.   The Tagged object
  69.   The TextArea object
  70.   The Options object
  71.   The XfText object
  72.   The XfSprite object
  73.   The JPEG object
  74.  
  75. Some sample drawfile descriptions
  76.   The Koch snowflake curve
  77.   A Lissajous figure
  78.   A typical text area
  79.   Circular arcs using Bezier curves
  80.   A silly spiral
  81.  
  82. Tagfiles
  83.  
  84. Technical issues
  85.   Memory management
  86.   Variables
  87.   Problems
  88.   Arbitrary restrictions
  89.  
  90. Differences from the previous version of mkdrawf
  91.   Points don’t have commas
  92.   Strings have quotation marks
  93.   No implicit hexadecimal
  94.  
  95. Revision history
  96.  
  97. Decoding drawfiles
  98.   Using decdrawf
  99.   The output from decdrawf
  100.  
  101.  
  102. ----------------------------------------------------------------------------
  103.  
  104.  
  105. Introduction
  106. ============
  107.  
  108. This is the user manual for mkdrawf, a program for creating drawfiles.
  109. Of course there are other programs for creating drawfiles, notably !Draw,
  110. but mkdrawf is unusual in  that it allows you complete control over what
  111. goes into the drawfile. It takes as input a text file describing the objects
  112. that should go into the drawfile; the description language it uses is quite
  113. powerful, having  variables, macros and some mathematical functions.
  114.  
  115. This manual describes the process of creating a drawfile using mkdrawf, and
  116. includes several sample mkdrawf input files and the resulting output.
  117.  
  118. This manual also describes its much simpler companion program decdrawf,
  119. which performs the inverse process: it converts drawfiles to mkdrawf
  120. descriptions.
  121.  
  122. Before reading this manual you might want to read the mkdrawf tutorial.
  123. You might also want to look at the manual for !Drawf, a Wimp front end
  124. for mkdrawf and decdrawf.
  125.  
  126.  
  127. Legal rubbish
  128. -------------
  129.  
  130. 1. These programs are not public domain; they are mine.
  131.  
  132. 2. You are welcome to distribute them exactly unchanged (where “them”
  133. includes all the source code and both versions (text and Impression) of
  134. this documentation). You are also welcome to make changes to your own
  135. copy of the programs.
  136.  
  137. 3. However, you are not permitted to distribute modified versions without
  138. my permission.
  139.  
  140. 4. Furthermore, you are not permitted to charge money for copies of this
  141. software; it is free software, and I intend that it should remain free.
  142. And I certainly don’t want anyone other than me making money from it!
  143.  
  144. If you make improvements to the programs, I am very unlikely to object to
  145. your distributing the improved version provided it is made clear what
  146. changes you have made; the point is that I don’t want to be blamed for
  147. other people’s bad programming or credited with their good programming,
  148. and that I want the documentation for mkdrawf to be consistent with the
  149. program. So if you improve mkdrawf, get in touch with me so that I can
  150. give you an updated version of the documentation to go with your improved
  151. version.
  152.  
  153. If you have somehow acquired an incomplete or modified version of these
  154. programs, you may distribute it; but I’d prefer you to get in touch with
  155. me and get a complete, up-to-date version of the programs. At the time of
  156. writing, the current version is version 3.09.
  157.  
  158.  
  159. Who am I?
  160. ---------
  161. If you want to get in touch (to moan about problems, to suggest improvements,
  162. to thank me for doing such a truly wonderful job, ...), you will need the
  163. following information.
  164.  
  165. I have an e-mail address and a snail-mail address. Both are valid as of
  166. December 1995, and both are likely to continue working for some time yet.
  167. E-mail is preferred, but I’ll try to answer snail-mail too.
  168.  
  169. e-mail:    gjm11@dpmms.cam.ac.uk
  170.  
  171. snail-mail:
  172.     Gareth McCaughan
  173.     Peterhouse
  174.     Cambridge CB2 1RD
  175.  
  176. I would be really happy to hear from you. If you have complaints or
  177. suggestions, they may help me to make mkdrawf better; and if you have
  178. neither, presumably that’s because mkdrawf is completely perfect for
  179. your needs… I’d be very glad to be told!
  180.  
  181.  
  182. How to read this manual
  183. -----------------------
  184.  
  185. Of course it’s up to you; and it’s not a very long manual, so you could
  186. probably read it in any order you like without causing yourself much trouble.
  187. However, I would suggest the following procedure:
  188.  
  189.   • Have a look at the “sample drawfile descriptions”, to give you some idea
  190.     about how mkdrawf works.
  191.   • If you don’t have much idea of just what goes into a drawfile, read “An
  192.     introduction to drawfiles”.
  193.   • If you’ve used the earlier version of mkdrawf, read “Differences
  194.     from the previous version...”.
  195.   • Read the three chapters on “The drawfile description language”, skipping
  196.     bits you don’t understand. The second contains the most obscurities; you
  197.     might well want to skim the third before reading the other two.
  198.   • Read “How to use mkdrawf”, and create a few files yourself, referring to
  199.     the DDL chapters.
  200.  
  201. At this point you’re on your own. You should be able to do anything you
  202. want, referring to this manual as necessary.
  203.  
  204. If you find this manual heavy going, you might like to read the mkdrawf
  205. tutorial.
  206.  
  207.  
  208. ----------------------------------------------------------------------------
  209.  
  210.  
  211. How to use mkdrawf
  212. ==================
  213.  
  214. This is pretty easy. Just create a suitable input file, and type
  215.   mkdrawf <input-file-name> <output-file-name>
  216. to make the output file. This will create the output file if it doesn’t
  217. already exist, and will set its filetype to DrawFile.
  218.  
  219. The only other way of invoking mkdrawf is to type
  220.   mkdrawf −v
  221. which displays the version number and date of your copy of mkdrawf. This
  222. will be useful if I make further improvements. This version of the manual
  223. describes version 3.09.
  224.  
  225. Alternatively, you can use the !Drawf application to give you a Wimp front
  226. end to both mkdrawf and decdrawf.
  227.  
  228.  
  229. Errors
  230. ------
  231.  
  232. mkdrawf produces three kinds of diagnostic: warnings, errors and fatal
  233. errors. I hope the distinction between them is clear. If any errors or
  234. fatal errors are produced, you should not rely on the resulting drawfile
  235. containing anything sensible, though in most cases it will at any rate
  236. be a valid drawfile. mkdrawf tries hard to carry on reading your input
  237. file even if there are errors (because that may help you to spot several
  238. problems at once); but you should not rely on anything after the first error
  239. making sense. Just as with C, a single error can produce a cascade of
  240. error messages.
  241.  
  242. All this is an improvement on versions 2.10 and earlier, which simply stopped
  243. dead the first time they found anything they couldn’t parse.
  244.  
  245. The command-line option -e will make mkdrawf omit the filename in error and
  246. warning messages. You are unlikely to need this.
  247.  
  248.  
  249. ----------------------------------------------------------------------------
  250.  
  251.  
  252. How to get mkdrawf
  253. ==================
  254.  
  255. If you’re reading this manual, you probably already have a copy. But perhaps
  256. you want to be sure you have the latest version, or you've accidentally
  257. formatted your hard disc, or something. Or perhaps you stole the manual.
  258. Anyway, you can get mkdrawf:
  259.  
  260.   • from me, electronically or postally. If you want a copy sent to you by
  261.     post, please send me either a floppy disc and whatever sort of packaging
  262.     you think is suitable for the return journey, plus £1stg to cover postage
  263.     and make me bother to send it; or £2stg, for which you will get an HD disc
  264.     (or a DD disc if you request that), in what seems to me to be suitable
  265.     packaging. If you add another £4 you can also have a nicely printed
  266.     version of the documentation.
  267.   • from some FTP sites. I know mkdrawf is available at micros.hensa.ac.uk
  268.     (at least from academic sites in the UK), and I’m pretty sure it’s also
  269.     available at ftp.demon.co.uk. Please try any suitable FTP sites you can
  270.     think of before trying to get a copy from me!
  271.  
  272.  
  273. ----------------------------------------------------------------------------
  274.  
  275.  
  276. An introduction to drawfiles
  277. ============================
  278.  
  279. This chapter describes briefly what sort of stuff goes into a drawfile.
  280. If you already know all about that (for instance, if you’ve read the
  281. relevant section of the PRMs), you can skip it. If not, read on...
  282.  
  283. A drawfile consists of a short header followed by a sequence of objects.
  284. Each object consists, in turn, of a short header (similar but not identical
  285. in structure to the header of the whole drawfile) followed by some more
  286. interesting stuff. Exactly what that “more interesting stuff” is depends
  287. on the object; in some cases, it can include other objects (and so
  288. recursively...); see the sections on Group and Tagged objects.
  289.  
  290. There are 12 types of object; several are not understood by the version of
  291. !Draw distributed with RISC OS 2, and one is so recent that no existing
  292. version of !Draw understands it. There is no guarantee that yet more object
  293. types will not be added in later versions of !Draw. Each type has an
  294. associated number, by which objects of that type are identified in drawfiles.
  295. The numbers are not consecutive; the apparent gaps are not mistakes.
  296.  
  297.  
  298. Object type 0: font table
  299. -------------------------
  300.  
  301. When you use !Draw you never see a font table object. That’s because it
  302. doesn’t actually describe any particular part of the drawing. A drawfile
  303. may contain text in several different fonts; internally these fonts are
  304. referred to by magic numbers rather than by names, and the font table
  305. establishes a correspondence between names and numbers. I don’t know for
  306. certain why it’s done this way, but here are some possible reasons:
  307.  
  308. 1. It saves a bit of space in the drawfile if one font is referred to
  309.    many times: only one byte needs to be repeated each time, rather than
  310.    a long font name.
  311. 2. It makes things easier for applications that have to render drawfiles:
  312.    they can call Font_FindFont once for each font in the table, and then
  313.    set up a table of font handles and use that.
  314. 3. It means that if you want to make wholesale changes to the fonts in a
  315.    drawfile (say, replacing Trinity with Homerton throughout), you only
  316.    have to change the font table.
  317.  
  318. (Reason number 3 here is irrelevant if you’re using !Draw, but if you’re
  319. using mkdrawf or something like it it might be significant. My money is on
  320. reason number 2 being the main one, though.)
  321.  
  322. There may only be one font table in a drawfile; if there are any text
  323. objects, there must be exactly one, and it must appear before they do.
  324. Actually !Draw doesn’t cope correctly if the font table is not the very
  325. first object in the file.
  326.  
  327.  
  328. Object type 1: text
  329. -------------------
  330.  
  331. If you select the text tool in !Draw and type some text, you are creating
  332. a text object. A text object specifies, as well as the text to be contained
  333. in it:
  334.   • the colour in which the text is to appear;
  335.   • the background it’s likely to be on;
  336.   • the font it is to appear in;
  337.   • the size and aspect ratio of the font;
  338.   • where the text is to start (that is, its bottom-left corner).
  339.   
  340. The background colour is just a hint. It doesn’t actually cause anything
  341. to be drawn in that colour, but it helps the anti-aliasing code in (for
  342. instance) !Draw to improve the appearance of the text.
  343.  
  344.  
  345. Object type 2: path
  346. -------------------
  347.  
  348. This is the commonest object type. A path is made up of a number of
  349. subpaths. Each subpath is drawn, and perhaps filled, separately (but
  350. the same options for things like path width, fill colour and so on are
  351. common to all the subpaths). A subpath consists of simple elements:
  352.   • move to a given place
  353.   • draw a line to a given place
  354.   • draw a Bezier curve to a given place, with given control points
  355.   • close the current subpath.
  356. Each subpath starts with a move, and each move begins a new subpath.
  357.  
  358. It’s possible to specify the following things for a path object:
  359.   • the colour to use for filling it in (may be “none”)
  360.   • the rule used to determined what gets filled and what doesn’t
  361.   • the colour to use for drawing the outline (may be “none”)
  362.   • the width of the outline
  363.   • how to join up adjacent sections of path
  364.   • what to do at the ends of the path
  365.   • whether the path outline should be “dashed”, and what dash pattern to use
  366.  
  367.  
  368. Object type 5: sprite
  369. ---------------------
  370.  
  371. A sprite object simply consists of an object header and a sprite. (The
  372. object header determines exactly where the sprite will appear and how big
  373. it will be.)
  374.  
  375.  
  376. Object type 6: group
  377. --------------------
  378.  
  379. A group object contains any number of other objects. (It’s possible to
  380. work out from the object header where in the drawfile the list of
  381. objects in the group ends.) The only other information in a group
  382. object is a name; the name has no effect on the rendition of the object,
  383. but it may be used for identification purposes by some applications.
  384.  
  385.  
  386. Object type 7: tagged
  387. ---------------------
  388.  
  389. A tagged object consists of a 4-byte identifier, an object and some quantity
  390. of extra data. A tagged object is rendered simply by rendering the object
  391. it contains; the other stuff may be used by certain applications. (The PRM
  392. says: “This allows specific programs to attach meaning to certain objects,
  393. while keeping the image renderable”.)
  394.  
  395.  
  396. Object type 9: text area
  397. ------------------------
  398.  
  399. A text area object consists of a number of columns and a quantity of text
  400. (and a little extra data). The text contains various escape sequences which
  401. control how it will be formatted. A text area object is rendered by
  402. formatting the text in the columns (using the columns in sequence); users
  403. of DTP packages may like to think of the columns as being linked text frames.
  404.  
  405. A complete list of the escape sequences and their meanings is contained
  406. in the next chapter of this manual.
  407.  
  408.  
  409. Object type 10: text column
  410. ---------------------------
  411.  
  412. Text column objects appear only inside text area objects. They describe
  413. the columns into which the text will be placed.
  414.  
  415.  
  416. Object type 11: options
  417. -----------------------
  418.  
  419. An options object describes the following things, most of which are
  420. specific to !Draw.
  421.   • The size of paper on which the objects are supposed to appear
  422.   • Some information about “paper limits”
  423.   • The set-up of the grid (shown? locked? what spacing? ...)
  424.   • The zoom ratio
  425.   • Whether the toolbox is to be shown or not
  426.   • What “entry mode” to use initially
  427.   • The size of !Draw’s undo buffer
  428.  
  429. If more than one options object appears, !Draw ignores all but the first.
  430. The RISC OS 2 version of !Draw ignores options objects (and doesn’t save
  431. them).
  432.  
  433.  
  434. Object type 12: transformed text
  435. --------------------------------
  436.  
  437. A transformed text object is a text object with bells on. The bells specify:
  438.   • what affine transformation to apply to the text
  439.   • whether to apply kerning to the text
  440.   • whether to render the text right-to-left
  441. An affine transformation is specified by a 2×2 matrix and a vector.
  442. More on this later.
  443.  
  444.  
  445. Object type 13: transformed sprite
  446. ----------------------------------
  447.  
  448. A transformed sprite object bears the same relationship to a sprite object
  449. as a transformed text object does to a text object, except that kerning and
  450. right-to-left aren’t issues. In other words, a transformed sprite object
  451. contains a transformation matrix (erm, and vector) and a sprite.
  452.  
  453.  
  454. Object type 16: JPEG image
  455. --------------------------
  456.  
  457. A JPEG image object consists of a small amount of header data and a JPEG image
  458. in JFIF format. (JPEG is a standard method of compressing images; JFIF is the
  459. name of the commonest file format for JPEG-compressed images. What is usually
  460. called a “JPEG file” should strictly be called a JFIF file.) No current
  461. version of !Draw understands this object type, but future versions might
  462. well do.
  463.  
  464.  
  465. ----------------------------------------------------------------------------
  466.  
  467.  
  468. The drawfile description language I
  469. ===================================
  470.  
  471. This chapter and the next two describe, in some detail, the language
  472. understood by mkdrawf. To be more precise: this chapter is a brief
  473. description of the syntax of the language, the next deals with variables
  474. and macros and things, and the next describes what gets done with the
  475. tokens produced when all the macro expansion and variable substitution
  476. are finished. (So it’s that chapter that actually discusses drawfile
  477. objects.)
  478.  
  479.  
  480. Tokens
  481. ------
  482.  
  483. As mkdrawf reads an input file, it parses it into tokens. A token might be
  484. a keyword like FontTable, or a number like 1.23456, or a colour like
  485. r200g100b123, or whatever. Except in funny circumstances -- strings and
  486. things -- tokens are delimited by whitespace and are not case-sensitive,
  487. so you can write LINE or Line or Line or lInE or whatever you happen to
  488. prefer.
  489.  
  490. Here is a list of the token types understood by mkdrawf, with an example
  491. of each. Some of these are not explained until the next chapter.
  492.   • Number        123.456e2    
  493.   • String        "foo bar"
  494.   • Colour        r123g0b255
  495.   • Keyword        Width
  496.   • Special keyword    Define
  497.   • Global variable    $myvar1
  498.   • Local variable    %length
  499.   • Macro name        Snowflake
  500.   • Opening brace    {
  501.   • Closing brace    }
  502.  
  503. Internally, mkdrawf actually uses a couple of other keyword types, but
  504. they aren’t things you can put into the file yourself.
  505.  
  506. Here’s a brief account of how mkdrawf decides what type each token it sees
  507. has:
  508.  
  509. Opening and closing braces are easy. Anything that starts with a $ is
  510. a global variable; anything that starts with a % is a local variable;
  511. anything that starts with a " is a string. Numbers are things that can
  512. be parsed successfully by the strtod function in the C library; colours
  513. are things matching the scanf format r%dg%db%d. Anything else is one of
  514. the other types. mkdrawf has a list of keywords and “specials”; anything
  515. else must be a macro name. Simple!
  516.  
  517.  
  518. Numbers
  519. -------
  520.  
  521. You can enter a number either in a form that the C library function strtod()
  522. can understand, or in the form 0x1234FEDC (meaning hexadecimal). Both get
  523. dealt with in the program as “double”s, should this be relevant.
  524.  
  525.  
  526. Comments
  527. --------
  528.  
  529. If a token begins with a # then that token, and everything else up to the
  530. end of the line, is ignored by mkdrawf. This is useful for making your
  531. mkdrawf input files more comprehensible, and also for “commenting out”
  532. sections that you don’t want to use but don’t want to throw away completely
  533. either.
  534.  
  535. I suppose that strictly speaking this means there’s another type of token
  536. (comment start), but that’s not how mkdrawf thinks about it internally.
  537. Something that would be a token but begins with a # never makes it as far
  538. as tokenhood; the token-maker just reads a new input line and tries again.
  539.  
  540.  
  541. Braces
  542. ------
  543.  
  544. The language understood by mkdrawf is a structured one; its structure
  545. reflects the structure of drawfiles. For instance, a Group object actually
  546. contains other objects; so the description of a Group object in a mkdrawf
  547. input file actually contains descriptions of other objects. Groupings of
  548. this sort are done with braces. Since braces are tokens, they must have
  549. whitespace on either side. (A brief note for the hitherto ignorant:
  550. “whitespace” includes newlines as well as spaces and tabs!)
  551.  
  552. Whenever it’s stated that something is delimited by braces, this means
  553. it’s delimited by matching braces. For instance, you can’t put unmatched
  554. braces into a macro definition.
  555.  
  556.  
  557. Points, dimensions and things
  558. -----------------------------
  559.  
  560. A point (meaning a location in 2-dimensional space, rather than a pixel)
  561. is represented by two numbers. By convention, the point 0 0 is at the
  562. bottom-left corner of the image. The unit for these numbers, and indeed
  563. for almost all dimensions, is by default the point; for our purposes a point
  564. is exactly 1/72 of an inch. (Historically the printer’s point is a slightly
  565. smaller unit than this; but the definition of the drawfile format says
  566. that its points are exactly this size. I think this accords with usage
  567. in PostScript and on the Apple Macintosh; it differs from that of TeX.)
  568. It's possible to use different units; more on this later.
  569.  
  570. A bounding box is represented by two points, which should be the bottom-left
  571. and top-right coordinates of the box.
  572.  
  573. In a drawfile, most dimensions are stored as integer multiples of 1/640 of
  574. a point; so giving dimensions to 10000 significant figures is probably not
  575. sensible.
  576.  
  577.  
  578. Colours
  579. -------
  580.  
  581. A colour is specified by giving its red, green and blue intensities. The
  582. format is as described above; the numbers should be between 0 and 255
  583. inclusive. There is also a special colour, called None or Transparent
  584. (these are synonyms), which means just what you would expect it to.
  585.  
  586. As of version 2.33, wherever a colour is required you may instead give
  587. three integers in the correct range. They will be used as the red, green
  588. and blue intensities of the colour. This makes it possible to do things
  589. like shading.
  590.  
  591.  
  592. Keywords and special keywords
  593. -----------------------------
  594.  
  595. Keywords are bits of drawfile object specification. Some of them name
  596. object types; some name parameters of objects; some are “flags” (their
  597. presence or absence determines something about an object); some are
  598. possible parameter values, when those values form a finite set. Examples
  599. (in order): Path, OutlineColour, Kerned, Mitred.
  600.  
  601. Special keywords do not directly describe drawfile objects. They are
  602. dealt with earlier, by the macro-and-variable machinery described in the
  603. next chapter. They are used in defining macros, doing arithmetic
  604. calculations, and so on.
  605.  
  606.  
  607. Token lists
  608. -----------
  609.  
  610. I’m not sure whether I should count these as tokens. They are treated as
  611. such in the program. A token list is, errm, a list of tokens; the expansion
  612. text of a macro is a token list, and the value of a variable can be too.
  613. The only thing you really need to know about these is that there’s an
  614. implementation limit on the depth of nesting of token lists, namely 256
  615. levels of nesting.
  616.  
  617. You get a token list into a variable by doing, say,
  618.   Set %womble { 1 2 3 4 }
  619. which gives the local variable womble the token list 1 2 3 4 as its value.
  620. (What’s a local variable? See the next chapter.)
  621.  
  622. Note: the body of a For loop is not actually a token list, although it
  623. looks like one; nor are the brace-delimited bits of drawfile objects.
  624.  
  625.  
  626. ----------------------------------------------------------------------------
  627.  
  628.  
  629. The drawfile description language II
  630. ====================================
  631.  
  632. The drawfile format, unlike (say) PostScript, has no “language” features
  633. at all. A drawfile cannot use variables, looping constructs and so on.
  634. mkdrawf allows you to use some (fairly weak) programming features of this
  635. kind in a way that fits quite well with its underlying language; for
  636. instance, you can give values to variables and define macros.
  637.  
  638. mkdrawf splits your input file into tokens, as discussed in the previous
  639. chapter. However, most of the time it isn’t just reading tokens; it’s
  640. expanding them too. This means that if it sees an expandable token
  641. (I’ll explain this in a moment) it replaces it with its expansion, which
  642. is usually another token or a whole sequence of tokens.
  643.  
  644. The tokens resulting from expansion are then expanded again, and so on;
  645. thus, what eventually emerges is a stream of unexpandable (i.e., simple)
  646. tokens. What happens to those is the subject of the next chapter.
  647.  
  648. Here’s a list of expandable token types, together with what happens to them
  649. on expansion. There’s more detailed information in the next few sections.
  650.  
  651.   • A variable (local or global) is replaced by its value.
  652.   • A macro, together with its parameters, is replaced by its text; while
  653.     that’s being processed, local variables are set up corresponding to
  654.     the parameter values given.
  655.   • A token list is replaced by the tokens in the list, in order.
  656.   • A For, together with its parameters, is replaced by several copies of
  657.     the loop body.
  658.   • An If vanishes, together with any conditional stuff in the “wrong”
  659.     arm of the If.
  660.   • A Define or Set vanishes, together with the thing being defined and
  661.     the value it’s being given; of course the defining or setting happens
  662.     too.
  663.   • An Include, together with the filename following it, is replaced by
  664.     the contents of that file. (This is slightly inaccurate: see below.)
  665.   • An operator (like Plus or Sin), together with 1 or 2 tokens following it,
  666.     is replaced by the result of applying that operator to the appropriate
  667.     values.
  668.  
  669.  
  670. Global variables
  671. ----------------
  672.  
  673. A global variable is named by a token that starts with a dollar sign $.
  674. When mkdrawf sees a global-variable token in its input stream it replaces
  675. it with the current value associated with that variable. Of course this
  676. isn’t quite true, since it must be possible to set the variable in the
  677. first place; when mkdrawf sees the special keyword Set it doesn’t expand
  678. the following token, but treats it as a variable name. It then sets the
  679. variable’s value to be the token that follows, or (if that’s an open-brace
  680. token) the token-list that follows.
  681.  
  682. The value of a variable can be any single token, or a token list. Note
  683. that if you do
  684.   Set $foo { 1 2 3 }
  685. the value of $foo is the list
  686.   1 2 3
  687. rather than the list
  688.   { 1 2 3 }.
  689. When you set a variable to a token list, the tokens in the list are not
  690. expanded as they are being read. (But of course they will be expanded later
  691. when the variable name is read and expanded.) See the comments below on the
  692. same feature for macro parameters if you want to know why.
  693.  
  694.  
  695. Macros
  696. ------
  697.  
  698. A macro’s name can be any token that doesn’t already have some other
  699. significance. So you can’t name a macro Width or 123 or $foo or %zog,
  700. but you could call it Fred or 2a or ^^!"£@. A macro expands to a list of
  701. tokens. You call a macro by giving its name followed by { }. (Why? See the
  702. next section.) Macros are defined with the Define special keyword, which
  703. behaves very much like the Set special keyword: give it the name of the
  704. macro, followed by the text of the macro enclosed in braces.
  705.  
  706.  
  707. Macro parameters and local variables
  708. ------------------------------------
  709.  
  710. There’s more, though: macros can take parameters, and can use local
  711. variables. I’m lumping these together because they have the same syntax
  712. and use the same internal machinery.
  713.  
  714. A parameter or local variable is named by a token that starts with a
  715. percent sign %. It has a value local to the macro containing it; local,
  716. in fact, to the macro invocation containing it. (The point is that you
  717. can call a macro many times; it’s a different variable each time.)
  718.  
  719. Local variables get their values in two ways. The first is by the Set
  720. special keyword, just as for global variables; the second is by being
  721. used as parameters when the macro is called. To call a macro with
  722. parameters, put some stuff between those braces. The stuff should look
  723. like this:
  724.   Fred { %foo 123 %aardvark Width %%% %foo }
  725. which means that macro Fred should be called, and three of its local
  726. variables given values. The local variables are called %foo, %aardvark
  727. and %%%; the values are, respectively, the number 123, the keyword Width,
  728. and whatever the value of local variable %foo is when Fred is called.
  729. (The procedure is: read a token without expansion, check it’s a local
  730. variable name, then read a token with expansion and assign it to the
  731. appropriate local variable for the macro about to be called.)
  732.  
  733. A local variable (or macro parameter) can have a token list as its value.
  734. To do this with a macro parameter, you say (for instance):
  735.   Fred { %foo 123 %bar { Width 1 OutlineColour r0g0b0 } %baz "Hello" }
  736. which means that %foo gets the value 123 and %baz the value "Hello",
  737. as before, but %bar gets that list as its value. Within the macro body,
  738. %bar will expand to Width 1 OutlineColour r0g0b0. Note again that whatever’s
  739. inside the braces doesn’t get expanded until %bar is expanded.
  740.  
  741. This allows you to do something very like anonymous functions (!), and
  742. if you need something variable in there you can always do
  743.   Fred { %list { Set %zog Plus %zog %foo } %foo $zoo }
  744. since the value given to %foo will be expanded at invocation time.
  745.  
  746. The fact that a local variable is local to a macro invocation rather than
  747. to a macro definition, as it were, makes it possible to do recursion. See
  748. the snowflake curve example later.
  749.  
  750. Note that the following will not work:
  751.   Define Foo { FontTable }
  752.   Foo {
  753.     1 "Trinity.Medium"
  754.     2 "Homerton.Bold"
  755.   }
  756. but the following will:
  757.   Define Foo { FontTable }
  758.   Foo { } {
  759.     1 "Trinity.Medium"
  760.     2 "Homerton.Bold"
  761.   }
  762. And so will:
  763.   Set $Foo { FontTable }     # or, Set $Foo FontTable
  764.   Foo {
  765.     1 "Trinity.Medium"
  766.     2 "Homerton.Bold"
  767.   }
  768.  
  769.  
  770. Positional parameters
  771. ---------------------
  772.  
  773. Sometimes you need or want a less cumbersome way of getting parameters into
  774. macros. Macro parameters of the form %number are special: %1 is the first token
  775. after the macro’s parameter list, %2 is the next and so on. As many of these are
  776. read as are needed. (This number may be different for different invocations of
  777. the same macro, please note.)
  778.  
  779. This allows you, for instance, to produce your own functions with syntax
  780. the same as that for the arithmetic functions described below.
  781.  
  782.  
  783. Arithmetic and things
  784. ---------------------
  785.  
  786. You can do some (very limited) mathematical operations on numbers. This
  787. is all done by the token-expansion machinery: for instance, expanding the
  788. Plus special keyword reads two more tokens (with expansion), checks that
  789. they’re numbers, and yields a numerical token whose value is the sum of
  790. their values. The special keywords that do this sort of thing are:
  791.   Plus Minus Times Over Sqrt Sin Cos Tan Arcsin Arccos Arctan Arctan2 Floor;
  792. it’s probably pretty obvious what most of these do, apart from Floor
  793. which gives the greatest integer no greater than the number you give it
  794. and Arctan2 which reads two numerical values x and y and returns the angle
  795. between the positive x-axis and the vector (x,y).
  796. I’m afraid that mathematical expressions look a bit ugly when written
  797. like this; for instance, what you might like to write as “sin(2(x+3))”
  798. becomes
  799.   Sin Times 2 Plus $x 3
  800. which I agree is nasty. Those used to LISP will probably find it a bit
  801. more manageable than most...
  802.  
  803. There is also Random, which reads no more tokens and expands to a random
  804. number between 0 (inclusive) and 1 (exclusive). Unless you are very unlucky
  805. you will get a different sequence of random numbers every time you run
  806. mkdrawf.
  807.  
  808.  
  809. String operations
  810. -----------------
  811.  
  812. It’s possible to do some things with strings, too. Two things, in fact.
  813. Firstly, you can append them to form new strings. Append 3 "foo" "bar " "baz"
  814. expands to "foobar baz". Secondly, you can feed them to the OS_GSTrans SWI,
  815. to get variable substitution and things. (Try making a text object including
  816. the line Text GSTrans "<Sys$Time>".)
  817.  
  818.  
  819. Conversions
  820. -----------
  821.  
  822. It’s sometimes useful to be able to convert strings to numbers, and vice
  823. versa. There are three operators for doing this. Str2Num and Num2Str do just
  824. what you would expect them to (Str2Num will give an error and a result of
  825. zero if given a string that wouldn’t be recognised as a number by the
  826. token-parsing routines). Font "foo" expands to the number of the font whose
  827. name is "foo", if there is any such in the font table. If there is a font
  828. table and it doesn’t contain a font called foo then the expansion is 0 and an
  829. error message is given; if no font table at all has been given, mkdrawf will
  830. insert the font name into an internal table and remember to build a font
  831. table for you when it finishes.
  832.  
  833.  
  834. Conditionals
  835. ------------
  836.  
  837. Expanding the token IfExists does the following: First it reads one token,
  838. without expansion. If this is the name of a variable that exists (i.e., has
  839. had a value assigned to it with Set or as a macro parameter), the next bunch
  840. of tokens will be read from whatever follows it, until an EndIf or Else
  841. token is seen. If an Else token is seen first, everything from there to the
  842. matching EndIf will be skipped. On the other hand, if what it reads is not
  843. the name of an existing variable, everything up to the matching EndIf or
  844. Else is skipped.
  845.  
  846. This is easier than it sounds; the behaviour is just the same as that of
  847. an If in BASIC or C or whatever. Tokens are not expanded while skipping;
  848. they are expanded while not skipping. This means that if you define a macro
  849. with unbalanced If and Else and EndIf things in it, you can cause chaos.
  850. So don’t.
  851.  
  852. As well as IfExists, there are two other sorts of If: IfLess reads two
  853. tokens, with expansion; they must be numbers, and it does what you think
  854. it does; and IfEqual reads two tokens, with expansion, and again does just
  855. what you think it does. If there’s a need for other sorts of conditional,
  856. I can put them in pretty easily.
  857.  
  858.  
  859. Iteration
  860. ---------
  861.  
  862. Finally, and most nastily of all, there is a For construct that behaves
  863. a little like the similarly-named things in other languages. Remember,
  864. though, that this works by macro-expansion; it doesn’t “compile” to a
  865. block of stuff followed by a test and a conditional jump. All the testing
  866. and jumping happens in the macro-expansion mechanism.
  867.  
  868. The syntax is
  869.   For variable initial limit { stuff }.
  870.  
  871. The variable, which may be local or global, is initially given the value
  872. initial. Then stuff is spliced into the token stream. When the end of the
  873. stuff is reached, the variable has its value increased by 1. If that value
  874. is now less than limit, then stuff is spliced into the token stream again,
  875. and it all repeats; otherwise we’re finished. Note that this has more the
  876. semantics of C’s do loop than of its while loop: the stuff is always read
  877. at least once.
  878.  
  879. Relevant facts: the variable is of course not expanded; the stuff is not
  880. expanded before it’s spliced into the token stream, so it can refer to
  881. variable and have that expand differently each time round the loop; it
  882. is legal to change the value of variable within the stuff, and this behaves
  883. in the way you would expect.
  884.  
  885.  
  886. File inclusion
  887. --------------
  888.  
  889. This is not really a “language feature”, but it seems to belong here more
  890. than it does anywhere else. If your mkdrawf code contains a line like
  891. Include "$.Zog.Wombat", the contents of that file will effectively be
  892. included at that point in the input file. You can nest these inclusions;
  893. mkdrawf can cope with having up to 17 input files open at once (although
  894. the Shared C Library or the operating system may impose other restrictions).
  895.  
  896. This allows you to have a “header file” containing frequently used variable
  897. and macro definitions, or to have a mostly-unchanging file with a few
  898. variable bits read from other files.
  899.  
  900. I advise you, for reasons of clarity, to put each Include on a line by
  901. itself. If you don’t, the precise behaviour is as follows: The remainder
  902. of the line on which the Include (with its associated string) finishes is
  903. read, and then input switches to the named file until that is exhausted.
  904.  
  905. You might also want to know that Include doesn’t do anything if it’s read at
  906. a time when tokens aren’t being expanded. The most notable such case is when
  907. the a macro definition is being read. So you can, if you must, have a macro
  908. called Include (although that would stop you using the Include feature from
  909. then onwards). And you can define a macro that includes a file every time it
  910. is expanded; but you can’t read the contents of a file into the definition of
  911. a macro.
  912.  
  913.  
  914. Units
  915. -----
  916.  
  917. It’s possible, as of version 3.07, to use units other than points. If mkdrawf
  918. sees Units 123, it interprets this as “From now on, treat all dimensions as
  919. being given in units each of which is 123 times the size of a point”. To make
  920. this friendlier, mkdrawf predefines a few variables for you: for instance,
  921. $Inches is 72, so that Units $Inches will allow you to write all your
  922. dimensions in inches. The complete list of such variables is, in ascending
  923. order of size: $ScaledPoints $OSUnits $Points $Millimetres $Centimetres
  924. $Inches. (A scaled point is 1/640 of a point, the smallest possible dimension
  925. in most contexts in a drawfile; an OS unit is 1/180 of an inch. More
  926. precisely, Draw assumes that an OS unit is 1/180 of an inch, although this is
  927. probably not true of your screen in your favourite screen mode.) The change
  928. in treatment of dimensions happens when the Units token is expanded, just as
  929. file inclusion happens when the Include token is expanded; so you can put
  930. unit changes into a macro.
  931.  
  932. There is also a Unit token; this expands to a number which is the number of
  933. points in the current unit — thus Units Unit is guaranteed to do nothing.
  934. This can be useful if you want to change units temporarily.
  935.  
  936. Warning: changing the Units affects all dimensions, including things you
  937. might not think of like dash patterns and widths of paths.
  938.  
  939.  
  940. ----------------------------------------------------------------------------
  941.  
  942.  
  943. The drawfile description language III
  944. =====================================
  945.  
  946. This chapter (finally!) describes what happens to the “simple” tokens
  947. that are spat out by the macro-expansion stuff. Here the correspondence
  948. between your input file and the final output file is extremely close.
  949.  
  950. After expansion, your input file should look like a succession of object
  951. descriptions. An object description describes a single drawfile object;
  952. when one object contains another, its object description will contain the
  953. object description for that other object.
  954.  
  955.  
  956. The format of an object description
  957. -----------------------------------
  958.  
  959. An object description consists of a keyword naming the object type,
  960. followed by a left brace, followed by some stuff describing the object,
  961. followed by a right brace. The details of the “stuff” depend, of course,
  962. on just what sort of object it is; in broad terms, though, it’s very much
  963. like what goes into the parameter list for a macro invocation, but instead
  964. of local variable names you put appropriate keywords. I shall refer to
  965. the keyword/value pairs as items.
  966.  
  967. In what follows, a “complete” (in the sense of showing all the possible
  968. keywords and the sort of values they take) description for each object
  969. type is given.
  970.  
  971.  
  972. Bounding boxes
  973. --------------
  974.  
  975. Almost any object can contain an item of the form BoundingBox 0 0 100 200;
  976. this overrides the bounding box mkdrawf would otherwise have given it. This
  977. is not usually a good thing to do, since mkdrawf calculates its bounding
  978. boxes very sensibly. Sprite and transformed sprite objects need a bounding
  979. box (see below); font table and options objects have no bounding boxes. You
  980. also can’t specify explicitly the bounding box of a text area object, because
  981. that is absolutely determined, with no room for disagreement, by its text
  982. columns.
  983.  
  984.  
  985. The Header pseudo-object
  986. ------------------------
  987.  
  988. There is one sort of object description that doesn’t actually describe
  989. a real object. Rather, it describes what goes into the header at the start
  990. of the drawfile. Here’s a “complete” Header object description.
  991.  
  992. Header {
  993.   Version 201 0
  994.   Creator "Aardvark"
  995.   BoundingBox 0 0  500 500
  996. }
  997.  
  998. The Version item takes two integers, the major and minor version numbers.
  999. Changes to the major number indicate incompatible changes in the file format,
  1000. so you shouldn’t give a major number other than 201 unless you have also
  1001. modified mkdrawf to make it produce the new format. The default is 201 0.
  1002.  
  1003. The Creator item takes a string, which must be at most 12 characters long.
  1004. If it’s less than that, it will be padded with spaces. It’s usual to make
  1005. it no more than 8 characters. The default is mkdrawf2 (this is the second
  1006. version of the mkdrawf program; the first was much simpler and lacked
  1007. variables, macros and things).
  1008.  
  1009. The BoundingBox item takes four numbers; their significance was explained
  1010. two chapters ago. You don’t have to give this; generally mkdrawf does a
  1011. good job of working out bounding boxes. You might want to change it for
  1012. special effects, though, but you should be warned that applications are
  1013. perfectly within their rights to misbehave horribly if given dishonest
  1014. bounding boxes!
  1015.  
  1016.  
  1017. The FontTable object
  1018. --------------------
  1019.  
  1020. Here’s a complete FontTable object description.
  1021.  
  1022. FontTable {
  1023.   1 "Trinity.Medium.Italic"
  1024.   2 "Helvetica.Medium.Exploding.Strawberry"
  1025.   3 "Corpus.Oblique"
  1026. }
  1027.  
  1028. Font number 0 is always the bitmapped system font; you should not try to
  1029. redefine it. Also, font numbers are only 1 byte long. In other words, the
  1030. numbers you give must be integers between 1 and 255, inclusive.
  1031.  
  1032. Incidentally, I have lost my only copy of the
  1033. Helvetica.Medium.Exploding.Strawberry font; if you know where I might
  1034. find another, please let me know.
  1035.  
  1036. If you don’t put a FontTable object in your drawfile description,
  1037. mkdrawf will construct one for you. However, if you do have a FontTable
  1038. it must contain all the fonts you use in Text and XfText objects.
  1039.  
  1040.  
  1041. The Text object
  1042. ---------------
  1043.  
  1044. Here’s a complete Text object description.
  1045.  
  1046. Text {
  1047.   Colour r0g0b0            # black
  1048.   Background r255g255b255  # white; remember this is just a hint
  1049.   Style 1                  # in other words, font number 1
  1050.   Size 10 12               # x-size 10 points, y-size 12 points
  1051.   StartAt 100 100          # start at (100,100)
  1052.   Text "This is a text object"
  1053. }
  1054.  
  1055. If you find Style unpleasant in this context, let me know. It’s what the
  1056. description in the PRM uses. It might be relevant that the “style” here is
  1057. a 4-byte word; one byte is used for the font number, and the rest is
  1058. reserved. So perhaps one day it will mean something other than just “font”...
  1059.  
  1060. You can specify the placing of the text in another way besides StartAt: if
  1061. you replace it with an item CentreIn 100 100 500 300 (say), then the text
  1062. will be placed so that its bounding box has its centre at the centre of that
  1063. box. Alternatively you can give both StartAt point and HCentreIn box; this
  1064. computes the horizontal position from the box and the vertical position from
  1065. the StartAt. Since these are horribly verbose, you can also say
  1066. CentreAt 300 200 or HCentreOn 100 500 200; the former means what you think
  1067. it does, the latter takes two x-coordinates and a y-coordinate.
  1068.  
  1069. As of version 3.08, when a Text or XfText object (we’ll meet XfText objects
  1070. later) is made, mkdrawf sets the variables $_x0, $_y0, $_x1, $_y1 to the
  1071. bounding box of the object it has just created. This makes it possible to
  1072. tell mkdrawf to put two pieces of text so that the gap between them is of
  1073. some desired size. It’s sometimes useful to be able to get at the bounding
  1074. box of a piece of text before you typeset it; version 3.08 also introduces
  1075. the Virtual keyword which allows you to do this. A Text or XfText object
  1076. which is Virtual doesn’t actually get put into the drawfile. The bounding box
  1077. variables, however, do get set. Thus you can find out the vital statistics of
  1078. a text object before you actually commit yourself to putting it in a
  1079. particular place. One other thing about Text and XfText objects has changed
  1080. in 3.08: most attributes of a piece of text now default to whatever values
  1081. they had for the last Text/XfText object (even if it was virtual). This
  1082. should save typing.
  1083.  
  1084.  
  1085. The Path object
  1086. ---------------
  1087.  
  1088. This one is rather complicated; glance at the description in the drawfile
  1089. summary earlier to see why! Anyway, here’s a complete Path object
  1090. description.
  1091.  
  1092. Path {
  1093.   FillColour None
  1094.   OutlineColour r0g0b255
  1095.   Width 1                  # in points. 0 means as thin as possible
  1096.   Style {
  1097.     Mitred                 # join style. Options: Mitred, Round, Bevelled
  1098.     EndCap Round           # Options: Butt, Round, Square, Triangular
  1099.     StartCap Triangular
  1100.     WindingRule NonZero    # determines how filling is done. Alternative: EvenOdd
  1101.     CapWidth 32            # for triangular caps only.
  1102.                            # 0..255, in 1/16ths of the line width
  1103.     CapLength 64           # ditto
  1104.     Dash {
  1105.       1 3 2 5 3            # if you have no idea what this means, experiment!
  1106.       Offset 2 }           # ditto
  1107.   }
  1108.   # Now the path itself
  1109.   Move 100 100
  1110.   Line 200 100
  1111.   Curve 250 100  200 300  400 400      # Bezier curve. Two control points, endpoint
  1112.   Close                    # this subpath
  1113.   Move 200 200
  1114.   Line 300 200
  1115.   Move 500 500             # this begins a new subpath too,
  1116.                            # even though no Close before it
  1117.   Line 0 0
  1118. }
  1119.  
  1120. If the Style item specifies a dash pattern, it must come before any path
  1121. elements. This is a consequence of the way in which the information is
  1122. arranged in the drawfile: the dash pattern, if present, comes before the
  1123. path elements, and it’s of variable size.
  1124.  
  1125. There are also “relative motion” keywords RMove, RLine and RCurve. These
  1126. are just like the R-less versions, except that the numbers they mention are
  1127. relative to the last point visited: thus they behave exactly like the
  1128. similarly-named PostScript operators.
  1129.  
  1130.  
  1131. The Sprite object
  1132. -----------------
  1133.  
  1134. I’m afraid the way you specify a sprite is pretty nasty; this is more or
  1135. less inevitable, but it’s possibly nastier than it ought to be. A sprite
  1136. object description contains a BoundingBox item (like that in the drawfile
  1137. header), and a load of numbers. I strongly advise you to specify the numbers
  1138. in hexadecimal; don’t forget that if you do this the 0x on the front is not
  1139. optional!
  1140.  
  1141. The bounding box is not optional. It specifies where the sprite is to be
  1142. placed, and how big it is to be.
  1143.  
  1144. The numbers are simply the words that will be placed into the file, in
  1145. order. See the PRMs for details of the sprite format.
  1146.  
  1147. Here’s an example.
  1148.  
  1149. Sprite {
  1150.   BoundingBox 100 100 200 200
  1151.   0x000002D4 0x745F6369 0x6C706D65 0x00006465
  1152.   several lines of hexadecimal rubbish deleted
  1153.   0x00000077
  1154. }
  1155.  
  1156. As of version 2.20, there is another way of specifying a sprite: the
  1157. BoundingBox item is still needed, but instead of the load of numbers
  1158. you write FromFile followed by two strings. The first should be the name of a
  1159. sprite file, and the second the name of a sprite in that file. The resulting
  1160. behaviour should be obvious. I recommend that you use the old method where
  1161. possible, because this keeps all the information necessary to recreate the
  1162. drawfile in one place.
  1163.  
  1164. The Group object
  1165. ----------------
  1166.  
  1167. Here’s a typical Group object description.
  1168.  
  1169. Group {
  1170.   Name "ThisIsAGroup"      # maximum 12 characters here
  1171.   Text {
  1172.     Size 10 10
  1173.     StartAt 100 100
  1174.     Style 2
  1175.     Text "Foo"
  1176.   }
  1177.   Group {                  # a group may contain another group
  1178.     Path {                 # All the path style options have sensible defaults
  1179.       Move 100 100
  1180.       Line 200 100
  1181.     }
  1182.     Path {
  1183.       FillColour r200g200b200
  1184.       Move 200 200
  1185.       Line 300 300
  1186.       Line 100 300
  1187.       Close
  1188.     }
  1189.   }                        # a group doesn't need to be given a name
  1190. }
  1191.  
  1192.  
  1193. The Tagged object
  1194. -----------------
  1195.  
  1196. A tagged object, remember, consists of a 4-byte tag identifier, an object,
  1197. and some other (optional, word-aligned) data. Here’s what it looks like:
  1198.  
  1199. Tagged {
  1200.   Identifier 0x12345678
  1201.   Text {
  1202.     blah blah blah
  1203.   }
  1204.   OtherData 0x9ABCDEF0
  1205.   OtherData 0x11111111
  1206.   OtherData 12345          # this is decimal 12345
  1207. }
  1208.  
  1209. Strictly speaking, you should register tag identifiers with Acorn. Unless
  1210. you’re planning to use them in a commercial product, there’s not much need
  1211. to bother, since they aren’t used much. Just pick a random number and hope
  1212. it doesn’t clash with anything.
  1213.  
  1214.  
  1215. The TextArea object
  1216. -------------------
  1217.  
  1218. Here’s a fairly complete text area object description. The only
  1219. incompleteness is in the fact that there should really be some control
  1220. sequences in the text.
  1221.  
  1222. TextArea {
  1223.   Column 100 400  200 500
  1224.   Column 220 400  320 500
  1225.   Colour r0g0b0
  1226.   Background r255g255b255
  1227.   Text {
  1228.     Really there should be some escape sequences at the start of this; too
  1229.     bad. This text will be formatted in the 2 columns specified at the
  1230.     start of the object description, or would be if the escape sequences
  1231.     were there.
  1232.   }
  1233. }
  1234.  
  1235. Note that the text is not quoted. The processing of text in a text area is
  1236. an exception to the way in which input is processed: it is just read
  1237. character by character, and terminated by the first line containing nothing
  1238. other than a closing brace and whitespace. The extra space at the starts of
  1239. lines in the example above isn’t a problem, because multiple whitespace
  1240. characters are treated as single spaces in text areas (unless there’s more
  1241. than one consecutive newline; see later).
  1242.  
  1243. This unusual processing has certain unfortunate consequences: you cannot get
  1244. anything into the text of a text area using macros or variables, and
  1245. comments don’t work. Also, anything following the open-brace token after
  1246. Text and on the same line is simply ignored.
  1247.  
  1248. All the columns must come before the text.
  1249.  
  1250. Silly implementation restriction (my fault, not Acorn’s): you may have
  1251. at most 16 columns. If you need more, it’s a trivial matter to change the
  1252. program to allow more.
  1253.  
  1254. Multiple spaces and tabs are treated as single spaces. A single newline is
  1255. treated as a single space (including absorbtion into multiple spaces);
  1256. extra newlines insert extra vertical space (for paragraphs). Newlines
  1257. occurring before any printing text are considered to be multiple newlines
  1258. for this purpose.
  1259.  
  1260. Here’s a list of escape sequences. Each starts with a backslash; the escape
  1261. sequences themselves are case-sensitive, but their arguments aren’t. Any
  1262. argument may be terminated with a /, and variable-length ones must be
  1263. (except that a newline will do instead). Dimensions should be given in
  1264. points.
  1265.  
  1266. \! <version number>    This must appear at the start of the text, and may
  1267.         not appear anywhere else. The version number must be
  1268.         1, and must be followed by / or a newline.
  1269. \A<code>    Determines alignment. <code> is L, R, C or D, indicating
  1270.         left, right, centred or double (i.e., L and R). Default is L.
  1271. \B<colour>    Set background colour hint for following text. <colour> might
  1272.         be 200 3 150; range is 0..255, at least one space is needed
  1273.         between successive numbers, and a / or newline is needed at
  1274.         the end.
  1275. \C<colour>    Set foreground colour for following text.
  1276. \D<number>    Indicates number of columns. This must be given, before any
  1277.         printing text, unless the number is 1.
  1278. \F<fontspec>    Defines a font reference number. Typical use:
  1279.           \F 1 Trinity.Medium 12
  1280.         means number 1 is Trinity Medium, 12 point. Font numbers
  1281.         are 1 or 2 digits, and are entirely separate from the
  1282.         numbers used for text objects. You may specify a font width
  1283.         as well: \F 1 <name> 12 10 means 12pt high, 10pt wide. Don’t
  1284.         forget the slash or newline. (This last goes for \C, \D, and
  1285.         most other escape sequences. I shall now stop mentioning it.)
  1286. \<number>    Means “now use font number ...”.
  1287. \L<leading>    Defines the leading; i.e., the vertical distance between
  1288.         baselines of successive lines of text. The default is 10pt;
  1289.         specify it in points.
  1290. \M<lt><spaces><rt>    Margin sizes; must be positive; default is 1 (point).
  1291. \P<leading>    Paragraph leading; i.e., the amount of extra space left from
  1292.         each newline after the first in any consecutive sequence.
  1293.         Default is 10pt.
  1294. \U<ulspec>    Switches on underlining. \U 10 2 means 10 units above (or
  1295.         is it below?) the baseline, 2 units thick. One unit is 1/256
  1296.         of the font size. Ranges -128..127, 0..255 respectively.
  1297.         Switch off either by giving a thickness of 0 or by using
  1298.         “\U.”.
  1299. \V[-]<digit>    Vertical move. In points.
  1300. \-        Allow a line break here, inserting a hyphen if one happens
  1301.         (and nothing otherwise).
  1302. \<newline>    Force a line break here.
  1303. \;        Everything from here to next newline is ignored.
  1304.  
  1305. Note:    there is no such thing as a TextColumn object descriptor. Text
  1306. column objects only occur inside text area objects, and are produced
  1307. automatically by mkdrawf.
  1308.  
  1309.  
  1310. The Options object
  1311. ------------------
  1312.  
  1313. Here’s an options object description illustrating just about everything.
  1314. Almost all of this is specific information for !Draw telling it how to
  1315. behave when it has the file loaded.
  1316.  
  1317. Options {
  1318.   PaperSize 4              # meaning: A4
  1319.   Limits {
  1320.     Shown                  # not sure what this does. Omit to negate
  1321.     Landscape              # Omit for portrait
  1322.     NonDefault             # not sure what this does. Omit to negate
  1323.   }
  1324.   Grid {
  1325.     Spacing 1.2345         # cm, unless "Inches" given; see below
  1326.     Divisions 5
  1327.     Isometric              # omit for rectangular
  1328.     AutoAdjust             # Omit to turn this off
  1329.     Shown                  # Omit if you don't want grid visible
  1330.     Lock                   # Omit if you don't want grid lock on
  1331.     Inches                 # Omit for centimetres
  1332.   }
  1333.   Zoom {
  1334.     Ratio 3 2              # means 3:2. Both numbers should be in range 1..8
  1335.     Lock                   # to powers of 2. !Draw seems to ignore it anyway
  1336.   }
  1337.   NoToolbox                # omit if you want toolbox shown when file loaded
  1338.   Mode Line                # initial entry mode. Possibilities are
  1339.                            # Line,ClosedLine,Curve,ClosedCurve,Rectangle,
  1340.                            # Ellipse,Text,Select.
  1341.   UndoSize 1234            # size of undo buffer, in bytes
  1342. }
  1343.  
  1344.  
  1345. The XfText object
  1346. -----------------
  1347.  
  1348. That is, transformed text. An XfText object description is just like a
  1349. Text object description, but it has up to three extra items. The most
  1350. important is one that looks like
  1351.   Matrix 0.5 1 2 -0.1  30 0
  1352. which means that the text should be transformed by the 2x2 matrix given as
  1353. the first 4 numbers, and then translated by the vector given as the last 2.
  1354. To be more precise, the transformation done is
  1355.   (x y)  |-->  (x y)  / 0.5    1  \   +  (30 0) .
  1356.                      |             |
  1357.                       \  2   -0.1 /
  1358.  
  1359. The other two items available are “flags”: Kerned and RightToLeft. You can
  1360. probably work out what they do. Incidentally, I think text in text objects
  1361. is never kerned, and text in text area objects is always kerned.
  1362.  
  1363. The position of the text in an XfText object may be specified using CentreIn
  1364. or CentreAt; as of version 3.09 you can even use HCentreIn or HCentreOn, but
  1365. the results aren't guaranteed to be sensible if the Matrix is non-trivial.
  1366.  
  1367.  
  1368. The XfSprite object
  1369. -------------------
  1370.  
  1371. An XfSprite object is just like a sprite object except that it can (and
  1372. should) also contain a transformation matrix, exactly like those used for
  1373. XfText objects. The sprite itself can (as for sprite objects) be given
  1374. either directly or in terms of a sprite file and a sprite name.
  1375.  
  1376. The placing and size of a transformed sprite are not determined by the
  1377. bounding box, but by the transformation matrix and the contents of the
  1378. sprite itself. However, mkdrawf doesn’t understand sprites (it just treats
  1379. a sprite as a lump of data), so it can’t make any sort of attempt at
  1380. computing a bounding box. So give it one.
  1381.  
  1382. For the record, an identity matrix with zero translation puts the
  1383. sprite’s bottom-left corner at (0,0) and its top right corner at (w.ex,h.ey)
  1384. where w,h are the width and height of the sprite in pixels and ex,ey are
  1385. the “eigenfactors” for the mode in which the sprite was defined.
  1386.  
  1387.  
  1388. The JPEG object
  1389. ---------------
  1390.  
  1391. A JPEG object is in several ways rather like a transformed sprite object.
  1392. Here is a “complete” JPEG object description:
  1393. JPEG {
  1394.   BoundingBox 100 100 300 200   # this is needed
  1395.   Size 200 100                  # and so is this; I'm not sure why
  1396.   DPI 90 45                     # in x,y directions. Default is 90,90
  1397.   Matrix 2 0 0 1 100 0          # Default is identity, of course
  1398.   FromFile "a_jpeg"
  1399. }
  1400.  
  1401. You must specify the Size; I’m not sure exactly what it means and how it
  1402. relates to the BoundingBox; I don’t have anything capable of displaying
  1403. drawfiles containing JPEG objects, so your guess is as good as mine. Instead
  1404. of giving a filename, you can in principle include the contents of the
  1405. JPEG file in the object description (as with sprites and transformed sprites),
  1406. but JPEGs are usually big enough that you really don’t want to do this. If
  1407. you do do this, you need to provide an item like
  1408.   Length 12345
  1409. giving the exact length of the JPEG image in bytes; mkdrawf will not try to
  1410. guess from the number of integers you give, because the size of a JPEG image
  1411. need not be a whole number of words.
  1412.  
  1413. A reminder: no current version of !Draw understands JPEG image objects.
  1414.  
  1415.  
  1416. ----------------------------------------------------------------------------
  1417.  
  1418.  
  1419. Some sample drawfile descriptions
  1420. =================================
  1421.  
  1422. Here are some examples of what can be done with mkdrawf. Only the input
  1423. files are given below, for obvious reasons; the results are in the “Examples”
  1424. directory.
  1425.  
  1426.  
  1427. The Koch snowflake curve
  1428. ------------------------
  1429.  
  1430. The fractal everybody knows. Dead easy. This takes just under 8.4 seconds
  1431. on my machine, by the way.
  1432.  
  1433. # Snowflake curve
  1434.  
  1435. Set $r3/2 Over Sqrt 3 2
  1436.  
  1437. # Side { %x0 .. %y0 .. %x1 .. %y1 .. %n .. }
  1438. # this should be inserted into a Path
  1439. # The assumption is that we’re
  1440. # already "at" (x0,y0).
  1441. Define Side {
  1442.   IfLess %n 1
  1443.     Line %x1 %y1
  1444.   Else
  1445.     Set %dx Over Minus %x1 %x0 3
  1446.     Set %dy Over Minus %y1 %y0 3
  1447.     Set %xa Plus %x0 %dx         Set %ya Plus %y0 %dy
  1448.     Set %xb Minus %x1 %dx        Set %yb Minus %y1 %dy
  1449.     Set %xh Over Plus %x0 %x1 2  Set %yh Over Plus %y0 %y1 2
  1450.     Set %xt Plus %xh Times %dy $r3/2
  1451.     Set %yt Minus %yh Times %dx $r3/2
  1452.     Set %m Minus %n 1
  1453.     Side { %x0 %x0 %y0 %y0  %x1 %xa %y1 %ya  %n %m }
  1454.     Side { %x0 %xa %y0 %ya  %x1 %xt %y1 %yt  %n %m }
  1455.     Side { %x0 %xt %y0 %yt  %x1 %xb %y1 %yb  %n %m }
  1456.     Side { %x0 %xb %y0 %yb  %x1 %x1 %y1 %y1  %n %m }
  1457.   EndIf
  1458. }
  1459.  
  1460. Set $x0 100  Set $y0 100
  1461. Set $x1 400  Set $y1 100
  1462. Set $x2 250  Set $y2 Plus 100 Times 300 $r3/2
  1463.  
  1464. Path {
  1465.   Move $x0 $y0
  1466.   Side { %x0 $x0 %y0 $y0  %x1 $x1 %y1 $y1  %n 5 }
  1467.   Side { %x0 $x1 %y0 $y1  %x1 $x2 %y1 $y2  %n 5 }
  1468.   Side { %x0 $x2 %y0 $y2  %x1 $x0 %y1 $y0  %n 5 }
  1469.   Close      # not really needed unless you want to fill it
  1470. }
  1471.  
  1472.  
  1473. A Lissajous figure
  1474. ------------------
  1475.  
  1476. You might have produced things slightly like this at school by connecting
  1477. a couple of signal generators to an oscilloscope. (Except I bet it didn’t
  1478. do the pretty chequered pattern.) The drawfile this produces could certainly
  1479. be made smaller by using Bezier curves instead of straight lines, but it’s
  1480. not very big anyway. mkdrawf takes about 3.1 seconds to process this file on
  1481. my machine.
  1482.  
  1483. Set $Pi 3.141592653589793
  1484. Set $Factor Over $Pi 400
  1485. Path {
  1486.   Fillcolour r255g0b0
  1487.   Style { WindingRule EvenOdd }
  1488.   For $i 0 801 {
  1489.     Set $j Times $i $Factor
  1490.     Set $p Cos Times 9 $j
  1491.     Set $q Sin Times 13 $j
  1492.     IfEqual $i 0 Move Else Line EndIf
  1493.       Plus 400 Times $p 300
  1494.       Plus 400 Times $q 300
  1495.   }
  1496.   Close
  1497. }
  1498.  
  1499.  
  1500. A typical text area
  1501. -------------------
  1502.  
  1503. This drawfile contains nothing but a text area. I apologise for the inanity
  1504. of the text in it; this was typed in at random one evening while I was
  1505. testing an earlier version of the program, and I just wanted a certain
  1506. amount of text.
  1507.  
  1508. TextArea {
  1509.   Column 100 400 200 500
  1510.   Column 220 400 320 500
  1511.   Colour r0g0b0
  1512.   Text {
  1513.     \! 1
  1514.     \F 1 Trinity.Medium.Italic 12
  1515.     \F 2 Trinity.Medium 12
  1516.     \1
  1517.     \AD
  1518.     \D2
  1519.     \L12
  1520.     This is some text I'm putting in a text area.
  1521.     I have no idea how it will look, nor indeed whether
  1522.     it will work at all. For all I know \2 mkdrawf\1 will
  1523.     just choke utterly on it, or corrupt my file, or
  1524.     cause demons to fly out of the monitor.
  1525.  
  1526.     This should be a new paragraph; it will still be in italics.
  1527.     \2 Now we should be in roman type. (Isn't this fun, boys
  1528.     and girls?)
  1529.     
  1530.     Apparently the 1998 World Cup will be decided, in the event
  1531.     of a draw, by a sudden-death playoff instead of by a penalty
  1532.     shootout. How interesting.
  1533.   }
  1534. }
  1535.  
  1536.  
  1537. Circular arcs using Bezier curves
  1538. ---------------------------------
  1539.  
  1540. Here’s a useful macro you may want to use in your own mkdrawf code. It
  1541. produces (an approximation to) an arc of a circle using Bezier curves. I
  1542. don’t know whether the particular approximation it uses is the same as the
  1543. one used in !Draw, but it gives good results. This takes about 0.5 seconds
  1544. on my machine, by the way.
  1545.  
  1546. # %x0,%y0 is centre
  1547. # %r      is radius
  1548. # %a0,%a1 are starting and ending angles in radians
  1549. # %n      if set, indicates how many arcs to use
  1550. Define Arc {
  1551.   Set %da Minus %a1 %a0
  1552.   IfExists %n Else
  1553.     Set %n Floor Plus .99 Over %da .75
  1554.   EndIf
  1555.   Set %da Over %da %n
  1556.   Set %t Over Minus 1 Cos Over %da 2
  1557.               Times .75 Sin Over %da 2
  1558.   Move Plus %x0 Times %r Cos %a0
  1559.        Plus %y0 Times %r Sin %a0
  1560.   Set %aa %a0
  1561.   Set %cc Cos %aa
  1562.   Set %ss Sin %aa
  1563.   For %k 0 %n {
  1564.     Set %a %aa
  1565.     Set %aa Plus %a %da
  1566.     Set %c %cc        Set %s %ss
  1567.     Set %cc Cos %aa   Set %ss Sin %aa
  1568.     Curve Plus %x0 Times %r Minus %c Times %t %s
  1569.           Plus %y0 Times %r Plus %s Times %t %c
  1570.           Plus %x0 Times %r Plus %cc Times %t %ss
  1571.           Plus %y0 Times %r Minus %ss Times %t %cc
  1572.           Plus %x0 Times %r %cc
  1573.           Plus %y0 Times %r %ss
  1574.   }
  1575. }
  1576.  
  1577. Set $Pi 3.141592653589793
  1578.  
  1579. Path {
  1580.   Arc { %x0 300 %y0 300 %r 200 %a0 0 %a1 Times 2 $Pi %n 2 }
  1581.   # very inaccurate: only 2 arcs
  1582.   Close
  1583. }
  1584. Path {
  1585.   Arc { %x0 300 %y0 300 %r 200 %a0 0 %a1 Times 2 $Pi }
  1586.   # I think this does 9 arcs
  1587.   Close
  1588. }
  1589.  
  1590.  
  1591. A silly spiral
  1592. --------------
  1593.  
  1594. I first drew pictures like this on an old Hewlett-Packard desktop computer,
  1595. back in 1982 or so. I still think they rate quite highly for
  1596. prettiness-to-effort ratio. This is really an excuse for demonstrating
  1597. RLine. Oh, and it takes about 2s.
  1598.  
  1599. Set $2Pi 6.2831853071795864769
  1600. Set $Conv Over $2Pi 360
  1601.  
  1602. Define Spiral {
  1603.   Set %theta 0
  1604.   Set %r %dr
  1605.   For %i 0 %n {
  1606.     RLine Times %r Cos Times $Conv %theta
  1607.           Times %r Sin Times $Conv %theta
  1608.     Set %r Plus %r %dr
  1609.     Set %theta Plus %theta %dt
  1610.     IfLess 360 %theta
  1611.       Set %theta Minus %theta 360
  1612.     EndIf
  1613.   }
  1614. }
  1615.  
  1616. Path {
  1617.   Outlinecolour r0g0b0  Width 0
  1618.   Move 250 250
  1619.   Spiral { %dr .5 %dt 65 %n 500 }
  1620. }
  1621.  
  1622.  
  1623. ----------------------------------------------------------------------------
  1624.  
  1625.  
  1626. Tagfiles
  1627. ========
  1628.  
  1629. NOTE: This describes an optional feature of mkdrawf, which is not included in
  1630. the ready-compiled version of mkdrawf distributed with this manual. You’ll
  1631. have to recompile if you want to use it. This is because I expect most people
  1632. not to need it — it was added because one particular user asked for it. If
  1633. you don’t use it, why should it take up space in your executable? To make a
  1634. version of mkdrawf with tagfiles enabled, compile mkdrawf.c with the
  1635. preprocessor symbol TAGS defined.
  1636.  
  1637. Suppose you have a mkdrawf “script” which gets used repeatedly, but with
  1638. slight changes made to some of the strings. (If you don’t, you don’t need
  1639. tagfiles.) You could go through and change the file every time, but that
  1640. would be tedious. You could have the strings put into variables by an
  1641. Included file, and use different files on different occasions, but that would
  1642. be a waste of variables. The tagfile feature provides an alternative.
  1643.  
  1644. A tagfile consists of a number of lines, each containing a tag and an
  1645. associated value. There is a mkdrawf operator which takes a string, looks for a
  1646. matching tag and replaces it with the corresponding value. There are also
  1647. mkdrawf “specials” for opning and closing tagfiles. This is getting terribly
  1648. abstract: here’s a concrete example.
  1649.  
  1650. A tagfile:
  1651.   One:un
  1652.   Two:deux
  1653.   # This is a comment; it will be ignored.
  1654.   Saturday:samedi # ceci n'est pas une remarque
  1655.   ThoughtPolice:Academie Francaise
  1656.  
  1657. A mkdrawf file:
  1658.   TagOpen "tagfile"
  1659.   ...
  1660.   Text { ...
  1661.     Text Append 3 "The " TagLookup "ThoughtPolice:FBI" " will get you!"
  1662.   }
  1663.   ...
  1664.   TagClose
  1665.  
  1666. This will behave exactly as if you’d had instead a line saying
  1667.   Text "The Academie Francaise will get you!".
  1668. If your tagfile contained a line
  1669.   ThoughtPolice:Child Support Agency
  1670. instead of the one above, then the effect would be as if the Text item was
  1671.   Text "The Child Support Agency will get you!".
  1672. If it didn’t contain any ThoughtPolice line at all, you’d get
  1673.   Text "The FBI will get you!".
  1674. You are allowed to miss off the default (“:FBI” above) in a TagLookup; if the
  1675. tag is not found you will get an error message and the expansion of the
  1676. TagLookup will be the empty string.
  1677.  
  1678. You may only have one tagfile “open” at a time. (In fact it is only really
  1679. open while the TagOpen is doing its work; its contents are read into memory,
  1680. and TagClose means “free the memory used for tagfile data”.) Its lines are,
  1681. in effect, searched in order when looking for a tag. 
  1682.  
  1683. The similarity between tagfiles and RISC OS message files is deliberate.
  1684. However, tagfiles don’t provide any of the fancy wildcarding features
  1685. provided by MessageTrans. They may do in the future.
  1686.  
  1687. If you put “-t foo” on the mkdrawf command line, the effect will be as if the
  1688. very first line of the file had been TagOpen "foo". This can be useful if you
  1689. want to run something with several different tagfiles without changing the
  1690. mkdrawf file itself; for instance, in makefiles.
  1691.  
  1692.  
  1693. ----------------------------------------------------------------------------
  1694.  
  1695.  
  1696. Technical issues
  1697. ================
  1698.  
  1699. If you’re interested in mkdrawf, you’re quite likely to be interested in
  1700. its internals. (Wimps use !Draw. Real Men use mkdrawf. Or something.) So
  1701. here is some information about how it works, with particular emphasis on
  1702. things that need improving. (After all, *you* might be able to make it
  1703. better...)
  1704.  
  1705.  
  1706. Memory management
  1707. -----------------
  1708.  
  1709. Oh dear.
  1710.  
  1711. This is a real mess, basically because it’s seldom trivial to know when
  1712. a piece of memory is finished with and can be thrown away. Every time a
  1713. string is created, a new block of memory is malloced; these blocks are
  1714. never freed. (Once upon a time this was true for numbers as well!) There
  1715. are some places in the program where we could free things, but there are
  1716. so many memory leaks that it is probably more sensible to wait until I
  1717. have the time and energy, and fix it all properly.
  1718.  
  1719. The real problem is that there is no guarantee that any particular token
  1720. will not get included in a token list. If that happens, we can’t afford
  1721. to throw it away. So we can’t, for instance, always free the memory used
  1722. by an old variable value. One solution to this problem would be to make
  1723. sure that we always copy tokens when we use them, but this would be terribly
  1724. time-inefficient. The best solution is probably to implement a
  1725. garbage-collector. Hmmm.
  1726.  
  1727. Fortunately, most drawfiles are quite small; and the amount of memory that
  1728. gets wasted at any one time is also small. There’s only likely to be a
  1729. practical problem here if you do complicated recursive things. At the
  1730. moment, that snowflake curve program needs about 280k (the mkdrawf program
  1731. itself being 94k), which I feel is rather excessive. I’ll work on it.
  1732.  
  1733.  
  1734. Variables
  1735. ---------
  1736.  
  1737. ... are stored in a hash table. The way in which all this works has changed
  1738. dramatically between version 2 and version 3; in version 2 there was a fairly
  1739. big global hash table and each macro invocation had its own local hash table,
  1740. whereas now there is a very big global hash table (which, by the way,
  1741. accounts for the increase in size since version 2) and local variables are
  1742. saved and restored as needed.
  1743.  
  1744. The hash scheme used is called the “method of coalescing lists”. I stole it
  1745. from Knuth, and stole his choices of hashing parameters too. In version 2 of
  1746. mkdrawf there were two sorts of local variable token, “resolved” and
  1747. “unresolved”. This distinction no longer exists; in effect, all variables are
  1748. now resolved.
  1749.  
  1750.  
  1751. Problems
  1752. --------
  1753.  
  1754. This is quite a complicated program, and I’m not a very reliable programmer.
  1755. There are bound to be a few bugs left, though I think I’d have spotted
  1756. anything really big. Fortunately, I am both a fast bug-fixer and a helpful
  1757. person; so if you spot any bugs and let me know, I can probably let you have
  1758. a fixed version of mkdrawf pretty quickly.
  1759.  
  1760. Similar remarks apply if you have features to suggest. Of course I don’t
  1761. guarantee to implement every (or any!) feature that is suggested to me, but
  1762. I am always open to suggestions.
  1763.  
  1764.  
  1765. Arbitrary restrictions
  1766. ----------------------
  1767.  
  1768. The following aren’t bugs, but do represent limitations of which you should
  1769. be aware. I don’t guarantee robustness in the event of your violating
  1770. these...
  1771.  
  1772.   • Token lists cannot be nested more than 256 deep; nor (independently)
  1773.     can macros; nor (independently) can Fors; nor (independently) can Ifs.
  1774.   • There must not be more than 2100 global things-with-names. That means
  1775.      • keywords and specials (there are about 100 of these);
  1776.      • global variables;
  1777.      • (names of) local variables;
  1778.      • macros.
  1779.     Before version 3 of mkdrawf, there was a limit of 677 global things
  1780.     and 61 local variables per macro.
  1781.   • A text area may not have more than 16 columns.
  1782.   • The drawfile produced by mkdrawf must be at most 4 megabytes long.
  1783.   • A macro may not use more than 9 positional parameters.
  1784.   • Include files cannot be nested more than 17 deep.
  1785.  
  1786.  
  1787. ----------------------------------------------------------------------------
  1788.  
  1789.  
  1790. Differences from the previous version of mkdrawf
  1791. ================================================
  1792.  
  1793. An earlier version of this program was distributed to a small number of
  1794. people. I have no idea whether it spread any further. The version described
  1795. in this manual is very considerably superior, and if you have been using
  1796. the old version you should change to the new one.
  1797.  
  1798. Unfortunately the two programs are not entirely compatible. They are
  1799. deliberately very similar, but there have had to be a few incompatible
  1800. changes. I think I’ve described them all in this chapter.
  1801.  
  1802. Changes since the transition to version 2 of mkdrawf are documented later,
  1803. in the section entitled “Revision history”.
  1804.  
  1805.  
  1806. Points don’t have commas
  1807. ------------------------
  1808.  
  1809. In the older version, points were entered as (for instance) 200,100. In
  1810. this version the comma is replaced by whitespace. This change was made to
  1811. make it possible for points to be computed using arithmetic and similar
  1812. operations; in the older version of mkdrawf a point was a single token, but
  1813. now each coordinate can be produced separately.
  1814.  
  1815. The same applies to transformation matrices and things, of course.
  1816.  
  1817. As I’ve already mentioned, a similar change may befall colours in a later
  1818. version of mkdrawf.
  1819.  
  1820.  
  1821. Strings have quotation marks
  1822. ----------------------------
  1823.  
  1824. In the older version, a text item might have contained a line like
  1825.   Text This` is` a` zog
  1826. where the backquotes indicated that the spaces following them were to be
  1827. part of the string. On reflection, I decided that this was a dreadful idea,
  1828. especially as I didn’t want to have to make the textual form of each token
  1829. part of the token. (Suppose you wanted a text item whose text was “$foo” or
  1830. something.) So now that would be replaced by
  1831.   Text "This is a zog"
  1832. which, to my mind, is cleaner.
  1833.  
  1834. The same difference affects other strings, such as group names and font names.
  1835.  
  1836.  
  1837. No implicit hexadecimal
  1838. -----------------------
  1839.  
  1840. In the older version, the OtherData in a tagged object were assumed to be given
  1841. in hexadecimal. Now if you want hex you must explicitly mark it as such with 0x.
  1842.  
  1843.  
  1844. ----------------------------------------------------------------------------
  1845.  
  1846.  
  1847. Revision history
  1848. ================
  1849.  
  1850. mkdrawf has been changed a number of times, and will doubtless change more
  1851. in the future. In case you’re curious about what has happened to it (or
  1852. want to see what’s changed since the last version you saw), here is a
  1853. brief account of the changes introduced with each new version. Not all
  1854. of these versions actually correspond to public releases of mkdrawf.
  1855.  
  1856. 2.00    First “new” version of mkdrawf; many incompatible changes in
  1857.     input format; programming features added; manual written.
  1858. 2.10    Sprites and transformed sprites added.
  1859. 2.20    Sprites and transformed sprites can be loaded from sprite files;
  1860.     Include feature; much improved error handling; several minor code
  1861.     changes.
  1862. 2.30    Bounding boxes of paths computed using Draw_ProcessPath instead of
  1863.     by computing bbox of points on path; optional tagfile features;
  1864.     Append, GSTrans features; almost all objects can have explicit
  1865.     BoundingBoxes; numerous bugfixes; code made rather cleaner;
  1866.     decdrawf -s and -v.
  1867. 2.35    Font, Str2Num, Num2Str, HCentreIn, CentreIn, Random features; implicit
  1868.     font tables; colours as triples of integers; JPEG objects; several
  1869.     minor bugfixes and code changes; tutorial written; !Drawf written,
  1870.     and some minor changes made to mkdrawf to support it.
  1871. 3.00    Complete rewrite of macro-expansion code, improving speed and
  1872.     memory use and fixing a serious bug with nested macros. General
  1873.     reorganisation of the source code (now in several files).
  1874.  
  1875.  
  1876. ----------------------------------------------------------------------------
  1877.  
  1878.  
  1879. Decoding drawfiles
  1880. ==================
  1881.  
  1882. With mkdrawf comes another program, called decdrawf, which turns drawfiles
  1883. into descriptions of the sort understood by mkdrawf. This is useful if
  1884. you’ve lost the mkdrawf source code for a drawfile, or if you want to sketch
  1885. something roughly and then tweak it so that all the points are in just the
  1886. right places.
  1887.  
  1888.  
  1889. Using decdrawf
  1890. --------------
  1891.  
  1892. ... is trivial, even easier than using mkdrawf. Just type, say,
  1893.   decdrawf foo
  1894. to get the contents of the drawfile named foo displayed to the screen.
  1895. If you want the output sent to a file, type
  1896.   decdrawf foo > bar
  1897. and the output will be put in a file called bar.
  1898.  
  1899. As with mkdrawf, you can say
  1900.   decdrawf -v
  1901. to get a version number (which will keep in step with the version number of
  1902. mkdrawf, even though one program may change without any change in the other).
  1903. More importantly, you can also request that decdrawf put sprites in a separate
  1904. sprite file rather than “inline” in hexadecimal, by putting -s <filename>
  1905. on the command line. If there are no sprites in the drawfile, the sprite file
  1906. will not be created.
  1907.  
  1908. Warning: A drawfile may contain several copies of one sprite, or (worse)
  1909. several different sprites with the same name. decdrawf will not output
  1910. multiple copies of duplicated sprites to a sprite file; where different
  1911. sprites have the same name, decdrawf will write them all to the sprite file
  1912. as they occur, but will emit warning messages indicating that this is
  1913. happening.
  1914.  
  1915.  
  1916. The output from decdrawf
  1917. ------------------------
  1918.  
  1919. is a file suitable for feeding into mkdrawf. It doesn’t use any macros,
  1920. variables etc, of course. Here and there in the output are comments, which
  1921. are intended to make clearer the correspondence between the data in the
  1922. drawfile and its textual description, or (in, for instance, the case of the
  1923. Options object) to remind you what alterations you could make.
  1924.  
  1925. If you give the -s <filename> option to decdrawf, you will (if there actually
  1926. are any sprites in the drawfile) get two output files. If you change the
  1927. name of the sprite file, you will need to change the relevant FromFiles
  1928. before feeding the result back to mkdrawf. Also, when you use -s you are
  1929. not actually guaranteed that feeding the output into mkdrawf will produce
  1930. the right results; see the warning above.
  1931.  
  1932. If there are JPEG image objects in a drawfile fed to decdrawf it will by
  1933. default include them (in hexadecimal) in the decoded drawfile. This is
  1934. inefficient, and JPEG images are usually rather large; so, instead, put
  1935. -j <prefix> on the command line; this will make decdrawf put JPEG images in
  1936. separate files named prefix01 and so on. decdrawf makes no attempt to avoid
  1937. owerwriting existing files; one consequence of this is that you should be
  1938. careful of truncation problems if a drawfile contains several JPEG images.
  1939.  
  1940. As with mkdrawf, you can get decdrawf not to tell you the filename it’s
  1941. working on in warnings and errors by giving it the option -e.
  1942.  
  1943. You can make decdrawf produce output in terms of units other than points,
  1944. by putting -u <unit> on the command-line. Here unit is one of sp, os, pt,
  1945. mm, cm, in (meaning scaled points, OS units, points, millimetres, centimetres,
  1946. inches). The short names are used here to save typing; the long ones are
  1947. used by mkdrawf to avoid clashing with potentially useful short variable
  1948. names.