|
|
1.1 ! root 1: .so ../ADM/mac ! 2: ....XX pic 53 "Pic \(em A Graphics Language for Typesetting" ! 3: ...\" Wed Sep 24 15:49:34 EDT 1986 ! 4: .de IT ! 5: \\$3\f2\\$1\f1\\$2 ! 6: .. ! 7: .TR 116 ! 8: .ND "Revised, May, 1991 ! 9: .TL ! 10: PIC \(em A Graphics Language for Typesetting ! 11: .br ! 12: User Manual\(dg ! 13: .AU ! 14: Brian W. Kernighan ! 15: .AI ! 16: .MH ! 17: .AB ! 18: .PP ! 19: .IT Pic ! 20: is a language for drawing simple figures ! 21: on a typesetter. ! 22: The basic objects in ! 23: .IT pic ! 24: are ! 25: boxes, ! 26: circles, ! 27: ellipses, ! 28: lines, ! 29: arrows, ! 30: arcs, ! 31: spline curves, ! 32: and text. ! 33: These may be placed anywhere, ! 34: at positions specified absolutely ! 35: or in terms of previous objects. ! 36: The example below illustrates the style and basic capabilities ! 37: of the language. ! 38: .PS ! 39: ellipse "document" ! 40: arrow ! 41: box "PIC" ! 42: arrow ! 43: box "TBL/EQN" "(optional)" dashed ! 44: arrow ! 45: box "TROFF" ! 46: arrow ! 47: ellipse "typesetter" ! 48: .PE ! 49: This picture was created with the input ! 50: .P1 ! 51: \&.PS ! 52: ellipse "document" ! 53: arrow ! 54: box "PIC" ! 55: arrow ! 56: box "TBL/EQN" "(optional)" dashed ! 57: arrow ! 58: box "TROFF" ! 59: arrow ! 60: ellipse "typesetter" ! 61: \&.PE ! 62: .P2 ! 63: .PP ! 64: .IT Pic ! 65: is a ! 66: .IT troff ! 67: preprocessor; ! 68: it passes most of its input through untouched, but translates ! 69: commands between ! 70: .CW .PS ! 71: and ! 72: .CW .PE ! 73: into ! 74: .IT troff ! 75: commands that draw the pictures. ! 76: .AE ! 77: .FS ! 78: \(dg This is a revised version of |reference(pic cstr 116). ! 79: .FE ! 80: .NH ! 81: Introduction ! 82: .PP ! 83: .IT Pic ! 84: is a language for drawing ! 85: pictures. ! 86: It operates as yet another ! 87: .IT troff ! 88: |reference(latest reference troff) ! 89: preprocessor ! 90: (in the same style as ! 91: .IT eqn ! 92: |reference(latest eqn) and ! 93: .IT tbl ! 94: |reference(latest tbl)), ! 95: with pictures delimited by ! 96: .CW .PS ! 97: and ! 98: .CW .PE . ! 99: .PP ! 100: .IT Pic ! 101: was inspired partly by Chris Van Wyk's ! 102: early work on ! 103: .IT ideal ! 104: |reference(ideal acm); ! 105: it has somewhat the same capabilities, ! 106: but quite a different flavor. ! 107: In particular, ! 108: .IT pic ! 109: is much more procedural\(ema picture ! 110: is drawn by specifying (sometimes in painful detail) ! 111: the motions that one goes through to draw it. ! 112: Other direct influences include the PICTURE language ! 113: |reference(beatty picture), ! 114: the V viewgraph language |reference(viewgraph-v), ! 115: and, more recently, new features from the ! 116: .IT grap ! 117: language |reference(bentley kernighan grap) ! 118: for typesetting graphs. ! 119: .PP ! 120: This paper is primarily a user's manual for ! 121: .IT pic ; ! 122: a discussion of design issues and user experience ! 123: may be found in ! 124: |reference(kernighan pic spe). ! 125: The next section shows how to use ! 126: .IT pic ! 127: in the most simple way. ! 128: Subsequent sections describe how to change ! 129: the sizes of objects when the defaults are wrong, ! 130: and how to change their positions when the standard positioning rules ! 131: are wrong. ! 132: An appendix describes the language succinctly and ! 133: summarizes changes since the last manual. ! 134: ......... ! 135: .NH ! 136: Basics ! 137: .PP ! 138: .IT Pic ! 139: provides boxes, lines, arrows, circles, ellipses, arcs, ! 140: and splines (smooth curves), ! 141: plus facilities for positioning ! 142: and labeling them. ! 143: The picture below shows all of the fundamental objects ! 144: (except for splines) ! 145: in their default sizes: ! 146: .PS ! 147: box "box" ! 148: move ! 149: line "line" above ! 150: move ! 151: arrow "arrow" above ! 152: move ! 153: circle "circle" ! 154: move ! 155: ellipse "ellipse" ! 156: move down .25 right ! 157: arc "arc" ! 158: .PE ! 159: Each picture begins with ! 160: .CW .PS ! 161: and ends with ! 162: .CW .PE ; ! 163: between them are commands to describe the picture. ! 164: Each command is typed on a line by itself. ! 165: For example ! 166: .P1 ! 167: \&.PS ! 168: box "this is" "a box" ! 169: \&.PE ! 170: .P2 ! 171: creates a standard box (\(34 inch wide, \(12 inch high) ! 172: and centers the two pieces of text in it: ! 173: .PS ! 174: box "this is" "a box" ! 175: .PE ! 176: .PP ! 177: Each line of text is a separate quoted string. ! 178: Quotes are mandatory, even if the text contains no blanks. ! 179: (Of course there needn't be any text at all.) ! 180: Each line will be ! 181: printed in the current size and font, ! 182: centered horizontally, and separated ! 183: vertically by the current ! 184: .IT troff ! 185: line spacing. ! 186: .IT Pic ! 187: does ! 188: not ! 189: center the complete drawing itself, ! 190: but the default definitions of ! 191: .CW .PS ! 192: and ! 193: .CW .PE ! 194: in the ! 195: .CW -ms ! 196: macro package do. ! 197: .PP ! 198: You can use ! 199: .CW circle ! 200: or ! 201: .CW ellipse ! 202: in place of ! 203: .CW box : ! 204: .PS ! 205: circle "this is" "a box" ! 206: move; move ! 207: ellipse "this is" "a box" ! 208: .PE ! 209: .PP ! 210: Text is centered on lines and arrows; if there is more than one ! 211: line of text, the lines are centered above and below: ! 212: .P1 ! 213: line "this is" "a line" ! 214: .P2 ! 215: .PS ! 216: line "this is" "a line" ! 217: .PE ! 218: .P1 ! 219: arrow "this is" "an arrow" ! 220: .P2 ! 221: .PS ! 222: arrow "this is" "an arrow" ! 223: .PE ! 224: .PP ! 225: Boxes and lines may be dashed or dotted; ! 226: just add the word ! 227: .CW dashed ! 228: or ! 229: .CW dotted ! 230: after ! 231: .CW box ! 232: or ! 233: .CW line : ! 234: .P1 ! 235: line dashed "dashed" "line" ! 236: .P2 ! 237: .PS ! 238: line dashed "dashed" "line" ! 239: .PE ! 240: .PP ! 241: Arcs by default turn 90 degrees counterclockwise from the current direction; ! 242: you can make them turn clockwise by saying ! 243: .CW arc ! 244: .CW cw : ! 245: .P1 ! 246: line; arc; arc cw; arrow ! 247: .P2 ! 248: .PS ! 249: line; arc; arc cw; arrow ! 250: .PE ! 251: A spline might well do this job better; we will return to that shortly. ! 252: .PP ! 253: As you might guess, ! 254: .P1 ! 255: arc; arc; arc; arc ! 256: .P2 ! 257: draws a circle, though not very efficiently. ! 258: Notice that several commands can be put on a single line ! 259: if they are separated by semicolons. ! 260: .PP ! 261: Objects are normally drawn one after another, ! 262: left to right, ! 263: and connected at the obvious places: ! 264: .P1 ! 265: arrow; box "input"; arrow; box "process"; arrow; box "output"; arrow ! 266: .P2 ! 267: .PS ! 268: arrow; box "input"; arrow; box "process"; arrow; box "output"; arrow ! 269: .PE ! 270: One way to leave a space is with ! 271: .CW move : ! 272: .P1 ! 273: box; move; box; move; box ! 274: .P2 ! 275: .PS ! 276: box; move; box; move; box ! 277: .PE ! 278: .PP ! 279: Although objects are normally connected left to right, ! 280: this can be changed. ! 281: If you specify a direction (as a separate object), subsequent objects ! 282: will be joined in that direction: ! 283: .P1 ! 284: down; box; arrow; ellipse; arrow; circle ! 285: .P2 ! 286: .PS ! 287: down; box; arrow; ellipse; arrow; circle ! 288: .PE ! 289: .P1 ! 290: left; box; arrow; ellipse; arrow; circle ! 291: .P2 ! 292: .PS ! 293: left; box; arrow; ellipse; arrow; circle ! 294: .PE ! 295: Each new picture begins going to the right. ! 296: .PP ! 297: Normally, figures are drawn at a fixed scale, ! 298: with objects of a standard size. ! 299: It is possible, however, to arrange that a figure be expanded or shrunk ! 300: to fit a particular width. ! 301: If the ! 302: .CW .PS ! 303: line contains a number, the drawing is forced to be that many inches wide, ! 304: with the height scaled proportionately. ! 305: Thus ! 306: .P1 ! 307: \&.PS 3.5 ! 308: .P2 ! 309: causes the picture to be 3.5 inches wide. ! 310: If two dimensions are specified, the second is the height. ! 311: .PP ! 312: .IT Pic ! 313: is pretty dumb about the size of text in relation ! 314: to the size of boxes, circles, and so on. ! 315: There is no way to say ! 316: ``make a box that just fits around this text'' ! 317: or ``make this text fit inside this circle'' ! 318: or ``draw a line as long as this text.'' ! 319: Tight fitting of text ! 320: can generally only be done by trial and error. ! 321: .PP ! 322: Speaking of errors, ! 323: if you make a grammatical error in the way you describe ! 324: a picture, ! 325: .IT pic ! 326: will complain and try to indicate where. ! 327: For example, the invalid input ! 328: .P1 ! 329: box arrow box ! 330: .P2 ! 331: will draw the message ! 332: .P1 ! 333: pic: syntax error near line 5, file - ! 334: context is ! 335: box >>> arrow <<< box ! 336: .P2 ! 337: The brackets ! 338: point to the place where the error was first noted; ! 339: it sometimes follows ! 340: the word in error, although in this example it's right on target. ! 341: The filename ! 342: .CW - ' ` ! 343: is the standard input. ! 344: .NH ! 345: Controlling Sizes ! 346: .PP ! 347: This section deals with how to ! 348: control the sizes of objects ! 349: when the default sizes are not what is wanted. ! 350: The next section deals with positioning them ! 351: when the default positions are not right. ! 352: .PP ! 353: Each object that ! 354: .IT pic ! 355: knows about ! 356: (boxes, circles, etc.) has ! 357: associated dimensions, like height, width, radius, and so on. ! 358: By default, ! 359: .IT pic ! 360: tries to choose sensible default values for these dimensions, ! 361: so that simple pictures can be drawn with a minimum ! 362: of fuss and bother. ! 363: All of the figures and motions shown so far ! 364: have been in their default sizes: ! 365: .DS ! 366: .ta 1i ! 367: box \(34" wide \(mu \(12" high ! 368: circle \(12" diameter ! 369: ellipse \(34" wide \(mu \(12" high ! 370: arc \(12" radius ! 371: line or arrow \(12" long ! 372: move \(12" in the current direction ! 373: .DE ! 374: .LP ! 375: When necessary, ! 376: you can make any object any size you want: ! 377: .P1 ! 378: box width 3 height 0.1; circle radius 0.1 ! 379: .P2 ! 380: .PS ! 381: box wid 3 ht 0.1; circle radius 0.1 ! 382: .PE ! 383: All positions and dimensions are in inches, so ! 384: the box is 3 inches wide and 1/10 inch high and the circle has radius 1/10 inch. ! 385: .PP ! 386: An attribute like ! 387: .CW width ! 388: changes only the one instance of the object. ! 389: You can also change the default size for all objects ! 390: of a particular type by assigning values to ! 391: .IT pic ! 392: variables; ! 393: this will be discussed in Section 6. ! 394: .PP ! 395: The attributes of ! 396: .CW height ! 397: (which you can abbreviate to ! 398: .CW ht ) ! 399: and ! 400: .CW width ! 401: (or ! 402: .CW wid ) ! 403: apply to boxes, circles, ! 404: ellipses, ! 405: and to the head on an arrow. ! 406: The attributes of ! 407: .CW radius ! 408: (or ! 409: .CW rad ) ! 410: and ! 411: .CW diameter ! 412: (or ! 413: .CW diam ) ! 414: can be used for circles and arcs if they seem more natural. ! 415: .PP ! 416: Lines and arrows are most easily drawn by specifying ! 417: the amount of motion from where you are right now, ! 418: in terms of directions. ! 419: Accordingly the words ! 420: .CW up , ! 421: .CW down , ! 422: .CW left ! 423: and ! 424: .CW right ! 425: and an optional distance can be attached to ! 426: .CW line , ! 427: .CW arrow , ! 428: and ! 429: .CW move : ! 430: .P1 ! 431: line up 1 right 2 ! 432: arrow left 2 ! 433: move left 0.1 ! 434: line <-> down 1 "height " rjust ! 435: .P2 ! 436: .PS ! 437: line up 1 right 2 ! 438: arrow left 2 ! 439: move left 0.1 ! 440: line <-> down 1 "height " rjust ! 441: .PE ! 442: The notation ! 443: .CW <-> ! 444: indicates a two-headed arrow; ! 445: use ! 446: .CW -> ! 447: for a head on the end and ! 448: .CW <- ! 449: for one on the start. ! 450: Lines and arrows are really the same thing; ! 451: in fact, ! 452: .CW arrow ! 453: is a synonym for ! 454: .CW line ! 455: .CW -> . ! 456: .PP ! 457: If you don't specify any distance after ! 458: .CW up , ! 459: .CW down , ! 460: etc., ! 461: .IT pic ! 462: uses the standard distance: ! 463: .P1 ! 464: line up right; line down; line down left; line up ! 465: .P2 ! 466: .PS ! 467: line up right; line down; line down left; line up ! 468: .PE ! 469: If you omit the direction associated with a distance, ! 470: the current direction is used. ! 471: .PP ! 472: Boxes and lines may be dotted or dashed: ! 473: .P1 ! 474: box dotted; line dotted; move; line dashed; box dashed ! 475: .P2 ! 476: .PS ! 477: box dotted; line dotted; move; line dashed; box dashed ! 478: .PE ! 479: If there is a number after ! 480: .CW dot , ! 481: the dots will be approximately that far apart. ! 482: You can also control the size of the dashes (at least somewhat): ! 483: if there is a length after the word ! 484: .CW dashed , ! 485: the dashes will be that long, ! 486: and the intervening spaces will be as close as possible to that size: ! 487: .P1 ! 488: line right 5 dashed; move left 5 down .25; right ! 489: line right 5 dashed 0.25; move left 5 down .25; right ! 490: line right 5 dashed 0.5; move left 5 down .25; right ! 491: line right 5 dashed 1 ! 492: .P2 ! 493: .PS ! 494: line right 5 dashed; move left 5 down .25; right ! 495: line right 5 dashed 0.25; move left 5 down .25; right ! 496: line right 5 dashed 0.5; move left 5 down .25; right ! 497: line right 5 dashed 1 ! 498: .PE ! 499: Dotted or dashed attributes apply only to lines and boxes. ! 500: .LP ! 501: .PP ! 502: You can make any object invisible by adding the word ! 503: .CW invis ! 504: after it. ! 505: This is particularly useful for positioning things correctly ! 506: near text: ! 507: .P1 ! 508: box invis "input"; arrow; box invis "output" ! 509: .P2 ! 510: .PS ! 511: box invis "input"; arrow; box invis "output" ! 512: .PE ! 513: .PP ! 514: Text may be positioned on lines and arrows: ! 515: .P1 ! 516: arrow "on top of"; move ! 517: arrow "above" "below"; move ! 518: arrow "above" above; move ! 519: arrow "below" below; move ! 520: arrow "above" "on top of" "below" ! 521: .P2 ! 522: .PS ! 523: arrow "on top of"; move ! 524: arrow "above" "below"; move ! 525: arrow "above" above; move ! 526: arrow "below" below; move ! 527: arrow "above" "on top of" "below" ! 528: .PE ! 529: .LP ! 530: .PP ! 531: The ``width'' of an arrowhead is the distance across ! 532: its tail; ! 533: the ``height'' is the distance along the shaft. ! 534: The arrowheads in this picture are default size and shape. ! 535: .PP ! 536: As we said earlier, arcs go 90 degrees counterclockwise ! 537: from where you are right now, and ! 538: .CW arc ! 539: .CW cw ! 540: changes this to clockwise. ! 541: The default radius is the same as for circles, ! 542: but you can change it with the ! 543: .CW rad ! 544: attribute. ! 545: It is also easy to draw arcs between specific places; ! 546: this will be described in the next section. ! 547: .PP ! 548: To put an arrowhead on an arc, use one of ! 549: .CW <- , ! 550: .CW -> ! 551: or ! 552: .CW <-> , ! 553: as with lines. ! 554: .LP ! 555: .PP ! 556: In all cases, ! 557: unless an explicit dimension for some object is specified, ! 558: you will get the default size. ! 559: If you want an object to have the same size ! 560: as the previous one of that kind, ! 561: add the word ! 562: .CW same . ! 563: Thus ! 564: in the set of boxes given by ! 565: .P1 ! 566: down; box ht 0.2 wid 1.5; move down 0.15; box same; move same; box same ! 567: .P2 ! 568: .PS ! 569: down; box ht 0.2 wid 1.5; move down 0.15; box same; move same; box same ! 570: .PE ! 571: the dimensions set by the first ! 572: .CW box ! 573: are used several times; ! 574: similarly, the amount of motion for the second ! 575: .CW move ! 576: is the same as for the first one. ! 577: .PP ! 578: You can change the default sizes of objects ! 579: by assigning values to the variables that define their values. ! 580: Here is the list, with their default values: ! 581: .P1 ! 582: .ta 2i 3.3i ! 583: boxwid = 0.75; boxht = 0.5 ! 584: linewid = 0.75; lineht = 0.5 ! 585: circlerad = 0.25; arcrad = 0.25 ! 586: ellipsewid = 0.75; ellipseht = 0.5 ! 587: movewid = 0.75; moveht = 0.5 ! 588: textwid = 0; textht = 0 ! 589: arrowwid = 0.05; arrowht = 0.1 \f1(These refer to the arrowhead.)\fP ! 590: dashwid = 0.05; arrowhead = 2 \f1(Arrowhead fill style)\fP ! 591: maxpsht = 8.5; maxpswid = 11 \f1(Maximum picture dimensions)\fP ! 592: fillval = 0.3; scale = 1 ! 593: .P2 ! 594: So if you want all your boxes to be long and skinny, and relatively close together, ! 595: .P1 ! 596: boxwid = 0.1; boxht = 1 ! 597: movewid = 0.2 ! 598: box; move; box; move; box ! 599: .P2 ! 600: .PS ! 601: boxwid = 0.1; boxht = 1 ! 602: movewid = 0.2 ! 603: box; move; box; move; box ! 604: .PE ! 605: .nf ! 606: .PS ! 607: x = boxwid ! 608: y = boxht ! 609: boxwid = 0.1 ! 610: boxht = 1 ! 611: movewid = 0.2 ! 612: boxwid = x ! 613: boxht = y ! 614: arrowhead = 7 ! 615: arrowhead = 2 ! 616: .PE ! 617: .PP ! 618: Setting the variable ! 619: .CW arrowhead ! 620: to a value like 7 causes arrowheads to be filled by overstriking; ! 621: the default is 2: ! 622: .P1 ! 623: arrowhead = 7; arrow; move; arrowhead = 2; arrow ! 624: .P2 ! 625: .PS ! 626: arrowhead = 7; arrow; move; arrowhead = 2; arrow ! 627: .PE ! 628: .PP ! 629: .IT Pic ! 630: works internally in inches. ! 631: Setting the variable ! 632: .CW scale ! 633: to some value causes all dimensions to be scaled down ! 634: by that value. ! 635: Thus, for example, ! 636: .CW scale=2.54 ! 637: causes dimensions to be interpreted as centimeters. ! 638: .PP ! 639: The numbers given in the ! 640: .CW .PS ! 641: line override the dimensions given in the picture; ! 642: these can be used to force a picture to a particular width and height. ! 643: Experience indicates that a good way to get a picture ! 644: of the right size is to enter its dimensions in inches, ! 645: then if necessary add a width and perhaps height to the ! 646: .CW .PS ! 647: line. ! 648: .PP ! 649: Once set, variables like ! 650: .CW boxht ! 651: retain their values from one picture to the next. ! 652: You can reset variables to their default values by listing them in a ! 653: .CW reset ! 654: statement: ! 655: .P1 ! 656: reset boxht, boxwid ! 657: .P2 ! 658: A bare ! 659: .CW reset ! 660: resets all variables. ! 661: .PP ! 662: There is a minimal facility for filling or shading objects, ! 663: intended for Postscript output devices. ! 664: The attribute ! 665: .CW fill ! 666: .IT expr ! 667: sets the gray scale value to ! 668: .IT expr ; ! 669: the default, determined by the variable ! 670: .CW fillval , ! 671: is 0.3. ! 672: Following Postscript, smaller values are darker. ! 673: Thus: ! 674: .P1 ! 675: box fill ! 676: box ht boxht/2 wid boxwid/2 "hello" at last box ! 677: .P2 ! 678: .PS ! 679: reset ! 680: box fill ! 681: box ht boxht/2 wid boxwid/2 "hello" at last box ! 682: .PE ! 683: .CW fill ! 684: currently only applies to boxes, circles, and ellipses. ! 685: .NH ! 686: Controlling Positions ! 687: .PP ! 688: You can place things anywhere you want; ! 689: .IT pic ! 690: provides a variety of ways to talk about positions. ! 691: .IT Pic ! 692: uses a standard Cartesian coordinate system with ! 693: .IT x ! 694: increasing rightwards and ! 695: .IT y ! 696: increasing upwards, ! 697: so any point or object has an ! 698: .IT x ! 699: and ! 700: .IT y ! 701: position, measured in inches. ! 702: The first object is placed with its start at position 0,0 by default. ! 703: The ! 704: .IT x,y ! 705: position of a box, circle or ellipse is its geometric center; ! 706: the position of a line or spline or motion is its beginning; ! 707: the position of an arc is the center of the corresponding circle. ! 708: .PP ! 709: Position modifiers like ! 710: .CW from , ! 711: .CW to , ! 712: .CW by ! 713: and ! 714: .CW at ! 715: are followed by an ! 716: .IT x,y ! 717: pair, and ! 718: can be attached to boxes, circles, lines, motions, and so on, ! 719: to specify or modify a position. ! 720: .PP ! 721: You can also use ! 722: .CW up , ! 723: .CW down , ! 724: .CW right , ! 725: and ! 726: .CW left ! 727: with ! 728: .CW line ! 729: and ! 730: .CW move : ! 731: .P1 ! 732: box ht 0.2 wid 0.2 at 0,0 "1" ! 733: move right 0.5 # or "move to 0.5,0" ! 734: box ht 0.2 wid 0.2 "2" ! 735: move right 0.5 # or "move 0.5" or "move same" ! 736: box ht 0.2 wid 0.2 "3" ! 737: .P2 ! 738: .PS 2 ! 739: box ht 0.2 wid 0.2 at 0,0 "1" ! 740: move right 0.5 # or "move to 0.5,0" ! 741: box ht 0.2 wid 0.2 "2" ! 742: move right 0.5 ! 743: box ht 0.2 wid 0.2 "3" ! 744: .PE ! 745: Comments can be used in pictures; ! 746: they begin with a ! 747: .CW # ! 748: and end at the end of the line. ! 749: .PP ! 750: Attributes like ! 751: .CW ht ! 752: and ! 753: .CW wid ! 754: and positions like ! 755: .CW at ! 756: can be written out in any order. ! 757: So ! 758: .P1 ! 759: box ht 0.2 wid 0.2 at 0,0 ! 760: box at 0,0 wid 0.2 ht 0.2 ! 761: box ht 0.2 at 0,0 wid 0.2 ! 762: .P2 ! 763: are all equivalent, though the last is harder to read ! 764: and thus less desirable. ! 765: .PP ! 766: The ! 767: .CW from ! 768: and ! 769: .CW to ! 770: attributes are particularly useful with arcs, ! 771: to specify the endpoints. ! 772: By default, arcs are drawn counterclockwise, ! 773: .P1 ! 774: "+" at 0,0 ! 775: arc -> from 0.5,0 to 0,0.5 ! 776: arc -> cw from 0,0 to 1,0.5 ! 777: .P2 ! 778: .PS ! 779: "+" at 0,0 ! 780: arc -> from 0.5,0 to 0,0.5 ! 781: arc -> cw from 0,0 to 1,0.5 ! 782: .PE ! 783: The radius can be made large to provide flat arcs: ! 784: .P1 ! 785: arc -> cw from 0,0 to 2,0 rad 15 ! 786: .P2 ! 787: .PS ! 788: arc -> cw from 0,0 to 2,0 rad 15 ! 789: .PE ! 790: If the circle is under-specified, ! 791: .IT pic ! 792: guesses a radius and/or center; ! 793: you will have to provide them explicitly if the guess is wrong. ! 794: .LP ! 795: .PP ! 796: We said earlier that ! 797: objects are normally connected left to right. ! 798: This is an over-simplification. ! 799: The truth is that objects are connected together ! 800: in the direction specified by the most recent ! 801: .CW up , ! 802: .CW down , ! 803: .CW left ! 804: or ! 805: .CW right ! 806: (either alone or as part of some object). ! 807: Thus, in ! 808: .P1 ! 809: arrow left; box; arrow; circle; arrow ! 810: .P2 ! 811: the ! 812: .CW left ! 813: implies connection towards the left: ! 814: .PS ! 815: arrow left; box; arrow; circle; arrow ! 816: .PE ! 817: This could also be written as ! 818: .P1 ! 819: left; arrow; box; arrow; circle; arrow ! 820: .P2 ! 821: .PP ! 822: Objects are joined in the direction determined by the last ! 823: .CW up , ! 824: .CW down , ! 825: etc., with the entry point of the second object attached ! 826: to the exit point of the first ! 827: (which is fixed at the time of entry). ! 828: Entry and exit points for boxes, circles and ellipses are ! 829: on opposite sides. ! 830: This automatic connection and direction selection ! 831: works well if the direction doesn't change but it will occasionally surprise you: ! 832: .P1 ! 833: arrow; circle; down; arrow ! 834: .P2 ! 835: .PS ! 836: arrow; circle; down; arrow ! 837: .PE ! 838: The arrow comes out of the right side of the circle, not the bottom, ! 839: as might be expected. ! 840: .PP ! 841: If a set of commands is enclosed in braces ! 842: .CW {...} , ! 843: the current position and direction of motion when the group is finished ! 844: will be exactly where it was when entered. ! 845: Nothing else is restored. ! 846: There is also a more general way to group objects, ! 847: using ! 848: .CW [ ! 849: and ! 850: .CW ] , ! 851: which is discussed in Section 9. ! 852: .NH ! 853: Labels and Corners ! 854: .PP ! 855: Objects can be labelled or named so that you can talk about them later. ! 856: For example, ! 857: .P1 ! 858: Box1: box ! 859: # ... other stuff ... ! 860: move to Box1 ! 861: .P2 ! 862: Place names ! 863: .IT must ! 864: begin with an upper case letter ! 865: (to distinguish them from variable names, ! 866: which begin with lower case letters). ! 867: The name refers to the ``center'' ! 868: of the object, ! 869: which is the geometric center for most things. ! 870: .PP ! 871: Other combinations also work: ! 872: .P1 ! 873: line from Box1 to Box2 ! 874: move to Box1 up 0.1 right 0.2 ! 875: move to Box1 + 0.2,0.1 # same as previous ! 876: line to Box1 - 0.5,0 ! 877: .P2 ! 878: The reserved name ! 879: .CW Here ! 880: may be used to refer to the current position. ! 881: .PP ! 882: Labels can be reset several times in a single picture, ! 883: so a statement like ! 884: .P1 ! 885: Box1: Box1 + 1,1 ! 886: .P2 ! 887: is perfectly legal. ! 888: .LP ! 889: .PP ! 890: You can also refer to previously drawn objects of each type, ! 891: using the word ! 892: .CW last . ! 893: For example, given the input ! 894: .P1 ! 895: box "A"; circle "B"; box "C" ! 896: .P2 ! 897: then ! 898: .CW last \& ` ! 899: .CW box ' ! 900: refers to box ! 901: .CW C , ! 902: .CW last \& ` ! 903: .CW circle ' ! 904: refers to circle ! 905: .CW B , ! 906: and ! 907: .CW 2nd \& ` ! 908: .CW last ! 909: .CW box ' ! 910: refers to box ! 911: .CW A . ! 912: Numbering of objects can also be done from the beginning, ! 913: so boxes ! 914: .CW A ! 915: and ! 916: .CW C ! 917: are ! 918: .CW 1st \& ` ! 919: .CW box ' ! 920: and ! 921: .CW 2nd \& ` ! 922: .CW box ' ! 923: respectively. ! 924: .PP ! 925: To cut down the need for explicit coordinates, ! 926: objects have ``corners'' named by compass points: ! 927: .P1 ! 928: B: box "B.c" ht 1 wid 1.5 ! 929: " B.e" at B.e ljust ! 930: " B.ne" at B.ne ljust ! 931: " B.se" at B.se ljust ! 932: "B.s" at B.s below ! 933: "B.n" at B.n above ! 934: "B.sw " at B.sw rjust ! 935: "B.w " at B.w rjust ! 936: "B.nw " at B.nw rjust ! 937: .P2 ! 938: .PS ! 939: B: box "B.c" ht 1 wid 1.5 ! 940: " B.e" at B.e ljust ! 941: " B.ne" at B.ne ljust ! 942: " B.se" at B.se ljust ! 943: "B.s" at B.s below ! 944: "B.n" at B.n above ! 945: "B.sw " at B.sw rjust ! 946: "B.w " at B.w rjust ! 947: "B.nw " at B.nw rjust ! 948: .PE ! 949: Note the use of ! 950: .CW ljust , ! 951: .CW rjust , ! 952: .CW above , ! 953: and ! 954: .CW below ! 955: to alter the default positioning of text, ! 956: and of a blank within some strings to help space them away from a vertical line. ! 957: .PP ! 958: Lines and arrows have a ! 959: .CW start , ! 960: an ! 961: .CW end ! 962: and a ! 963: .CW center ! 964: in addition to corners. ! 965: Circles and ellipses have corners too; ! 966: an arc has the same corners as the circle of which it is a part. ! 967: The words ! 968: .CW left , ! 969: .CW right , ! 970: .CW top , ! 971: and ! 972: .CW bottom ! 973: are synonyms for ! 974: .CW west , ! 975: .CW east , ! 976: .CW north ! 977: and ! 978: .CW south . ! 979: .PP ! 980: It is often easiest to position objects by positioning ! 981: some part of one at some part of another, ! 982: for example the southwest corner of one at the southeast corner ! 983: of another. ! 984: The ! 985: .CW with ! 986: attribute ! 987: permits this kind of positioning: ! 988: .P1 ! 989: box ht 0.75 wid 0.75 ! 990: box ht 0.5 wid 0.5 with .sw at last box.se ! 991: .P2 ! 992: .PS ! 993: box ht 0.75 wid 0.75 ! 994: box ht 0.5 wid 0.5 with .sw at last box.se ! 995: .PE ! 996: Notice that the corner after ! 997: .CW with ! 998: is written ! 999: .CW .sw . ! 1000: .PP ! 1001: As another example, consider ! 1002: .P1 ! 1003: ellipse ! 1004: ellipse ht .2 wid .3 with .se at 1st ellipse.nw ! 1005: ellipse ht .2 wid .3 with .sw at 1st ellipse.ne ! 1006: .P2 ! 1007: .PS ! 1008: ellipse ! 1009: ellipse ht .2 wid .3 with .se at 1st ellipse.nw ! 1010: ellipse ht .2 wid .3 with .sw at 1st ellipse.ne ! 1011: .PE ! 1012: .LP ! 1013: .PP ! 1014: Sometimes it is desirable to have a line intersect a circle ! 1015: at a point which is not one of the eight compass points ! 1016: that ! 1017: .IT pic ! 1018: knows about. ! 1019: In such cases, the proper visual effect can be obtained by using ! 1020: the attribute ! 1021: .CW chop ! 1022: to chop off part of the line: ! 1023: .P1 ! 1024: circlerad = 0.15; arrowhead = 7 ! 1025: circle "a" ! 1026: circle "b" at 1st circle - (0.4, 0.6) ! 1027: circle "c" at 1st circle + (0.4, -0.6) ! 1028: arrow from 1st circle to 2nd circle chop ! 1029: arrow from 1st circle to 3rd circle chop ! 1030: .P2 ! 1031: .PS ! 1032: circlerad = 0.15; arrowhead = 7 ! 1033: circle "a" ! 1034: circle "b" at 1st circle - (0.4, 0.6) ! 1035: circle "c" at 1st circle + (0.4, -0.6) ! 1036: arrow from 1st circle to 2nd circle chop ! 1037: arrow from 1st circle to 3rd circle chop ! 1038: reset ! 1039: .PE ! 1040: By default the line is chopped by ! 1041: .CW circlerad ! 1042: at each end. ! 1043: This may be changed: ! 1044: .P1 ! 1045: line ... chop \f2r\fP ! 1046: .P2 ! 1047: chops both ends by ! 1048: \f2r\fP, and ! 1049: .P1 ! 1050: line ... chop \f2r1\fP chop \f2r2\fP ! 1051: .P2 ! 1052: chops the beginning by ! 1053: .IT r1 ! 1054: and the end by ! 1055: .IT r2 . ! 1056: More complicated intersections can be computed with ! 1057: the built-in trigonometric functions listed in the next section. ! 1058: .PP ! 1059: There is one other form of positioning that is sometimes useful, ! 1060: to refer to a point some fraction of the way between ! 1061: two other points. ! 1062: This can be expressed in ! 1063: .IT pic ! 1064: as ! 1065: .P1 ! 1066: \f2fraction\fP of the way between \f2position1\fP and \f2position2\fP ! 1067: .P2 ! 1068: where ! 1069: .IT fraction ! 1070: is any expression, and ! 1071: .IT position1 ! 1072: and ! 1073: .IT position2 ! 1074: are any positions. ! 1075: You can abbreviate this rather windy phrase; ! 1076: ``of the way'' is optional, and the whole thing can ! 1077: be written instead as ! 1078: .P1 ! 1079: \f2fraction\fP < \f2position1\fP , \f2position2\fP > ! 1080: .P2 ! 1081: As a pair of examples: ! 1082: .P1 ! 1083: box ! 1084: arrow right from 1/3 of the way between last box.ne and last box.se ! 1085: arrow right from 2/3 <last box.ne, last box.se> ! 1086: .P2 ! 1087: .PS ! 1088: box ! 1089: arrow right from 1/3 of the way between last box.ne and last box.se ! 1090: arrow right from 2/3 <last box.ne, last box.se> ! 1091: .PE ! 1092: .P1 ! 1093: A: ellipse ! 1094: ellipse ht .2 wid .3 with .se at 1st ellipse.nw ! 1095: ellipse ht .2 wid .3 with .sw at 1st ellipse.ne ! 1096: circle rad .05 at 0.5 <A.nw,A.c> ! 1097: circle rad .05 at 0.5 <A.ne,A.c> ! 1098: arc from 0.25 <A.w,A.e> to 0.75 <A.w,A.e> ! 1099: .P2 ! 1100: .PS ! 1101: A: ellipse ! 1102: ellipse ht .2 wid .3 with .se at 1st ellipse.nw ! 1103: ellipse ht .2 wid .3 with .sw at 1st ellipse.ne ! 1104: circle rad .05 at 0.5 <A.nw,A.c> ! 1105: circle rad .05 at 0.5 <A.ne,A.c> ! 1106: arc from 0.25 <A.w,A.e> to 0.75 <A.w,A.e> ! 1107: .PE ! 1108: Naturally, ! 1109: the distance given by ! 1110: .IT fraction ! 1111: can be greater than 1 or less than 0. ! 1112: .PP ! 1113: Advice:\ ! 1114: experience suggests that the easiest way to position objects ! 1115: is by placing them relative to previous objects ! 1116: and places, using ! 1117: .CW with , ! 1118: .CW at , ! 1119: etc. ! 1120: This is better than using ! 1121: .CW move ; ! 1122: you should generally avoid ! 1123: .CW move . ! 1124: .NH ! 1125: Variables, Expressions and Built-in Functions ! 1126: .PP ! 1127: It's generally a bad idea to write everything in ! 1128: absolute coordinates if you are likely ! 1129: to change things. ! 1130: .IT Pic ! 1131: variables let you parameterize your picture: ! 1132: .P1 ! 1133: a = 0.5; b = 1 ! 1134: ! 1135: box wid a ht b ! 1136: ellipse wid a/2 ht 1.5*b ! 1137: Box2: Box1 - (a/2, b/2) ! 1138: .P2 ! 1139: Expressions may use the standard operators ! 1140: .CW + , ! 1141: .CW - , ! 1142: .CW * , ! 1143: .CW / , ! 1144: .CW % , ! 1145: .CW ^ ! 1146: (exponentiation), ! 1147: and parentheses for grouping. ! 1148: .PP ! 1149: The most important variables are the predefined ones for ! 1150: controlling the default sizes of objects, ! 1151: listed in Section 3. ! 1152: These may be set at any time in any picture, ! 1153: and retain their values from picture to picture until reset. ! 1154: .PP ! 1155: You can use the height, width, radius, ! 1156: and ! 1157: .IT x ! 1158: and ! 1159: .IT y ! 1160: coordinates of any object or corner in an expression: ! 1161: .P1 ! 1162: Box1.x # the \f2x\fP coordinate of the center of Box1 ! 1163: Box1.ne.y # the \f2y\fP coordinate of the northeast corner of Box1 ! 1164: Box1.wid # the width of Box1 ! 1165: Box1.ht # and its height ! 1166: 2nd last circle.rad # the radius of the 2nd last circle ! 1167: .P2 ! 1168: .PP ! 1169: Any pair of expressions enclosed in parentheses ! 1170: defines a position; furthermore such positions ! 1171: can be added or subtracted to yield new positions: ! 1172: .EQ ! 1173: delim $$ ! 1174: define cw X font CW X ! 1175: .EN ! 1176: .P1 ! 1177: (\f2x\fP, \f2y\fP) ! 1178: ($x sub 1$, $y sub 1$) + ($x sub 2$, $y sub 2$) ! 1179: .P2 ! 1180: If $p sub 1$ and $p sub 2$ are positions, then ! 1181: $( p sub 1 , p sub 2 )$ ! 1182: refers to the point ! 1183: $( p sub 1 font CW .x ,~ p sub 2 font CW .y )$. ! 1184: .PP ! 1185: .IT Pic ! 1186: provides a small collection of standard functions: ! 1187: .DS ! 1188: .ta 3i ! 1189: $cw "sin" (expr)$, $cw "cos" (expr)$, $cw atan2 (y,x)$ (angle in radians) ! 1190: $cw "log" (expr)$, $cw "exp" (expr)$ (Beware: both base 10) ! 1191: $cw "sqrt" (expr)$, $cw "max" (e sub 1 , e sub 2 )$, $cw "min" (e sub 1 , e sub 2 )$ ! 1192: $cw "int" (expr)$ (integer part of $expr$) ! 1193: $cw rand ()$ (random number between 0 and 1) ! 1194: .DE ! 1195: .EQ ! 1196: delim off ! 1197: .EN ! 1198: .NH ! 1199: More on Text ! 1200: .PP ! 1201: Normally, text is centered ! 1202: at the geometric center of the object it is associated with. ! 1203: The attribute ! 1204: .CW ljust ! 1205: causes the left end to be at the specified point ! 1206: (which means that the text lies to the right of the specified place!), ! 1207: and ! 1208: .CW rjust ! 1209: puts the right end at the place. ! 1210: .CW above ! 1211: and ! 1212: .CW below ! 1213: center the text one half line space in the given direction. ! 1214: .PP ! 1215: Text attributes can be compounded: ! 1216: .P1 ! 1217: arrow 1 "ljust above" ljust above ! 1218: .P2 ! 1219: .PS ! 1220: arrow 1 "ljust above" ljust above ! 1221: .PE ! 1222: .LP ! 1223: .PP ! 1224: Text is most often an attribute of some other object, ! 1225: but you can also have self-standing text: ! 1226: .P1 ! 1227: "origin" "(0,0)" at 0,0 ! 1228: "this is" "(1,1)" at 1,1 ! 1229: box ht 1 wid 1 dotted with .sw at 0,0 ! 1230: .P2 ! 1231: .PS ! 1232: "origin" "(0,0)" at 0,0 ! 1233: "this is" "(1,1)" at 1,1 ! 1234: box ht 1 wid 1 dotted with .sw at 0,0 ! 1235: .PE ! 1236: .LP ! 1237: In effect, \f2n\fP text strings are contained in an invisible box ! 1238: of width ! 1239: .CW textwid ! 1240: and height \f2n\fP \(mu ! 1241: .CW textht . ! 1242: The variables ! 1243: .CW textwid ! 1244: and ! 1245: .CW textht ! 1246: may be set to any values; ! 1247: they are normally zero. ! 1248: .PP ! 1249: A list of numeric expressions can be converted to a formatted string ! 1250: with the ! 1251: .CW sprintf ! 1252: function and used anywhere a quoted string can be: ! 1253: .P1 ! 1254: B: box wid log(20) ! 1255: sprintf("width = %g, height = %g ", B.wid, B.ht) rjust at B.w ! 1256: .P2 ! 1257: .PS ! 1258: B: box wid log(20) ! 1259: sprintf("width = %g, height = %g ", B.wid, B.ht) rjust at B.w ! 1260: .PE ! 1261: ....... ! 1262: .NH ! 1263: Lines and Splines ! 1264: .PP ! 1265: A ``line'' may actually be a path, ! 1266: that is, it may consist of connected segments: ! 1267: .P1 ! 1268: line right 1 then down .5 left 1 then right 1 ! 1269: .P2 ! 1270: .PS ! 1271: line right 1 then down .5 left 1 then right 1 ! 1272: .PE ! 1273: The word ! 1274: .CW then ! 1275: separates components of the path. ! 1276: .PP ! 1277: A spline is a smooth curve guided by a set of straight lines ! 1278: just like the line above. ! 1279: It begins at the same place, ends at the same place, ! 1280: and in between is tangent to the mid-point of each guiding line. ! 1281: The syntax for a spline is identical to a (path) line ! 1282: except for using ! 1283: .CW spline ! 1284: instead of ! 1285: .CW line : ! 1286: .P1 ! 1287: line dashed right 1 then down .5 left 1 then right 1 ! 1288: spline from start of last line \e ! 1289: right 1 then down .5 left 1 then right 1 ! 1290: .P2 ! 1291: .PS ! 1292: line dashed right 1 then down .5 left 1 then right 1 ! 1293: spline from start of last line \ ! 1294: right 1 then down .5 left 1 then right 1 ! 1295: .PE ! 1296: (Long input lines can be split by ending each piece ! 1297: with a backslash.) ! 1298: .PP ! 1299: The elements of a path, whether line or spline, ! 1300: are specified as a series of points, ! 1301: either in absolute terms or by ! 1302: .CW up , ! 1303: .CW down , ! 1304: etc. ! 1305: .P1 ! 1306: spline right then up then left then down -> ! 1307: .P2 ! 1308: .PS ! 1309: spline right then up then left then down -> ! 1310: .PE ! 1311: .P1 ! 1312: spline right then up left then down -> ! 1313: .P2 ! 1314: .PS ! 1315: spline right then up left then down -> ! 1316: .PE ! 1317: .PP ! 1318: Notice that arrowheads may be put on the ends ! 1319: of a line or spline. ! 1320: .NH ! 1321: Blocks ! 1322: .PP ! 1323: Any sequence of ! 1324: .IT pic ! 1325: statements may be enclosed in ! 1326: brackets ! 1327: .CW [ ! 1328: and ! 1329: .CW ] ! 1330: to form ! 1331: a block, ! 1332: which can then be treated as a single object, ! 1333: and manipulated rather like an ordinary box: ! 1334: .P1 ! 1335: box "1" ! 1336: [ box "2"; arrow "3" above; box "4" ] with .n at last box.s - (0,0.1) ! 1337: "Thing 2: " rjust at last [].w ! 1338: .P2 ! 1339: .PS ! 1340: box "1" ! 1341: [ box "2"; arrow "3" above; box "4" ] with .n at last box.s - (0,0.1) ! 1342: "Thing 2: " rjust at last [].w ! 1343: .PE ! 1344: Notice that ! 1345: ``last''-type constructs treat blocks as a unit and don't look ! 1346: inside for objects: ! 1347: .CW last "" `` ! 1348: .CW box.s '' ! 1349: refers to box 1, not box 2 or 4. ! 1350: You can use ! 1351: .CW last\ [] , ! 1352: etc., ! 1353: just like ! 1354: .CW last\ box . ! 1355: .PP ! 1356: Blocks have the same compass corners as ! 1357: boxes (determined by the bounding box). ! 1358: It is also ! 1359: possible to position a block by placing either an absolute ! 1360: coordinate (like ! 1361: .CW 0,0 ) ! 1362: or an internal label (like ! 1363: .CW A ) ! 1364: at some ! 1365: external point, as in ! 1366: .P1 ! 1367: [ ...; A: ...; ... ] with .A at ... ! 1368: .P2 ! 1369: By default, blocks join with other things as boxes do, at the ! 1370: center of the appropriate side. ! 1371: .PP ! 1372: Names of variables and places within a block are local ! 1373: to that block, and thus do not affect variables and places ! 1374: of the same name outside. ! 1375: (In particular, that includes the built-in variables like ! 1376: .CW boxwid , ! 1377: etc.; ! 1378: if they are set within a block, ! 1379: they revert to their original values when the block is left.) ! 1380: You can get at the internal ! 1381: place names with constructs like ! 1382: .P1 ! 1383: last [].A ! 1384: .P2 ! 1385: or ! 1386: .P1 ! 1387: B.A ! 1388: .P2 ! 1389: where ! 1390: .CW B ! 1391: is a name attached to a block: ! 1392: .P1 ! 1393: B: [ ... ; A: ...; ] ! 1394: .P2 ! 1395: When combined with ! 1396: .CW define ! 1397: statements (next section), blocks provide ! 1398: a reasonable simulation of a procedure mechanism. ! 1399: .PP ! 1400: Although blocks nest, ! 1401: it is currently possible to look only one level deep ! 1402: with constructs like ! 1403: .CW B.A , ! 1404: although ! 1405: .CW A ! 1406: may be ! 1407: further qualified by a corner name (i.e., ! 1408: .CW B.A.sw ! 1409: or ! 1410: .CW top ! 1411: .CW of ! 1412: .CW B.A ! 1413: are legal). ! 1414: .PP ! 1415: The following example illustrates most of the points made above ! 1416: about how blocks work: ! 1417: .P1 ! 1418: h = .5; dh = .02; dw = .1 ! 1419: [ ! 1420: Ptr: [ ! 1421: boxht = h; boxwid = dw ! 1422: A: box ! 1423: B: box ! 1424: C: box ! 1425: box wid 2*boxwid "..." ! 1426: D: box ! 1427: ] ! 1428: Block: [ ! 1429: boxht = 2*dw; boxwid = 2*dw ! 1430: movewid = 2*dh ! 1431: A: box; move ! 1432: B: box; move ! 1433: C: box; move ! 1434: box invis "..." wid 2*boxwid; move ! 1435: D: box ! 1436: ] with .t at Ptr.s - (0,h/2) ! 1437: arrow from Ptr.A to Block.A.nw + (dh,0) ! 1438: arrow from Ptr.B to Block.B.nw + (dh,0) ! 1439: arrow from Ptr.C to Block.C.nw + (dh,0) ! 1440: arrow from Ptr.D to Block.D.nw + (dh,0) ! 1441: ] ! 1442: box dashed ht last [].ht+dw wid last [].wid+dw at last [] ! 1443: .P2 ! 1444: This produces ! 1445: .PS ! 1446: h = .5 ! 1447: dh = .02 ! 1448: dw = .1 ! 1449: [ ! 1450: Ptr: [ ! 1451: boxht = h; boxwid = dw ! 1452: A: box ! 1453: B: box ! 1454: C: box ! 1455: box wid 2*boxwid "..." ! 1456: D: box ! 1457: ] ! 1458: Block: [ ! 1459: boxht = 2*dw; boxwid = 2*dw ! 1460: movewid = 2*dh ! 1461: A: box; move ! 1462: B: box; move ! 1463: C: box; move ! 1464: box invis "..." wid 2*boxwid; move ! 1465: D: box ! 1466: ] with .t at Ptr.s - (0,h/2) ! 1467: arrow from Ptr.A to Block.A.nw + (dh,0) ! 1468: arrow from Ptr.B to Block.B.nw + (dh,0) ! 1469: arrow from Ptr.C to Block.C.nw + (dh,0) ! 1470: arrow from Ptr.D to Block.D.nw + (dh,0) ! 1471: ] ! 1472: box dashed ht last [].ht+dw wid last [].wid+dw at last [] ! 1473: .PE ! 1474: .NH ! 1475: Macros ! 1476: .PP ! 1477: .IT Pic ! 1478: provides a basic macro facility. ! 1479: In the simplest form, ! 1480: .P1 ! 1481: define \f2name\fP { \f2replacement text\fP } ! 1482: .P2 ! 1483: defines ! 1484: .IT name ! 1485: to be the ! 1486: .IT "replacement text" . ! 1487: Any subsequent occurrence of ! 1488: .IT name ! 1489: will be replaced by ! 1490: .IT "replacement text" . ! 1491: .PP ! 1492: Macros may have arguments. ! 1493: If the replacement text of a macro definition contains occurrences of ! 1494: .CW $1 , ! 1495: .CW $2 , ! 1496: etc., ! 1497: these will be replaced by the corresponding actual arguments ! 1498: when the macro is invoked. ! 1499: The invocation for a macro with arguments is ! 1500: .P1 ! 1501: name(arg1, arg2, ...) ! 1502: .P2 ! 1503: Non-existent arguments are replaced by null strings. ! 1504: Macro definitions last from picture to picture; ! 1505: a macro definition can be removed by ! 1506: .P1 ! 1507: undef \f2macro-name\fP ! 1508: .P2 ! 1509: .PP ! 1510: As an example, one might define a ! 1511: .CW square ! 1512: by ! 1513: .P1 ! 1514: define square { box ht $1 wid $1 $2 } ! 1515: .P2 ! 1516: and use it as ! 1517: .P1 ! 1518: square(1, "one" "inch") ! 1519: square(0.5) ! 1520: square(0.25, "\es-4tiny\es+4" dashed) ! 1521: .P2 ! 1522: .PS ! 1523: define square { box ht $1 wid $1 $2 } ! 1524: square(1, "one" "inch") ! 1525: square(0.5) ! 1526: square(0.25, "\s-4tiny\s+4" dashed) ! 1527: .PE ! 1528: Notice how the second argument may be used to pass in arbitrary contents. ! 1529: .PP ! 1530: Coordinates like ! 1531: .IT x,y ! 1532: may be enclosed in parentheses, ! 1533: as in ! 1534: .IT x,y ), ( ! 1535: so they can be included in a macro argument. ! 1536: .NH ! 1537: File Copy ! 1538: .PP ! 1539: The statement ! 1540: .P1 ! 1541: copy "\f2filename\fP" ! 1542: .P2 ! 1543: inserts the contents of the named file ! 1544: at that point in the input. ! 1545: Any ! 1546: .CW .PS ! 1547: or ! 1548: .CW .PE ! 1549: lines within the file ! 1550: are ignored, so previously prepared pictures ! 1551: can be used as parts of larger ones without editing. ! 1552: .PP ! 1553: .IT Pic ! 1554: also provides the ! 1555: .CW copy ! 1556: .CW thru ! 1557: mechanism found in ! 1558: .IT grap : ! 1559: .P1 ! 1560: copy "\f2file\fP" thru \f2macro-name\fP ! 1561: .P2 ! 1562: copies ! 1563: .IT file , ! 1564: treating each line as an invocation of the named macro ! 1565: (each field being an argument). ! 1566: A literal macro may be used instead of a name: ! 1567: .P1 ! 1568: copy "\f2file\fP" thru { \f2macro replacement text\fP } ! 1569: .P2 ! 1570: and if no file name is given, ! 1571: the remainder of the input until the next ! 1572: .CW .PE ! 1573: is used. ! 1574: So to plot a set of circles at points whose coordinates and radii ! 1575: are included in-line: ! 1576: .P1 ! 1577: copy thru { circle rad $3 at $1,$2 } ! 1578: 0 0 .05 ! 1579: 1 1 .1 ! 1580: .2 .3 .03 ! 1581: .4 .7 .05 ! 1582: \&... ! 1583: .P2 ! 1584: .PS ! 1585: copy thru { circle rad $3 at $1,$2 } ! 1586: 0 0 .05 ! 1587: 1 1 .1 ! 1588: .2 .3 .03 ! 1589: .4 .7 .05 ! 1590: .1 .8 .1 ! 1591: .4 .9 .02 ! 1592: .7 .5 .15 ! 1593: 1 .4 .04 ! 1594: .8 0 .075 ! 1595: .5 .25 .03 ! 1596: .PE ! 1597: .PP ! 1598: The ! 1599: .CW sh ! 1600: command executes an arbitrary commandline: ! 1601: .P1 ! 1602: sh { \f2anything\fP } ! 1603: .P2 ! 1604: Macros within ! 1605: .IT anything ! 1606: are expanded first. ! 1607: .NH ! 1608: Loops and Conditionals ! 1609: .PP ! 1610: .IT Pic ! 1611: provides an ! 1612: .CW if ! 1613: statement and a ! 1614: .CW for ! 1615: loop. ! 1616: .P1 ! 1617: pi = atan2(0,-1) ! 1618: for i = 0 to 2 * pi by 0.1 do { ! 1619: "\-" at i/2, 0 ! 1620: "s" at i/2, sin(i)/2 ! 1621: "c" at i/2, cos(i)/2 ! 1622: } ! 1623: .P2 ! 1624: .PS ! 1625: .ps -2 ! 1626: pi = atan2(0,-1) ! 1627: for i = 0 to 2 * pi by 0.1 do { ! 1628: "\-" at i/2, 0 ! 1629: "s" at i/2, sin(i)/2 ! 1630: "c" at i/2, cos(i)/2 ! 1631: } ! 1632: .ps +2 ! 1633: .PE ! 1634: The ! 1635: .CW by ! 1636: clause is optional; ! 1637: if the value is preceded by a ! 1638: .CW * , ! 1639: the steps are multiplicative, not additive. ! 1640: The body of the loop is delimited by braces, ! 1641: which are also used for definitions, ! 1642: .CW copy , ! 1643: .CW sh ! 1644: and ! 1645: .CW if ! 1646: statements. ! 1647: .PP ! 1648: The ! 1649: .CW if ! 1650: statement is ! 1651: .P1 ! 1652: if \f2expression\fP then { \f2anything\fP } else { \f2anything\fP } ! 1653: .P2 ! 1654: where the ! 1655: .CW else ! 1656: clause is optional. ! 1657: The ! 1658: .IT expression ! 1659: may use the usual relational operators: ! 1660: .CW == , ! 1661: .CW != , ! 1662: .CW > , ! 1663: .CW >= , ! 1664: .CW < , ! 1665: .CW <= , ! 1666: .CW && , ! 1667: and ! 1668: .CW || . ! 1669: .P1 ! 1670: pi = atan2(0,-1) ! 1671: for i = 0 to pi by 0.1 do { ! 1672: if (s = sin(i)) > 0.8 then { s = 0.8 } ! 1673: "x" at i/2, s/2 ! 1674: } ! 1675: .P2 ! 1676: .PS ! 1677: .ps -2 ! 1678: pi = atan2(0,-1) ! 1679: for i = 0 to pi by 0.1 do { ! 1680: if (s = sin(i)) > 0.8 then { s = 0.8 } ! 1681: "x" at i/2, s/2 ! 1682: } ! 1683: .ps +2 ! 1684: .PE ! 1685: A string comparison using ! 1686: .CW == ! 1687: or ! 1688: .CW != ! 1689: is also permitted, to compare quoted strings: ! 1690: .P1 ! 1691: if "\f2string1\fP" == "\f2string2\fP" then ... ! 1692: .P2 ! 1693: .NH ! 1694: \fITroff\fP Interface ! 1695: .PP ! 1696: .IT Pic ! 1697: is usually run as a ! 1698: .IT troff ! 1699: preprocessor: ! 1700: .P1 ! 1701: pic file | troff -ms ! 1702: .P2 ! 1703: Run it before ! 1704: .IT eqn ! 1705: if it is also present. ! 1706: .PP ! 1707: If the ! 1708: .CW .PS ! 1709: line looks like ! 1710: .P1 ! 1711: \&.PS <file ! 1712: .P2 ! 1713: then the contents of ! 1714: .CW file ! 1715: are inserted in place of the ! 1716: .CW .PS ! 1717: line, ! 1718: whether or not the file contains ! 1719: .CW .PS ! 1720: or ! 1721: .CW .PE . ! 1722: (This feature is deprecated in favor of the ! 1723: .CW copy ! 1724: statement.) ! 1725: .PP ! 1726: .IT Pic ! 1727: copies the ! 1728: .CW .PS ! 1729: and ! 1730: .CW .PE ! 1731: lines from input to output intact, ! 1732: except that it adds two things on the same line as the ! 1733: .CW .PS : ! 1734: .P1 ! 1735: \&.PS h w ! 1736: .P2 ! 1737: .CW h ! 1738: and ! 1739: .CW w ! 1740: are the picture height and width in units. ! 1741: The ! 1742: .CW -ms ! 1743: macro package has definitions for ! 1744: .CW .PS ! 1745: and ! 1746: .CW .PE ! 1747: that cause ! 1748: pictures to be centered and offset a bit from surrounding text. ! 1749: (See the appendix.) ! 1750: .PP ! 1751: If ! 1752: .CW .PF '' `` ! 1753: is used instead of ! 1754: .CW .PE , ! 1755: the position after printing is restored to where ! 1756: it was before the picture started, instead of being at the bottom. ! 1757: .CW F '' (`` ! 1758: is for ``flyback.'') ! 1759: .PP ! 1760: Any input line that begins with a ! 1761: period is assumed to be a ! 1762: .IT troff ! 1763: command that makes sense at that point; ! 1764: it is copied to the output at that point in the document. ! 1765: It is asking for trouble to add vertical space or in any way fiddle with ! 1766: the line spacing here, ! 1767: but point size and font changes are generally harmless: ! 1768: .P1 ! 1769: \&.ps 24 ! 1770: circle radius .4 at 0,0 ! 1771: \&.ps 12 ! 1772: circle radius .2 at 0,0 ! 1773: \&.ps 8 ! 1774: circle radius .1 at 0,0 ! 1775: \&.ps 6 ! 1776: circle radius .05 at 0,0 ! 1777: \&.ps 10 \e" don't forget to restore size ! 1778: .P2 ! 1779: .PS ! 1780: .ps 24 ! 1781: circle radius .4 at 0,0 ! 1782: .ps 12 ! 1783: circle radius .2 at 0,0 ! 1784: .ps 8 ! 1785: circle radius .1 at 0,0 ! 1786: .ps 6 ! 1787: circle radius .05 at 0,0 ! 1788: .ps 10 \" don't forget to restore size ! 1789: .PE ! 1790: .IT Pic ! 1791: does preserve the state of ! 1792: .IT troff 's ! 1793: fill mode across pictures. ! 1794: .PP ! 1795: It is also safe to include sizes, fonts and local motions ! 1796: within quoted strings ! 1797: .CW \&"..." ) ( ! 1798: in ! 1799: .IT pic , ! 1800: so long as whatever changes are made are unmade before exiting the string. ! 1801: For example, to print text in Helvetica Bold 2 points larger: ! 1802: .P1 ! 1803: ellipse "\es+2\ef(HBSmile!\efP\es-2" ! 1804: .P2 ! 1805: .PS ! 1806: ellipse "\s+2\f(HBSmile!\fP\s-2" ! 1807: .PE ! 1808: This is essentially the same rule as applies in ! 1809: .IT eqn . ! 1810: .PP ! 1811: There is a subtle problem with complicated equations inside ! 1812: .IT pic ! 1813: pictures \(em they come out wrong ! 1814: if ! 1815: .IT eqn ! 1816: has to leave extra vertical space for the equation. ! 1817: If your equation involves more than subscripts and superscripts, ! 1818: you must add to the beginning of each equation the extra information ! 1819: .CW "space 0" : ! 1820: .P1 ! 1821: arrow ! 1822: box "$space 0 {H( omega )} over {1 - H( omega )}$" ! 1823: arrow ! 1824: .P2 ! 1825: .EQ ! 1826: delim $$ ! 1827: .EN ! 1828: .PS ! 1829: arrow ! 1830: box "$space 0 {H( omega )} over {1 - H( omega )}$" ! 1831: arrow ! 1832: .PE ! 1833: .NH ! 1834: Some Examples ! 1835: .PP ! 1836: Here are a handful of larger examples: ! 1837: .KS ! 1838: .PS ! 1839: define ndblock X ! 1840: box wid boxwid/2 ht boxht/2 ! 1841: down; box same with .t at bottom of last box; box same ! 1842: X ! 1843: .ps -2 ! 1844: .ft CW ! 1845: boxht = .2; boxwid = .3; dx = 0.05 ! 1846: down; box; box; box; box ht 3*boxht "." "." "." ! 1847: L: box; box; box invis wid 2*boxwid "hashtab:" with .e at 1st box .w ! 1848: right ! 1849: Start: box wid .5 with .sw at 1st box.ne + (.4,.2) "..." ! 1850: N1: box wid .2 "n1"; D1: box wid .3 "d1" ! 1851: N3: box wid .4 "n3"; D3: box wid .3 "d3" ! 1852: box wid .4 "..." ! 1853: N2: box wid .5 "n2"; D2: box wid .2 "d2" ! 1854: ! 1855: arrow right from 2nd box ! 1856: ndblock ! 1857: spline -> right .2 from 3rd last box then to N1.sw + (dx,0) ! 1858: spline -> right .3 from 2nd last box then to D1.sw + (dx,0) ! 1859: arrow right from last box ! 1860: ndblock ! 1861: spline -> right .2 from 3rd last box to N2.sw-(dx,.2) to N2.sw+(dx,0) ! 1862: spline -> right .3 from 2nd last box to D2.sw-(dx,.2) to D2.sw+(dx,0) ! 1863: arrow right 2*linewid from L ! 1864: ndblock ! 1865: spline -> right .2 from 3rd last box to N3.sw + (dx,0) ! 1866: spline -> right .3 from 2nd last box to D3.sw + (dx,0) ! 1867: ! 1868: circlerad = .3 ! 1869: circle invis "ndblock" at last box.e + (1.2,.2) ! 1870: arrow dashed from last circle.w to last box chop 0 chop .3 ! 1871: ! 1872: box invis wid 2*boxwid "ndtable:" with .e at Start.w ! 1873: .ps ! 1874: .ft ! 1875: .PE ! 1876: .KE ! 1877: .sp ! 1878: .P1 ! 1879: .vs -1p ! 1880: define ndblock { ! 1881: box wid boxwid/2 ht boxht/2 ! 1882: down; box same with .t at bottom of last box; box same ! 1883: } ! 1884: boxht = .2; boxwid = .3; circlerad = .3; dx = 0.05 ! 1885: down; box; box; box; box ht 3*boxht "." "." "." ! 1886: L: box; box; box invis wid 2*boxwid "hashtab:" with .e at 1st box .w ! 1887: right ! 1888: Start: box wid .5 with .sw at 1st box.ne + (.4,.2) "..." ! 1889: N1: box wid .2 "n1"; D1: box wid .3 "d1" ! 1890: N3: box wid .4 "n3"; D3: box wid .3 "d3" ! 1891: box wid .4 "..." ! 1892: N2: box wid .5 "n2"; D2: box wid .2 "d2" ! 1893: arrow right from 2nd box ! 1894: ndblock ! 1895: spline -> right .2 from 3rd last box then to N1.sw + (dx,0) ! 1896: spline -> right .3 from 2nd last box then to D1.sw + (dx,0) ! 1897: arrow right from last box ! 1898: ndblock ! 1899: spline -> right .2 from 3rd last box to N2.sw-(dx,.2) to N2.sw+(dx,0) ! 1900: spline -> right .3 from 2nd last box to D2.sw-(dx,.2) to D2.sw+(dx,0) ! 1901: arrow right 2*linewid from L ! 1902: ndblock ! 1903: spline -> right .2 from 3rd last box to N3.sw + (dx,0) ! 1904: spline -> right .3 from 2nd last box to D3.sw + (dx,0) ! 1905: circlerad = .3 ! 1906: circle invis "ndblock" at last box.e + (1.2,.2) ! 1907: arrow dashed from last circle.w to last box chop 0 chop .3 ! 1908: box invis wid 2*boxwid "ndtable:" with .e at Start.w ! 1909: .P2 ! 1910: .sp ! 1911: .KS ! 1912: .PS 5 ! 1913: .ps 8 ! 1914: boxht = .5; boxwid = .75 ! 1915: circlerad = .25 ! 1916: arrow "source" "code" ! 1917: LA: box "lexical" "analyzer" ! 1918: arrow "tokens" above ! 1919: P: box "parser" ! 1920: arrow "intermediate" "code" ! 1921: Sem: box "semantic" "checker" ! 1922: arrow ! 1923: ! 1924: arrow <-> up from top of LA ! 1925: LC: box "lexical" "corrector" ! 1926: arrow <-> up from top of P ! 1927: Syn: box "syntactic" "corrector" ! 1928: arrow up ! 1929: DMP: box "diagnostic" "message" "printer" ! 1930: arrow <-> right from right of DMP ! 1931: ST: box "symbol" "table" ! 1932: arrow from LC.ne to DMP.sw ! 1933: arrow from Sem.nw to DMP.se ! 1934: arrow <-> from Sem.top to ST.bot ! 1935: .PE ! 1936: .KE ! 1937: .LP ! 1938: .P1 ! 1939: \&.PS 5 ! 1940: \&.ps 8 ! 1941: \& arrow "source" "code" ! 1942: \&LA: box "lexical" "analyzer" ! 1943: \& arrow "tokens" above ! 1944: \&P: box "parser" ! 1945: \& arrow "intermediate" "code" ! 1946: \&Sem: box "semantic" "checker" ! 1947: \& arrow ! 1948: \& ! 1949: \& arrow <-> up from top of LA ! 1950: \&LC: box "lexical" "corrector" ! 1951: \& arrow <-> up from top of P ! 1952: \&Syn: box "syntactic" "corrector" ! 1953: \& arrow up ! 1954: \&DMP: box "diagnostic" "message" "printer" ! 1955: \& arrow <-> right from right of DMP ! 1956: \&ST: box "symbol" "table" ! 1957: \& arrow from LC.ne to DMP.sw ! 1958: \& arrow from Sem.nw to DMP.se ! 1959: \& arrow <-> from Sem.top to ST.bot ! 1960: \&.PE ! 1961: .P2 ! 1962: .PP ! 1963: There are eighteen objects (boxes and arrows) in the picture, ! 1964: and one line of ! 1965: .IT pic ! 1966: input for each; ! 1967: this seems like an acceptable level of verbosity. ! 1968: .sp ! 1969: .KS ! 1970: .PS ! 1971: .ps -2 ! 1972: circle "DISK" ! 1973: arrow "character" "defns" ! 1974: CPU: box "CPU" "(16-bit mini)" ! 1975: { arrow <- from top of CPU up "input " rjust } ! 1976: arrow ! 1977: CRT: " CRT" ljust ! 1978: line from CRT - 0,0.075 up 0.15 \ ! 1979: then right 0.5 \ ! 1980: then right 0.5 up 0.25 \ ! 1981: then down 0.5+0.15 \ ! 1982: then left 0.5 up 0.25 \ ! 1983: then left 0.5 ! 1984: Paper: CRT + 1.05,0.75 ! 1985: arrow <- from Paper down 1.5 ! 1986: " ... paper" ljust at end of last arrow + 0, 0.25 ! 1987: circle rad 0.05 at Paper + (-0.055, -0.25) ! 1988: circle rad 0.05 at Paper + (0.055, -0.25) ! 1989: " rollers" ljust at Paper + (0.1, -0.25) ! 1990: .ps +2 ! 1991: .PE ! 1992: .ce ! 1993: Basic Digital Typesetter ! 1994: .sp ! 1995: .KE ! 1996: .LP ! 1997: .P1 ! 1998: .vs -1 ! 1999: \&.PS ! 2000: \&.ps -2 ! 2001: circle "DISK" ! 2002: arrow "character" "defns" ! 2003: CPU: box "CPU" "(16-bit mini)" ! 2004: { arrow <- from top of CPU up "input " rjust } ! 2005: arrow ! 2006: CRT: " CRT" ljust ! 2007: line from CRT - 0,0.075 up 0.15 \e ! 2008: then right 0.5 \e ! 2009: then right 0.5 up 0.25 \e ! 2010: then down 0.5+0.15 \e ! 2011: then left 0.5 up 0.25 \e ! 2012: then left 0.5 ! 2013: Paper: CRT + 1.05,0.75 ! 2014: arrow <- from Paper down 1.5 ! 2015: " ... paper" ljust at end of last arrow + 0, 0.25 ! 2016: circle rad 0.05 at Paper + (-0.055, -0.25) ! 2017: circle rad 0.05 at Paper + (0.055, -0.25) ! 2018: " rollers" ljust at Paper + (0.1, -0.25) ! 2019: \&.ps +2 ! 2020: \&.PE ! 2021: \&.ce ! 2022: \&Basic Digital Typesetter ! 2023: .P2 ! 2024: .SH ! 2025: Acknowledgements ! 2026: .PP ! 2027: I am indebted to Chris Van Wyk for ideas from several versions of ! 2028: .IT ideal . ! 2029: He and Doug McIlroy have also contributed algorithms ! 2030: for line and circle drawing, ! 2031: and made useful suggestions on the design of ! 2032: .IT pic . ! 2033: Theo Pavlidis contributed the basic spline algorithm; ! 2034: Eric Grosse provided code to compute the bounding box of an arc. ! 2035: Charles Wetherell pointed out reference ! 2036: [2] ! 2037: to me, and made several valuable criticisms on an early ! 2038: draft of the language and manual. ! 2039: The exposition in this manual has been greatly improved ! 2040: by suggestions from Jim Blinn and Mark Miller. ! 2041: I am grateful to ! 2042: my early users \(em ! 2043: Brenda Baker, ! 2044: Dottie Luciani, ! 2045: and Paul Tukey ! 2046: \(em ! 2047: for their suggestions and cheerful use of ! 2048: an often shaky and clumsy system. ! 2049: .PP ! 2050: More recent versions of ! 2051: .IT pic ! 2052: have benefited greatly from ! 2053: adventurous use by ! 2054: Jon Bentley and Ravi Sethi; ! 2055: their comments on the manual are also much appreciated. ! 2056: .SH ! 2057: References ! 2058: .LP ! 2059: |reference_placement ! 2060: .BP ! 2061: ........ ! 2062: .SH ! 2063: Appendix A: \fIPic\fP Reference Manual ! 2064: .SH ! 2065: Pictures ! 2066: .PP ! 2067: The top-level object in ! 2068: .IT pic ! 2069: is the ``picture'': ! 2070: .P1 ! 2071: \f2picture\fP: ! 2072: .PS \f2optional-width\fP \f2optional-height\fP ! 2073: \f2element-list\fP ! 2074: .PE ! 2075: .P2 ! 2076: If ! 2077: .IT optional-width ! 2078: is present, the picture is made that many inches wide, ! 2079: regardless of any dimensions used internally. ! 2080: The height is scaled in the same proportion unless ! 2081: .IT optional-height ! 2082: is present. ! 2083: If instead the line is ! 2084: .P1 ! 2085: \&.PS <f ! 2086: .P2 ! 2087: the file ! 2088: .CW f ! 2089: is inserted in place of the ! 2090: .CW .PS ! 2091: line. ! 2092: If ! 2093: .CW .PF ! 2094: is used instead of ! 2095: .CW .PE , ! 2096: the position after printing is restored to what it was ! 2097: upon entry. ! 2098: .PP ! 2099: In no case will the picture be larger than ! 2100: .CW maxpsht ! 2101: \(mu ! 2102: .CW maxpswid . ! 2103: .SH ! 2104: Elements ! 2105: .PP ! 2106: An ! 2107: .IT element-list ! 2108: is a list of elements (what else?); ! 2109: the elements are ! 2110: .P1 ! 2111: \f2element\fP: ! 2112: \f2primitive attribute-list\fP ! 2113: \f2placename\fP : \f2element\fP ! 2114: \f2placename\fP : \f2position\fP ! 2115: \f2var\fP = \f2expr\fP ! 2116: \f2direction\fP ! 2117: { \f2element-list\fP } ! 2118: [ \f2element-list\fP ] ! 2119: for \f2var\fP = \f2expr\fP to \f2expr\fP by \f2expr\fP do { \f2anything\fP } ! 2120: if \f2expr\fP then { \f2anything\fP } else { \f2anything\fP } ! 2121: copy \f2file\fP ! 2122: copy thru \f2macro\fP ! 2123: copy \f2file\fP thru \fPmacro\fP ! 2124: sh { \f2commandline\fP } ! 2125: print \f2expr\fP ! 2126: reset \f2optional var-list\fP ! 2127: \f2troff-command\fP ! 2128: .P2 ! 2129: .PP ! 2130: Elements are separated by newlines or semicolons; ! 2131: a long element may be continued by ending the line with a backslash. ! 2132: Comments are introduced by a ! 2133: .CW # ! 2134: and terminated by a newline. ! 2135: .PP ! 2136: Variable names begin with a lower case letter; ! 2137: place names begin with upper case. ! 2138: Place and variable names retain their values ! 2139: from one picture to the next. ! 2140: .PP ! 2141: The current position and direction of motion are saved upon entry ! 2142: to a ! 2143: .CW {...} ! 2144: block and restored upon exit. ! 2145: .PP ! 2146: Elements within a block enclosed in ! 2147: .CW [...] ! 2148: are treated as a unit; ! 2149: the dimensions are determined by the extreme points ! 2150: of the contained objects. ! 2151: Names, variables, and direction of motion within a block are local to that block. ! 2152: .PP ! 2153: .IT troff-command ! 2154: is any line that begins with a period. ! 2155: Such a line is assumed to make sense in the context where it appears; ! 2156: accordingly, ! 2157: if it doesn't work, don't call. ! 2158: .SH ! 2159: Primitives ! 2160: .PP ! 2161: The primitive objects are ! 2162: .P1 ! 2163: \f2primitive\fP: ! 2164: box ! 2165: circle ! 2166: ellipse ! 2167: arc ! 2168: line ! 2169: arrow ! 2170: spline ! 2171: move ! 2172: \f2text-list\fP ! 2173: .P2 ! 2174: .CW arrow ! 2175: is a synonym for ! 2176: .CW line ! 2177: .CW -> . ! 2178: .SH ! 2179: Attributes ! 2180: .PP ! 2181: An ! 2182: .IT attribute-list ! 2183: is a sequence of zero or more attributes; ! 2184: each attribute consists of a keyword, perhaps followed by a value. ! 2185: .P1 ! 2186: .ta .5i 2.5i ! 2187: \f2attribute\fP: ! 2188: h(eigh)t \f2expr\fP wid(th) \f2expr\fP ! 2189: rad(ius) \f2expr\fP diam(eter) \f2expr\fP ! 2190: up \f2opt-expr\fP down \f2opt-expr\fP ! 2191: right \f2opt-expr\fP left \f2opt-expr\fP ! 2192: from \f2position\fP to \f2position\fP ! 2193: at \f2position\fP with \f2corner\fP ! 2194: by \f2expr, expr\fP then ! 2195: dotted \f2opt-expr\fP dashed \f2opt-expr\fP ! 2196: chop \f2opt-expr\fP -> <- <-> ! 2197: invis solid ! 2198: fill \f2opt-expr\fP same ! 2199: \f2text-list\fP \f2expr\fP ! 2200: .P2 ! 2201: Missing attributes and values are filled in from defaults. ! 2202: Not all attributes make sense for all primitives; ! 2203: irrelevant ones are silently ignored. ! 2204: The attribute ! 2205: .CW at ! 2206: causes the geometrical center to be put at the specified place; ! 2207: .CW with ! 2208: causes the position on the object to be put at the specified place. ! 2209: For lines, splines and arcs, ! 2210: .CW height ! 2211: and ! 2212: .CW width ! 2213: refer to arrowhead size. ! 2214: A bare ! 2215: .IT expr ! 2216: implies motion in the current direction. ! 2217: .SH ! 2218: Text ! 2219: .PP ! 2220: Text is normally an attribute of some primitive; ! 2221: by default it is placed at the geometrical center of the object. ! 2222: Stand-alone text is also permitted. ! 2223: A ! 2224: .IT text-list ! 2225: is a list of text items; a text item is ! 2226: a quoted string optionally followed by positioning requests: ! 2227: .P1 ! 2228: \f2text-item\fP: ! 2229: "..." \f2positioning ...\fP ! 2230: sprintf("\f2format\fP", \f2expr\fP, \f2...\fP) \f2positioning ...\fP ! 2231: \f2positioning\fP: ! 2232: center ljust rjust above below ! 2233: .P2 ! 2234: If there are multiple text items for some primitive, ! 2235: they are centered vertically except as qualified. ! 2236: Positioning requests apply to each item independently. ! 2237: .PP ! 2238: Text items can contain ! 2239: .IT troff ! 2240: commands for size and font changes, local motions, etc., ! 2241: but make sure that these are balanced ! 2242: so that the entering state is restored before exiting. ! 2243: .SH ! 2244: Positions and places ! 2245: .PP ! 2246: A position is ultimately an ! 2247: .IT x,y ! 2248: coordinate pair, but it may be specified in other ways. ! 2249: .P1 ! 2250: \f2position\fP: ! 2251: \f2expr, expr\fP ! 2252: \f2place\fP \(+- \f2expr, expr\fP ! 2253: \f2place\fP \(+- ( \f2expr, expr\fP ) ! 2254: ( \f2position\fP,\f2 position\fP ) ! 2255: \f2expr\fP \f2[\fPof the way\f2]\fP between \f2position\fP and \f2position\fP ! 2256: \f2expr\fP < \f2position\fP , \f2position\fP > ! 2257: ( \f2position\fP ) ! 2258: .sp .5 ! 2259: \f2place\fP: ! 2260: \f2placename\fP \f2optional-corner\fP ! 2261: \f2corner\fP of \f2placename\fP ! 2262: \f2nth\fP \f2primitive\fP \f2optional-corner\fP ! 2263: \f2corner\fP of \f2nth\fP \f2primitive\fP ! 2264: Here ! 2265: .P2 ! 2266: An ! 2267: .IT optional-corner ! 2268: is one of the eight compass points ! 2269: or the center or the start or end of a primitive. ! 2270: .P1 ! 2271: \f2optional-corner\fP: ! 2272: .n .e .w .s .ne .se .nw .sw .c .start .end ! 2273: \f2corner\fP: ! 2274: top bot left right start end ! 2275: .P2 ! 2276: Each object in a picture has an ordinal number; ! 2277: .IT nth ! 2278: refers to this. ! 2279: .P1 ! 2280: \f2nth\fP: ! 2281: \f2n\fPth ! 2282: \f2n\fPth last ! 2283: .P2 ! 2284: Since barbarisms like ! 2285: .CW 1th ! 2286: and ! 2287: .CW 3th ! 2288: are barbaric, ! 2289: synonyms like ! 2290: .CW 1st ! 2291: and ! 2292: .CW 3rd ! 2293: are accepted as well. ! 2294: .SH ! 2295: Variables ! 2296: .PP ! 2297: The built-in variables and their default values are: ! 2298: .P1 ! 2299: .ta .5i 2.5i ! 2300: boxwid 0.75 boxht 0.5 ! 2301: circlerad 0.25 arcrad 0.25 ! 2302: ellipsewid 0.75 ellipseht 0.5 ! 2303: linewid 0.5 lineht 0.5 ! 2304: movewid 0.5 moveht 0.5 ! 2305: textwid 0 textht 0 ! 2306: arrowwid 0.05 arrowht 0.1 ! 2307: dashwid 0.1 arrowhead 2 ! 2308: maxpsht 8.5 maxpswid 11 ! 2309: scale 1 fillval .3 ! 2310: .P2 ! 2311: These may be changed at any time, ! 2312: and the new values remain in force from picture to picture until changed again ! 2313: or reset by a ! 2314: .CW reset ! 2315: statement. ! 2316: Variables changed within ! 2317: .CW [ ! 2318: and ! 2319: .CW ] ! 2320: revert to their previous value upon exit from the block. ! 2321: Dimensions are divided by ! 2322: .CW scale ! 2323: during output. ! 2324: .SH ! 2325: Expressions ! 2326: .PP ! 2327: Expressions in ! 2328: .IT pic ! 2329: are evaluated in floating point. ! 2330: All numbers representing dimensions are taken to be in inches. ! 2331: .EQ ! 2332: delim $$ ! 2333: .EN ! 2334: .P1 ! 2335: \f2expr\fP: ! 2336: \f2expr\fP \f2op\fP \f2expr\fP ! 2337: - \f2expr\fP ! 2338: ! \f2expr\fP ! 2339: ( \f2expr\fP ) ! 2340: variable ! 2341: number ! 2342: \f2place\fP .x ! 2343: \f2place\fP .y ! 2344: \f2place\fP .ht ! 2345: \f2place\fP .wid ! 2346: \f2place\fP .rad ! 2347: sin($expr$) cos($expr$) atan2($expr,expr$) log($expr$) exp($expr$) ! 2348: sqrt($expr$) max($expr,expr$) min($expr,expr$) int($expr$) rand() ! 2349: \f2op\fP: ! 2350: + - * / % ^ ! 2351: < <= > >= == != && || ! 2352: .P2 ! 2353: .SH ! 2354: Definitions ! 2355: .PP ! 2356: The ! 2357: .CW define ! 2358: and ! 2359: .CW undef ! 2360: statements are not part of the grammar. ! 2361: .P1 ! 2362: \f2define\fP: ! 2363: define \f2name\fP { \f2replacement text\fP } ! 2364: \f2undef\fP: ! 2365: undef \f2name\fP ! 2366: .P2 ! 2367: .EQ ! 2368: delim off ! 2369: .EN ! 2370: Occurrences of ! 2371: .CW $1 , ! 2372: .CW $2 , ! 2373: etc., ! 2374: in the replacement text ! 2375: will be replaced by the corresponding arguments if ! 2376: .IT name ! 2377: is invoked as ! 2378: .P1 ! 2379: \f2name\fP(\f2arg1\fP, \f2arg2\fP, ...) ! 2380: .P2 ! 2381: Non-existent arguments are replaced by null strings. ! 2382: .IT Replacement ! 2383: .IT text ! 2384: may contain newlines. ! 2385: The ! 2386: .CW undef ! 2387: statement removes the definition of a macro. ! 2388: .SH ! 2389: The .PS and .PE Macros ! 2390: .PP ! 2391: This is the default definition of the ! 2392: .CW .PS ! 2393: and ! 2394: .CW .PE ! 2395: macros: ! 2396: .P1 ! 2397: .de PS \e" start picture; $1 is height, $2 is width, in inches ! 2398: .sp .3 ! 2399: .in (\e\en(.lu-\e\e$2)/2u ! 2400: .ne \e\e$1 ! 2401: .. ! 2402: .de PE \e" end of picture ! 2403: .in ! 2404: .sp .6 ! 2405: .. ! 2406: .P2 ! 2407: .SH ! 2408: Summary of Features Added Since Original Version ! 2409: .PP ! 2410: The built-in functions ! 2411: .CW sin , ! 2412: .CW cos , ! 2413: .CW atan2 , ! 2414: .CW log , ! 2415: .CW exp , ! 2416: .CW sqrt , ! 2417: .CW max , ! 2418: .CW min , ! 2419: .CW int , ! 2420: and ! 2421: .CW rand ! 2422: are available. ! 2423: .PP ! 2424: The ! 2425: .CW copy ! 2426: statement includes data from a file or that follows immediately: ! 2427: .P1 ! 2428: copy "\f2filename\fP" ! 2429: copy thru \f2macro\fP ! 2430: copy "\f2filename\fP" thru \f2macro\fP ! 2431: .P2 ! 2432: The ! 2433: .IT macro ! 2434: may be either the name of a defined macro, or the body of a macro ! 2435: enclosed in braces. ! 2436: If no filename is given, ! 2437: .CW copy ! 2438: copies the input until the next ! 2439: .CW .PE . ! 2440: .PP ! 2441: The ! 2442: .CW for ! 2443: and ! 2444: .CW if ! 2445: statements provide loops and decision-making: ! 2446: .P1 ! 2447: for \f2var\fP=\f2expr\fP to \f2expr\fP by \f2expr\fP do { \f2anything\fP } ! 2448: if \f2expr\fP then { \f2anything\fP } else { \f2anything\fP } ! 2449: .P2 ! 2450: The ! 2451: .CW by ! 2452: and ! 2453: .CW else ! 2454: clauses are optional. ! 2455: The ! 2456: .IT expr ! 2457: in an ! 2458: .CW if ! 2459: may use the usual relational operators ! 2460: or the tests ! 2461: .IT str1 ! 2462: .CW == ! 2463: (or ! 2464: .CW != ) ! 2465: .IT str2 ! 2466: for two quoted strings. ! 2467: .PP ! 2468: The ! 2469: .CW sh ! 2470: command executes any sequence of commands, after expanding any defined names: ! 2471: .P1 ! 2472: sh { \f2anything\fP } ! 2473: .P2 ! 2474: .PP ! 2475: In all of the above, ! 2476: any single character that does not occur within the body ! 2477: may be used to enclose a body, ! 2478: instead of ! 2479: braces, as in ! 2480: .P1 ! 2481: define name X replacement text X ! 2482: .P2 ! 2483: .PP ! 2484: Text strings are first-class citizens: ! 2485: a statement beginning with a sequence of text strings is treated ! 2486: as an invisible box with the strings positioned at its center. ! 2487: The variable ! 2488: .CW textht ! 2489: and ! 2490: .CW textwid ! 2491: may be set to any values to control positioning. ! 2492: The height of \f2n\fP such strings is \f2n\fP \(mu ! 2493: .CW textht . ! 2494: .PP ! 2495: It is possible to convert expressions to formatted strings: ! 2496: .P1 ! 2497: sprintf("\f2format\fP", \f2expr\fP, \f2expr\fP, ...) ! 2498: .P2 ! 2499: is equivalent to a quoted string in any context. ! 2500: Variants of ! 2501: .CW %f ! 2502: and ! 2503: .CW %g ! 2504: are the only sensible format conversions. ! 2505: .PP ! 2506: Built-in variables may be reset to default values with ! 2507: .CW reset . ! 2508: .PP ! 2509: The ! 2510: .CW undef ! 2511: statement removes a macro definition. ! 2512: .PP ! 2513: Arrowheads may be filled with the ! 2514: .CW arrowhead ! 2515: variable; ! 2516: their positioning is improved on arcs. ! 2517: .PP ! 2518: The width and height of the generated picture ! 2519: may be set independently from the ! 2520: .CW .PS ! 2521: line; ! 2522: the maximum height and width are set from ! 2523: .CW maxpsht ! 2524: and ! 2525: .CW maxpswid . ! 2526: .PP ! 2527: The state of ! 2528: .IT troff 's ! 2529: fill or no-fill mode is preserved around a picture. ! 2530: .PP ! 2531: Input numbers may be expressed in ! 2532: .CW E ! 2533: notation. ! 2534: .PP ! 2535: Numerous internal changes have been made as well. ! 2536: Any number of objects, text strings, etc., may be used; ! 2537: the only limit is total available memory. ! 2538: Output is now produced in inches instead of units ! 2539: for a particular typesetter, ! 2540: so the ! 2541: .CW -T ! 2542: option has gone away.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.