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