home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume4 / xpic / part14 < prev    next >
Encoding:
Internet Message Format  |  1989-07-21  |  52.2 KB

  1. Path: uunet!island!argv
  2. From: argv@island.uu.net (Dan Heller)
  3. Newsgroups: comp.sources.x
  4. Subject: v04i079: xpic -- pic previewer for X11, Part14/15
  5. Message-ID: <927@island.uu.net>
  6. Date: 22 Jul 89 07:42:17 GMT
  7. Organization: Island Graphics, Marin County, California
  8. Lines: 1678
  9. Approved: island!argv@sun.com
  10.  
  11. Submitted-by: Mark Moraes <moraes@ai.toronto.edu>
  12. Posting-number: Volume 4, Issue 79
  13. Archive-name: xpic/part14
  14.  
  15.  
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 14 (of 15)."
  24. # Contents:  xpic/doc/xpic.doc xpic/xpic.c
  25. # Wrapped by moraes@neat.ai on Thu Jul 13 22:36:12 1989
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'xpic/doc/xpic.doc' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'xpic/doc/xpic.doc'\"
  29. else
  30. echo shar: Extracting \"'xpic/doc/xpic.doc'\" \(29158 characters\)
  31. sed "s/^X//" >'xpic/doc/xpic.doc' <<'END_OF_FILE'
  32. X$Header: xpic.doc,v 1.11 89/02/10 04:12:27 xwindows Exp $
  33. X                              Using xpic.
  34. X                              -----------
  35. X
  36. X                             Mark Moraes
  37. X                  Computer Systems Research Institute
  38. X                      (moraes@csri.toronto.edu)
  39. X
  40. XXpic is a drawing package for the X Windows system, inspired
  41. Xstrongly by a similar, much-used package written by Bruno Preiss
  42. Xfor the BitGraph (bgpic).  Xpic was not intended for painting, but
  43. Xdrawing diagrams, and figures. It was intended to produce output
  44. Xfor pic(1) and PostScript(tm), and some of its features stem from
  45. Xthat. But it outputs a simple file of object descriptions, which
  46. Xcan be translated to any device you like, if you write the
  47. Xappropriate filter. At present, filters exist for pic (the troff
  48. Xand TeX versions) and PostScript.
  49. X
  50. XUsage:
  51. Xxpic [host:display] [geometry] [iconGeometry] option ..... file ... 
  52. X
  53. XThe list of options is shown below - either the short form, or the 
  54. Xlong form is valid. The option is followed by a description, and the 
  55. Xdefault.
  56. X
  57. XOption   Resource name    Action                 Default
  58. X
  59. X-grid,   gridOn "off"     Turns grid off         (On)
  60. X+grid,   gridOn "on"      Turns grid on          (On)
  61. X-gs,     gridSpacing      Grid spacing in pixels (8)
  62. X-ph,     pageHeight       PageHeight in 10*in.   (110)
  63. X-pw,     pageWidth        PageWidth in 10*in.    (85)
  64. X-rotate, rotate "on"      swap page height and width
  65. X+rotate, rotate "off"     normal page height and width
  66. X-backup, backup "off"     No backup file on write(On)
  67. X+backup, backup "on"      Make backup file on write(On)
  68. X-cr,     cursorColor      Sets cursor color      (Black)
  69. X-hl,     highlight        Sets highlight color   (Black)
  70. X
  71. XThanks to a sneak trick in the way xpic saves files, *executing* a file
  72. Xsaved by xpic will cause it to start up xpic on itself. This feature
  73. Xmay not be available on all systems.
  74. X
  75. X(Note that we refer to two types of buttons in this document - mouse
  76. Xbuttons, and screen buttons (which are pieces of text on the screen
  77. Xsurrounded by borders, which darken when the mouse cursor moves into
  78. Xthem, and highlight and select when the left mouse button is pressed
  79. Xin them. We will always call a mouse button a 'left button', 'right
  80. Xbutton', or 'middle button' or just a 'mouse button'. Any other use of
  81. Xbutton means a screen button)
  82. X
  83. XThe basic screen consists of three sections: the drawing window, the
  84. Xtext interaction window, and the button area.
  85. X
  86. X The Drawing Window
  87. X ------------------
  88. XThe drawing window has a grid, with crosses every five grid points. Each
  89. Xcross is supposed to be at 0.5 inch spacings - as such, the default page
  90. Xsize is supposed to represent an 8.5x11" page. Changing the size results
  91. Xin the picture window resizing as best as it can, while the menus and
  92. Xthe input window remain constant. (There is a minimum window size, which
  93. Xcan be discovered by experimentation) Resizing assumes the so-called
  94. X'quarter-plane' model - i.e. the upper-left corner of the picture is the
  95. Xorigin, and remains fixed; Increasing the size means that more room is
  96. Xavailable to draw, but the scale does NOT change. If you make the window
  97. Xsmaller, then stuff that may go outside the window boundaries will be
  98. Xclipped, but will still be part of the picture.
  99. X
  100. XThe cross-hairs cursor in the drawing window tracks the mouse. The
  101. Xtracking is done by the X server, and possesses all the disadvantages of
  102. XX tracking. However, the cursor position, as far as xpic is concerned,
  103. Xis "snapped" to the nearest grid point, (or a fraction thereof,
  104. Xdepending on the Snap setting - more on this later.)
  105. X
  106. XAll objects in the drawing window "rubber-band", i.e. they follow the
  107. Xmouse, re-drawing on each mouse movement. This means that hyper-speed
  108. Xmovement of the mouse is very unwise. 
  109. X
  110. XThe mouse button convention is reasonably consistent:
  111. X
  112. XThe Left mouse button selects a point. This is really the action mouse button for
  113. Xmost tasks. (In edit mode, i.e. copy, move, delete, paste, adjust, this
  114. Xmouse button selects the nearest selectable object - 'nearest' means the
  115. Xobject whose bounding-box centre is closest to the mouse)
  116. X
  117. XThe Right mouse button ends lines, and splines at the last point at which the
  118. XLeft mouse button was clicked. i.e. the rubber-banded segment vanishes.
  119. X(In edit mode, this deselects the object that has been selected, and
  120. Xmakes it non-selectable. So a subsequent Left click will select the 
  121. Xnext-nearest object. This selection cycles around)
  122. X
  123. XThe Middle mouse button aborts the operation, and erases the element being
  124. Xdrawn. Use with care - It cannot be undone. (Maybe this should become
  125. XSHIFT-Middle mouse button.) (In edit mode, in addition to aborting whatever
  126. Xoperation was in progress, it also makes all objects selectable again)
  127. X
  128. XSmall fonts are barely readable - they are meant to give an idea of size
  129. Xmore than anything. Using 6 point fonts requires considerable imagination.
  130. XThe fonts are not exact replicas of what you can get on paper, and are
  131. Xlimited to a small subset of fonts which I could scale and generate for
  132. XX.
  133. X
  134. X The Button Area
  135. X ---------------
  136. XThe buttons are grouped in button-boxes. Click the left mouse button on a
  137. Xbutton to select it.  There are three types of buttons - radio-buttons,
  138. Xcommand buttons and updown buttons. The radio-buttons when clicked on, turn
  139. Xon, AND the button in the same button box which was on turns off - i.e. only
  140. Xone radio-button in any button box will be on at any one time. The selected
  141. Xbutton will be in inverse video, and will remain that way till another
  142. Xbutton is selected. The updown buttons have a "+" sign on the left and a "-"
  143. Xsign on the right - clicking the left mouse button will cause the updown
  144. Xbutton to advance to the next selection, which is displayed in the centre of
  145. Xthe button. Clicking the right mouse button will cause the updown button to
  146. Xmove to the previous selection.
  147. X
  148. XIn the command button boxes, no item remains permanantly selected.
  149. XWhen a button is pressed, it executes a command, and unhighlights
  150. Xautomatically.
  151. X
  152. X Button functions:
  153. X -----------------
  154. XThe top button box consists of basic functions - for drawing elements,
  155. Xand for editing them.
  156. X
  157. XThe basic element drawing functions are:
  158. X
  159. XBox:
  160. X    Draws a rectangle. Select the button, and click the left mouse
  161. Xbutton in the drawing window to start the box, (this specifies one
  162. Xcorner) and move the mouse to the other corner of the desired box and
  163. Xclick the left mouse button again to end the box.
  164. X
  165. XLine:
  166. X    This is a continuous "poly-line". To draw the line, select
  167. Xthis button, and go into the drawing window. Each left click puts down
  168. Xa point for the line, and clicking the right button ends the line.
  169. X(Note that the point where you click the right button is not part of
  170. Xthe line)
  171. X
  172. XSpline:
  173. X    Works just like a line, except that it draws a quadratic
  174. XB-spline connecting the points instead of a line.
  175. X
  176. XCircle:
  177. X    The first click of the left mouse button sets the centre, and
  178. Xthe second click sets the radius.
  179. X
  180. XEllipse:
  181. X    The first click sets one corner of the box enclosing the
  182. Xellipse, and the second click sets the other corner.
  183. X
  184. X
  185. XText: 
  186. X    To put text, select the Text button. Then, click the left mouse
  187. Xbutton somewhere in the drawing window. The interaction window will
  188. Xprompt for text with a "?". After inputting the text, (and hitting
  189. Xreturn), move the mouse (which will now have the text string attached)
  190. Xto the place where the text should be and click the left mouse button
  191. Xagain. The way the text string is attached to the mouse depends on the
  192. Xtext positioning attributes (left justified, centred, right-justified,
  193. Xetc).
  194. X
  195. X    Xpic tries to display onscreen text as a reasonable approximation of
  196. Xwhat you will see on the hardcopy output. This is subject to the
  197. Xavailability of reasonable fonts, and xpic's interfaces with the output
  198. Xdevices (the filter programs x2ps, x2pic, and x2tpic, documented below).
  199. XHowever, since the output medium (presently pic for troff, or PostScript) is
  200. Xlikely to have non-ascii characters which xpic cannot display easily on the
  201. Xscreen (not without putting the full pic or PostScript text semantics in
  202. Xxpic) there are bound to be differences. For example, the troff notation for
  203. Xbullet is \(bu - if you put this on screen, it will appear as such. If you
  204. Xprint it with pic and troff, it will come out on paper as a bullet. If you
  205. Xtry printing it with tpic and TeX, it will come out as \(bu. For tpic and
  206. XTeX, you have to say \bullet. For PostScript, you have to say \267.  In all
  207. Xcases, xpic will not understand and will print \(bu, \bullet or \267 on the
  208. Xscreen respectively. The user is expected to understand this. If you want
  209. Xsnazzy effects like special characters or equations on your output device,
  210. Xbe sure you understand the output device - xpic will try not to get it the
  211. Xway - it won't help much either.
  212. X
  213. XObviously, if you want a real honest-to-goodness backslash, you have to
  214. Xescape it with another backslash, for TeX, troff and PostScript. Backslash,
  215. Xin xpic text, like in most other aspects of Unix, is magic - it unleashes
  216. Xspells and incantations that are wondrous to behold if you know what you are
  217. Xdoing, and devastating if you don't. Beware.
  218. X
  219. XThe text interaction window is used whenever text is needed, or
  220. Xfilenames, or such-like. It allows a decent subset of EMACS (actually,
  221. XJOVE) commands to edit the text in the line. The usual concepts of
  222. Xpoint and mark apply, and killing, and yanking back killed text. Note
  223. Xthat there is no kill ring, or mark stack - and C-X performs the
  224. Xfunction of C-X C-X (There are no prefixes!) The keys to which
  225. Xcommands are bound can be changed : the default bindings are:
  226. X
  227. X    /* motion bindings */
  228. X
  229. X    <Ctrl>F:            forward-character
  230. X    <Key>168:           forward-character       /* Cursor -> key */
  231. X    <Ctrl>B:            backward-character
  232. X    <Key>167:           backward-character      /* Cursor <- key */
  233. X    <Ctrl>A:            beginning-of-line
  234. X    <Ctrl>E:            end-of-line
  235. X    <Ctrl>U:            universal-argument      /* Multiplies by four */
  236. X
  237. X    /* delete bindings */
  238. X
  239. X    <Ctrl>D:            delete-next-character
  240. X    <Ctrl>H:            delete-previous-character
  241. X    <Key>113:           delete-previous-character
  242. X    <Key>188:           delete-previous-character
  243. X
  244. X    /* kill bindings */ 
  245. X
  246. X    <Ctrl>X:            exchange-point-and-mark
  247. X    <Ctrl> :            make-this-the-mark
  248. X    <Ctrl>W:            kill-region
  249. X    <Ctrl>K:            kill-to-end-of-line
  250. X    <Meta>D:            kill-to-beginning-of-line
  251. X
  252. X    /* yank bindings */ 
  253. X
  254. X    <Ctrl>Y:            yank-killed-text
  255. X
  256. X    /* exit quit stuff */
  257. X
  258. X    <Ctrl>J:            newline
  259. X    <Key>115:           newline
  260. X    <Ctrl>M:            newline
  261. X    <Key>189:           newline
  262. X    <Ctrl>G:            abort
  263. X    <Ctrl>C:            abort
  264. X
  265. X    /* selection stuff */
  266. X
  267. X    <BtnDown>left:      set-cursor-to-mouse
  268. X    <BtnDown>middle:    set-mark-to-mouse
  269. X    <BtnDown>right:     get-x-buffer
  270. X
  271. XTheir functions should be sort-of obvious - if not, grab a Jove manual.
  272. X(USD-17 in the 4.3 manuals).  vi users have my sympathies. The minibuf
  273. Xbecomes the Focus of input whenever it is required, so you need not move
  274. Xthe mouse into the interaction window to type. When input is over, Focus is
  275. Xgiven to the RootWindow, as it presumably was before the program
  276. Xstarted. (If it wasn't, tough!) Clicking the left mouse button at a point in
  277. Xthe interaction window moves the point there, clicking the middle
  278. Xmouse button sets the mark there, (indicated by the text cursor flashing there
  279. Xbriefly) Clicking the right mouse button extracts the text in the global X cut
  280. Xbuffer and pastes it in at the point.
  281. X
  282. XChanging these bindings can be done by putting a file of bindings in the
  283. Xabove format (without the C style comments) somewhere, and adding the
  284. Xline 
  285. X    xpic.Minibuf.eventBindings:         filename
  286. X
  287. Xin you .Xdefaults file. 'filename' can be an absolute pathname (starting
  288. Xwith a '/') or a pathname relative to your home directory (starting without
  289. Xa '/'. i.e. the ~ character is implicit. ~ does not work, however.) See more
  290. Xon resources below. 
  291. X
  292. XNote that xpic will not go on if it expects input from the input window,
  293. Xunless a newline (RETURN, LINE-FEED) or abort (^G) is input. It does
  294. Xnot, however, stop other applications from continuing.
  295. X
  296. XThe editing operations have two modes, selected in the second button
  297. Xbox - they should be discussed before the editing functions.
  298. X
  299. XElement:
  300. X    This allows editing of individual objects. You select an
  301. Xobject to edit by going into the drawing window and clicking near
  302. Xit (after selecting one of the editing functions in the "Elements"
  303. Xbox) The selected object will highlight - lines, boxes, splines,
  304. Xellipses, circles by being redrawn thicker, and text will get a
  305. Xshaded box over it. If you happen to have selected the wrong
  306. Xobject, simply click the right mouse button (which will deselect
  307. Xthe object, i.e unhighlight it, and mark it rejected) and click the
  308. Xleft mouse button again. This time, it will select the second
  309. Xnearest object, since the first selection is marked as rejected.
  310. XYou can cycle through all objects on the screen without moving the
  311. Xmouse, simply by clicking the left and right button alternately.
  312. X
  313. X    Once selected, you can perform the appropriate editing
  314. Xoperation on the object.
  315. X
  316. XBlock:
  317. X    In this mode, you operate on all objects contained within a
  318. Xbox which you draw in the drawing window - first left mouse button
  319. Xclick sets one corner of the box, and the second mouse click sets the
  320. Xother corner. This will usually highlight all the elements within the
  321. Xbox, and put a box on the mouse cursor, which you can drag around and
  322. Xposition with another left click. The selected objects will be redrawn
  323. Xat the new position, and highlighted. You can keep dragging the box
  324. Xaround and repositioning it as long as you like - when you're
  325. Xsatisfied with the position/shape of the new object, click the right
  326. Xbutton and the objects unhighlight, and the drag box vanishes.
  327. X
  328. XThe editing operations available are:
  329. X
  330. XCopy:
  331. X    This makes a copy of the selected object(s). In element mode, it
  332. Xputs the copy of the object on the mouse cursor and allows you to
  333. Xdrag it around and place it with another click of the mouse. In block
  334. Xmode, you can drag the enclosing box around, which is why you get
  335. Xmultiple chances to place it - since you can't see all the elements
  336. Xmove.
  337. X
  338. XMove: 
  339. X    Similar to copy, except the objects in question themselves
  340. Xmove, instead of making a copy.
  341. X
  342. XDelete:
  343. X    The selected object(s) highlight, and you are prompted to
  344. Xclick again to confirm the delete. The most recently deleted
  345. Xelement/block is stored in a kill-buffer, and can be retrieved with a
  346. XPaste operation.
  347. X
  348. XPaste:
  349. X    A left click in the drawing window puts the element/block most
  350. Xrecently deleted on the mouse cursor and allows it to be dragged
  351. Xaround and positioned. (one try for elements, multiple tries for
  352. Xblocks, as usual)
  353. X
  354. XAdjust:
  355. X    This differs considerably in element and block modes. In
  356. Xelement mode, the selected object can be adjusted depending on the
  357. Xtype of object. For lines and splines, the nearest point in the
  358. Xline/spline is selected and moves with the mouse cursor, the object
  359. Xbeing redrawn appropriately. For boxes, the nearest corner is
  360. Xadjusted. In circles, the radius is changed. For ellipses, like boxes,
  361. Xthe nearest corner (of the enclosing box) is moved. Text is put in the
  362. Xminibuffer and can be edited - hitting return puts it back on the
  363. Xdrawing window.
  364. X
  365. X    In block mode, adjustment is primarily useful for lines and
  366. Xsplines. (But works on other objects). All control points within the
  367. Xblock are moved around. (This is an exception to the strict
  368. Xcontainment rule which applies to all other block operations. Here,
  369. Xeven those elements which have only part of them in the selected block
  370. Xare selected). For lines/splines, the control points are any point,
  371. Xfor a boxes/ellipses, they are any corner enclosed, for circles, the
  372. Xcentres are the control points, and for text, the text origin is the
  373. Xcontrol point moved. This mode is best learnt by experimenting - it is
  374. Xmore easily seen than described.
  375. X
  376. XGet, Put:
  377. X    These work only in block mode (and make loud and persistent
  378. Xcomplaints if selected in element mode). Get will prompt for the name
  379. Xof an xpic file when the left mouse button is cliecked in the drawing
  380. Xwindow, and will read it in, and put the enclosing box on the
  381. Xmouse cursor to be positioned. The elements from the file will be
  382. Xinserted into the figure. 
  383. X
  384. X    Put does exactly the reverse - it prompts for a file name to
  385. Xsave the selected block to. The saved file can be read in with the Get
  386. Xcommand, or used as a full xpic picture (xpicture?)  in its own right.
  387. X
  388. XChange Attributes:
  389. X    This will change the attributes of the selected object(s) to
  390. Xthe current set of attributes. Th eattributes are described below.
  391. X
  392. X Attributes
  393. X ----------
  394. X
  395. XThe following attributes affect all objects excpet Text. (i.e. Line,
  396. XSpline, Box, Circle, Ellipse).
  397. X
  398. XPatterns:
  399. X    The five patterns are Solid, Dotted, Short-Dashed,
  400. XLong-Dashed, and Dot-Dashed.
  401. X
  402. XLine Thickness:
  403. X    Ranges from 0 to 10. A zero line width means a thin line, that
  404. Xis half the width of a line of width 1, but is drawn with the same
  405. Xwidth as a line of width 1 because of screen resolution.
  406. X
  407. X    This attribute affects only lines and splines:
  408. X
  409. XArrows:
  410. X    Whether to draw arrows at the start of a line, the end of a
  411. Xline, both ends of a line, or not at all.
  412. X
  413. X
  414. XThe following attributes apply to only Text objects:
  415. X
  416. XFont:
  417. X    This is an updown button - it will display the current font.  By
  418. Xclicking the right or left button, one can cycle through the available fonts
  419. X- which are determined from the X server.  See the section on fonts (later)
  420. Xfor more on this.
  421. X
  422. XPoint Size:  
  423. X    Also an updown button, which permits cycling through the
  424. Xavailable pointsizes for the current font. 
  425. X
  426. XText Vertical, Horizontal Alignment:
  427. X    These two boxes indicate how the text should be placed at the
  428. Xmouse position. The vertical alignment Top means that the mouse is at
  429. Xthe Top of the text, Middle is for the mouse at the bottom of the
  430. Xtext, and Bottom means that the mouse is below the text.
  431. X
  432. X    The horizontal alignment decides if the mouse if to be to the
  433. XLeft, Centre, or Right of the text.
  434. X
  435. XThe next attribute decides how to round off the mouse position:
  436. X
  437. XSnap:
  438. X    The grid points are 8 pixels apart. There are 10 grid points
  439. Xto every inch. (i.e 80 points per inch). The default snap value makes
  440. Xsure that all points in the diagram are rounded off to the nearest
  441. Xgrid point. This makes drawing precise figures much easier. If you
  442. Xneed more resolution, you can reduce the snap value (snap of 1 means
  443. Xthat there is no real snap) or increase it. Since X Windows does the
  444. Xmouse cursor tracking, you can move the cursor in between the grip
  445. Xpoints even at snap of 8. But the rubber banding of the objects will
  446. Xshow you the effect of snap - objects will not allow you to select a
  447. Xpixel in between two grid points if you have a snap of 8.
  448. X
  449. X Command Boxes
  450. X -------------
  451. X
  452. XThe file operations are:
  453. X
  454. XRead:
  455. X    Reads in a new file and puts it into a new cell. (Eventually,
  456. Xyou should be able to switch between buffers easily. For now, it isn't
  457. Xpossible, so xpic insists you must save a file before reading in
  458. Xanother one).
  459. X
  460. XSave:
  461. X    Saves the current cell in a file. If the cell has no filename
  462. Xassociated with it, it will prompt for a cell in the interaction
  463. Xwindow. When xpic saves a file, it makes a backup of the file before
  464. Xthe save in a file of the form filename~ for the file filename.
  465. X
  466. XSave As:
  467. X    It will prompt for a filename in the interaction window, and
  468. Xsave the cell there. From then on, the new filename is th eone
  469. Xassociated with the cell.
  470. X
  471. X
  472. XThe miscellaneous operations are:
  473. X
  474. XUndo:
  475. X    This extremely handy operation allows one level of undo - it
  476. Xwill exactly undo the last operation performed EXCEPT for File
  477. Xoperations. Also, undo is effective for block operations immediately
  478. Xafter the block operation only. The first edit operation performed
  479. X(even if it is aborted) after a block operation makes the undo
  480. Ximpossible (and strange things will happen if the undo is performed -
  481. Xthis is due to the way undo is implemented; unlikely to change).  If
  482. Xundo is clicked twice, the first undo is undone. 
  483. X
  484. XRedisplay:
  485. X    Refreshes the drawing window, and cleans up internal data structures
  486. Xsomewhat. (xpic will automatically refresh itself if the window is
  487. Xobscured and later exposed)
  488. X
  489. XGrid:
  490. X    Toggles the grid on and off. With th egrid off, you usually
  491. Xget a reasonable idea of what the picture will look when on paper.
  492. XThis wins the least used command sweepstakes hands-down.
  493. X
  494. XStatus:
  495. X    Prints the status of the buffer, in the form
  496. X
  497. XXPIC version.patchlevel   Buffer: buffername   File: filename   [Modified]
  498. X
  499. X    The [Modified] flag indicates that changes have been made to
  500. Xthe picture since it was last saved.
  501. X
  502. XExit:
  503. X    The advanced user will deduce what this is for.
  504. X
  505. X Resources
  506. X ---------
  507. X
  508. XThe buttons and button boxes used by xpic are standard toolkit items, their
  509. Xresources may be set easily. The interaction window and drawing window have
  510. Xthe following resource names:
  511. X
  512. X                            name                class
  513. X    Program:                xpic                XPic
  514. X    Form enclosing it:      form                Form
  515. X    Interaction window:     minibuf             Minibuf
  516. X    Drawing Window:         picture             Window
  517. X    Labels:                 label               StaticText
  518. X    ButtonBoxes:            label.box           RowCol
  519. X    Buttons:                button name         PushButton
  520. X
  521. XProgram level resources are
  522. X    Resource name           Resource class      default
  523. X    name                    Name                xpic
  524. X    iconGeometry            IconGeometry        (none)
  525. X    iconPixmap              IconPixmap          one is provided
  526. X    pageWidth               PageWidth           85
  527. X    pageHeight              PageHeight          105
  528. X    gridSpacing             GridSpacing         8
  529. X    gridOn                  GridOn              True
  530. X    gridColor               GridColor           Black
  531. X    cursorColor             CursorColor         Black
  532. X    highlight               Highlight           Black
  533. X    rotate                  Rotate              False
  534. X    backup                  Backup              True
  535. X    printer                 Printer             PostScript
  536. X    lprcommand              LprCommand          x2ps -w | lpr -P%s
  537. X    
  538. XA sample resource file is: 
  539. X
  540. X    xpic*picture.background:    #80cfdf
  541. X    xpic*picture.foreground:    black
  542. X    xpic*RowCol.background:        MediumTurquoise
  543. X    xpic*RowCol.borderWidth:    0
  544. X    xpic*PushButton.font:        helv10b
  545. X    xpic*PushButton.background:    SkyBlue
  546. X    xpic*PushButton.foreground:    DarkSlateGrey
  547. X    xpic*PushButton.border:        MediumAquamarine
  548. X    xpic*Minibuf.background:    #13e5e5
  549. X    xpic*Minibuf.foreground:    black
  550. X    xpic*Minibuf.font:        9x15
  551. X    xpic*Minibuf.borderWidth:    0
  552. X    xpic*StaticText.background:    white
  553. X    xpic*StaticText.font:        fg-13
  554. X    xpic*StaticText.borderWidth:    0
  555. X    xpic*background:        SkyBlue
  556. X    
  557. X Output
  558. X ------
  559. X    Xpic saves files in an internal, (ascii) easy to read/write
  560. Xformat (easy for xpic and me, that is!) This format can be translated
  561. Xinto PostScript and pic.
  562. X
  563. Xpic:
  564. X    Use the program x2pic - no options etc. Just
  565. X        x2pic [-s scale] [-f numfonts] [filename] ...
  566. X
  567. X-s scale 
  568. Xscales the picture by 'scale', where scale can be a float. It tries to
  569. Xscale the fonts too, unlike pic's scale command, but don't expect
  570. Xmiracles.
  571. X
  572. X-f numfonts
  573. Xsets the maximum number of fonts in the font mapping table. See the
  574. Xsection on fonts below. The default is usually adequate unless the
  575. Xuser has lots of fonts in the ~/.x2pic or ~/.x2tpic file.
  576. X
  577. XEach file becomes a separate .PS/.PE and the pic output is written to
  578. Xstdout. If no filename is given, it is read from stdin.
  579. X
  580. XThen process it normally through pic. Note that the fonts on the screen
  581. Xmatch the output fonts closely, but not perfectly.  So don't try to draw
  582. Xboxes/ellipses/stuff around text with no tolerance - be generous.
  583. X(Remember the old cartoonists adage - draw the bubble AFTER the text,
  584. Xnot before)
  585. X
  586. Xpic cannot do anything other than solid circles/ellipses/splines. It
  587. Xhas a silent limit of 50 points per spline which it enforces by core
  588. Xdump.
  589. X
  590. XThere is a similar program called x2tpic which generates almost
  591. Xexactly the same output, but with font style/size selection commands
  592. Xin TeX. It can be used with tpic.
  593. X
  594. XPostScript:
  595. X    x2ps [-w] [-r] [-x] [-s scale] [-p prologuefile] [-t trailerfile] 
  596. X        [-f numfonts] [-h hoffset] [-v voffset] [filename] ....
  597. X
  598. X-w WYSIWYG mode, prints the figure as it was in the screen without moving the
  599. Xpicture so the picture's lower left corner is at the page lower left corner.
  600. XUseful for sending the picture straight to the printer. (The Print button on
  601. Xxpic uses this by default. If you don't have a PostScript printer, you
  602. Xmay want to change the printing command to use x2pic, pic, and troff)
  603. X
  604. X-r prints the figure in landscape mode, rotated by 90 degrees. It
  605. Xgoes together with the -r option on xpic.
  606. X
  607. X-x suppresses the showpage emitted by x2ps - LaTeX used to need this.
  608. X(Locally, we've fixed LaTeX by defining /showpage to be null in the 
  609. Xspecial header).
  610. X
  611. X-s scale 
  612. Xscales the picture by 'scale', where scale can be a float.
  613. X
  614. X-p prologuefile
  615. X-t trailerfile
  616. Xspecify the prologue and trailer to be used. The defaults are
  617. X/usr/local/lib/xpic/x2ps.pro and x2ps.tra. Use these only if you know
  618. Xwhat you're doing. Typically, you'd take x2ps.{pro,tra} and modify
  619. Xthem to change something you don't like - or you think is buggy. On
  620. Xyour own head be it.
  621. X
  622. X-h hoffset
  623. X-v voffset
  624. Xspecify the horizontal and vertical offset to add to the figure, in
  625. Xinches. hoffset and voffset may be floats.
  626. X
  627. X-f numfonts
  628. Xsets the maximum number of fonts in the font mapping table. See the
  629. Xsection on fonts below. The default is usually adequate unless the
  630. Xuser has lots of fonts in the ~/.x2ps file.
  631. X
  632. X FONTS
  633. X -----
  634. X    xpic reads a font description file to decide what fonts it can use
  635. Xfrom the server, and to deal with differing resolutions of available screen
  636. Xfonts.  The fontdesc file should be something like 
  637. X
  638. X    <Full name(used in label)> <prefix> <fontname-root>
  639. X
  640. XThe actual font name would be prefix.fontname-root.size[.<dots-per-inch>]
  641. Xwhere size is a point size, at the specified dots-per-inch.
  642. X
  643. X(eg)
  644. XItalic    devsun    i
  645. XRoman    devsun    r
  646. XBold    devsun    b
  647. XSpecial    devsun    s
  648. XItalic    xpic    i
  649. XBold    xpic    r
  650. XSpecial    xpic    s
  651. XRoman    xpic    r
  652. X
  653. Xsays that fonts of the form devsun.i.* (where the * is the point
  654. Xsize) are Italic fonts. Xpic will scale font point sizes to the
  655. Xscreen resolution. If more than one font of the same Full name,
  656. Xand effective point size at the current screen resolution exists,
  657. Xthen the first one gets used.
  658. X
  659. XTo set the default, a line of the form 
  660. X    default <Full name> <pointsize>
  661. Xcould be put in. (If it isn't there, the default is the first fontname
  662. Xand the first size of that font.
  663. X
  664. XThe default fontdesc file it reads is XPICLIBDIR/fontdesc/xpic. It also 
  665. Xchecks for a ~/.xpic file, and anything in that overrides the system
  666. Xdefaults.
  667. X
  668. X    x2pic uses a similar fontdesc file, which lists the mapping of
  669. Xxpic font names to pic (or really, troff) font changing commands.
  670. X
  671. X(eg)
  672. XRoman     \fR
  673. XItalic     \fI
  674. XBold     \fB
  675. XSpecial    \fS
  676. XBigBold    \f(BB
  677. X
  678. XThe default x2pic fontdesc is in XPICLIBDIR/fontdesc/x2pic, and it also
  679. Xreads ~/.x2pic.
  680. X
  681. X    x2ps does the same thing to map xpic font names to PostScript names.
  682. X
  683. X(eg)
  684. XRoman Times-Roman
  685. XItalic Times-Italic
  686. XBold Times-Bold
  687. XSpecial Symbol
  688. XBigBold Helvetica-Bold
  689. X
  690. XThe default x2ps fontdesc is in XPICLIBDIR/fontdesc/x2ps, and it also
  691. Xreads ~/.x2ps.
  692. X
  693. X
  694. X    x2tpic has a slightly more complex font description file,
  695. Xwhich has the following fields:
  696. X    <Full xpic name> <pointsize> <tex name> <tex font> <optional tex scale>
  697. X
  698. X(eg)
  699. XRoman     9        \Xninerm    cmr9
  700. X
  701. X-- maps xpic Roman, 9 pt, to the name \Xninerm, corresponding to cmr9.
  702. X
  703. XRoman     11        \Xelevenrm    cmr10  \magstephalf
  704. X
  705. X-- maps xpic Roman, 11 pt, to the name \Xelevenrm, corresponding to
  706. Xcmr10, scaled by magstephalf. (See the TeXbook for more in this)
  707. X
  708. XItalic     6        \Xsixit        cmti7  857
  709. X
  710. X-- maps xpic Italic, 6 pt, to the name \Xsixit, corresponding to cmti7
  711. Xscaled 857.
  712. X
  713. XSpecial 6        \Xsixsp        PS-Symbol pointsize6
  714. X
  715. X-- We store the .tfm file for PostScript(tm) fonts under the names
  716. XPS-postscriptname. (eg) PS-Symbol. Other sites may use different names
  717. X(eg) pssymbol. The above line generates the appropriate scaled at
  718. Xcommand to get 6 point Symbol.
  719. X
  720. Xx2tpic will search this table to find the closest font to the one
  721. Xrequested. It will find the closest size in either the same font style
  722. Xor Roman.
  723. X
  724. XIf you want to add to the table, keep the entries in ~/.x2tpic.
  725. XUsually, your system will have the right map of fonts in the default.
  726. XIf not, ask the person who installed xpic to talk to the person who
  727. Xlooks after TeX.
  728. X
  729. X BUGS
  730. X ----
  731. XPlease report bugs to me, as specifically as you can. Note that if
  732. Xthe system crashes, xpic cannot retrieve work like text editors.
  733. XIf xpic dies due to some unpleasant cause (program error, network
  734. Xerror, a signal), it dumps the current unsaved cell into some
  735. Xtemporary directory - usually /tmp.
  736. X
  737. XIf you make improvements, or think they should be made, tell me. If
  738. Xyou send code, please use context diffs - the -c flag on diff.
  739. X
  740. XGood luck.
  741. X
  742. X-----------
  743. X+ PostScript is a trademark of Adobe, Inc.
  744. END_OF_FILE
  745. if test 29158 -ne `wc -c <'xpic/doc/xpic.doc'`; then
  746.     echo shar: \"'xpic/doc/xpic.doc'\" unpacked with wrong size!
  747. fi
  748. # end of 'xpic/doc/xpic.doc'
  749. fi
  750. if test -f 'xpic/xpic.c' -a "${1}" != "-c" ; then 
  751.   echo shar: Will not clobber existing file \"'xpic/xpic.c'\"
  752. else
  753. echo shar: Extracting \"'xpic/xpic.c'\" \(20476 characters\)
  754. sed "s/^X//" >'xpic/xpic.c' <<'END_OF_FILE'
  755. X/* $Header: xpic.c,v 1.5 89/04/21 03:32:24 xwindows Exp $ */
  756. X/*
  757. X *  This file contains lots of basic routines which manipulate the data
  758. X *  and create/free/read/write various structures
  759. X */
  760. X
  761. X#include <strings.h>
  762. X#include <sys/types.h>
  763. X#include <sys/param.h>
  764. X#ifndef MAXPATHLEN
  765. X# ifdef PATH_MAX
  766. X#  define MAXPATHLEN    PATH_MAX
  767. X# else
  768. X   /* If you haven't got either MAXPATHLEN or PATH_MAX defined, ouch! */
  769. X#  define MAXPATHLEN    256
  770. X# endif
  771. X#endif
  772. X#include <sys/stat.h>
  773. X#include <stdio.h>
  774. X#include <values.h>
  775. X
  776. X#include "xpic.h"
  777. X#include "windows.h"
  778. X#include "input.h"
  779. X#include "gels.h"
  780. X#include "tune.h"
  781. X#include "newfonts.h"
  782. X#include "assert.h"
  783. X
  784. X#define round(x)    ((int) ((x) + 0.5))
  785. X#define xfree(x)    if (x) free(x); else
  786. X
  787. X/* 
  788. X *  basic bounding box manipulation routines (may write them later as
  789. X *  macros if I think the speed improvement warrants it.) Note that
  790. X *  'contains' means 'p' lying within or on the bounding box 'clip', hence
  791. X *  'intersects' means 'b' intersecting or touching 'clip'.
  792. X */
  793. X
  794. XBOOL containsXY(x, y, clip)
  795. Xregister int x, y;
  796. Xregister Box *clip;
  797. X{
  798. X    return((x >= clip->ll.x) && (x <= clip->ur.x) &&
  799. X     (y >= clip->ll.y )&& (y <= clip->ur.y));
  800. X}
  801. X
  802. XBOOL contains(p, clip)
  803. Xregister Point *p;
  804. Xregister Box *clip;
  805. X{
  806. X    return((p->x >= clip->ll.x) && (p->x <= clip->ur.x) &&
  807. X     (p->y >= clip->ll.y )&& (p->y <= clip->ur.y));
  808. X}
  809. X
  810. X/* 
  811. X *  If two boxes intersect, then the area of intersection must be
  812. X *  positive, i.e. ur.x of the intersection > ll.x AND ur.y > ll.y where
  813. X *  ur.x of the intersection is the minimum of the ur.x of the two
  814. X *  boxes, and the ll.x is the maximum of the ll.x of the two boxes
  815. X *  (similarly for y). (Assuming ll.x < ur.x, ll.y < ur.y ALWAYS for all
  816. X *  boxes.)
  817. X */
  818. XBOOL intersects(b, clip)
  819. Xregister Box *b;
  820. Xregister Box *clip;
  821. X{
  822. X    return ( (MAX(b->ll.x, clip->ll.x) <= MIN(b->ur.x, clip->ur.x)) &&
  823. X         (MAX(b->ll.y, clip->ll.y) <= MIN(b->ur.y, clip->ur.y)) );
  824. X}
  825. X
  826. X
  827. X/* Returns TRUE if box 'b' lies ENTIRELY within 'clip' */
  828. XBOOL within(b, clip)
  829. Xregister Box *b;
  830. Xregister Box *clip;
  831. X{
  832. X    return(contains(&(b->ll), clip) && contains(&(b->ur), clip));
  833. X}
  834. X
  835. X
  836. X/*
  837. X *  Frees the vertex buffer of a pointlist, and the pointlist itself
  838. X */
  839. Xvoid FreePtList(pt)
  840. Xregister PointList *pt;
  841. X{
  842. X    if (!pt)
  843. X        return;
  844. X    xfree((char *) pt->v);
  845. X    free((char *) pt);
  846. X}
  847. X
  848. X
  849. X/*
  850. X *  Takes a XPoint array, mallocs space for N points, and copies the first
  851. X *  N points from the given XPoint array to the PointList
  852. X */
  853. XPointList *NewPtList(vertices, n)
  854. Xregister XPoint *vertices;
  855. Xint n;
  856. X{
  857. X    PointList *thisPtList;
  858. X    
  859. X    if ((thisPtList = (PointList *) malloc(sizeof(PointList))) == NULL) {
  860. X        message("NewPointList: Can't get memory for new pointlist element");
  861. X        return( (PointList *) NULL);
  862. X    }
  863. X
  864. X    if ((thisPtList->v = (XPoint *) calloc((unsigned) n, sizeof(XPoint)))
  865. X     == NULL) {
  866. X        message("NewPointList: Can't get memory for new vertex list");
  867. X        free((char *) thisPtList);
  868. X        return( (PointList *) NULL);
  869. X    }
  870. X
  871. X    thisPtList->nVerts = n;
  872. X
  873. X    (void) bcopy((char *) vertices, (char *) (thisPtList->v),
  874. X     (int) (n * sizeof(XPoint)));
  875. X     
  876. X    return(thisPtList);
  877. X}
  878. X
  879. X
  880. X/* Reads in a pointlist from the current inFile */
  881. XPointList *ReadPtList(scale, type)
  882. Xdouble scale;
  883. Xint type;
  884. X{
  885. X    PointList *thisPtList;
  886. X    register XPoint *tmp;
  887. X    register int i, n;
  888. X    int x, y;
  889. X    
  890. X    if ((thisPtList = (PointList *) malloc(sizeof(PointList))) == NULL) {
  891. X        message("Can't get memory for new pointlist");
  892. X        return( (PointList *) NULL);
  893. X    }
  894. X
  895. X    if (fscanf(inFile, " %d", &(thisPtList->nVerts)) != 1) {
  896. X        free((char *) thisPtList);
  897. X        return( (PointList *) NULL);
  898. X    }
  899. X
  900. X    if (type == SPLINE)
  901. X         thisPtList->nVerts += 2;
  902. X
  903. X    n = thisPtList->nVerts;
  904. X
  905. X    if ((thisPtList->v = (XPoint *) calloc((unsigned) n, sizeof(XPoint)))
  906. X     == NULL) {
  907. X        message("Can't get memory for new vertex list");
  908. X        free((char *) thisPtList);
  909. X        return( (PointList *) NULL);
  910. X    }
  911. X
  912. X    tmp = thisPtList->v;
  913. X    if (type == SPLINE) {
  914. X        tmp++;
  915. X        n -= 2;
  916. X    }
  917. X
  918. X    for (i = 0; i < n; i++, tmp++) {
  919. X        if (fscanf(inFile, " %d %d", &x, &y) != 2) {
  920. X            FreePtList(thisPtList);
  921. X            return((PointList *) NULL);
  922. X        }
  923. X        tmp->x = round(x * scale);
  924. X        tmp->y = round(y * scale);
  925. X    }
  926. X    return(thisPtList);
  927. X}
  928. X
  929. X
  930. X/* writes out a pointlist to the current outFile */
  931. Xvoid WritePtList(pt, type)
  932. XPointList *pt;
  933. Xint type;
  934. X{
  935. X    register int i, j, n;
  936. X    register XPoint *vert;
  937. X    
  938. X    vert = pt->v;
  939. X    n = pt->nVerts;
  940. X    if (type == SPLINE) {
  941. X        vert++;
  942. X        n -= 2;
  943. X    }
  944. X
  945. X    (void) fprintf(outFile, "%d\n", n);
  946. X
  947. X    for (i = 0, j = 1; i < n; i++, vert++, j++) {
  948. X        (void) fprintf(outFile, " %d %d", vert->x, vert->y);
  949. X        if (j == 4) {
  950. X            j = 0;
  951. X            (void) fputc('\n', outFile);
  952. X        }
  953. X    }
  954. X    if (j != 1)
  955. X        (void) fputc('\n', outFile);
  956. X}
  957. X
  958. X
  959. X/*
  960. X *  makes a Gel
  961. X */
  962. XGel *NewGel()
  963. X{
  964. X    Gel *thisGel;
  965. X    
  966. X    if ((thisGel = (Gel *) malloc(sizeof(Gel))) == NULL) {
  967. X        message("NewGel: Can't get memory for new element");
  968. X        return( (Gel *) NULL);
  969. X    }
  970. X
  971. X    /* Null the pointers, and other fields */
  972. X    bzero((char *) thisGel, sizeof(Gel));
  973. X    
  974. X    thisGel->number = GelCounter++;
  975. X    
  976. X    return (thisGel);
  977. X}
  978. X
  979. X
  980. X/*
  981. X *  Traverse the linked list, freeing each gel - for some items like line,
  982. X *  may need to traverse sub-lists i.e ptlist
  983. X */
  984. Xvoid FreeGel(g)
  985. Xregister Gel *g;
  986. X{
  987. X    register Gel *tmp = g;
  988. X
  989. X    while (tmp != NULL) {
  990. X        switch (tmp->type) {
  991. X        case LINE:
  992. X        case SPLINE:
  993. X            FreePtList( (PointList *) tmp->data);
  994. X            break;
  995. X        case TEXT:
  996. X            {
  997. X                TextString *tmp_text = (TextString *) tmp->data;
  998. X                if (tmp_text) xfree(tmp_text->str);
  999. X                xfree( (char *) tmp_text);
  1000. X            }
  1001. X            break;
  1002. X        case CIRCLE:
  1003. X        case ELLIPSE:
  1004. X            xfree(tmp->data);
  1005. X            break;
  1006. X        default:
  1007. X            break;
  1008. X        }
  1009. X        tmp = tmp->next;
  1010. X        free ((char *) g);
  1011. X        g = tmp;
  1012. X    }
  1013. X}
  1014. X
  1015. X
  1016. X/*
  1017. X *  Pushes a list of Gels (g) onto another list of gels (stack). It
  1018. X *  returns the number of gels pushed onto the stack.
  1019. X */
  1020. Xint PushGel(stack, g)
  1021. Xregister Gel *g, **stack;
  1022. X{
  1023. X    register Gel *tmp;
  1024. X    register i = 0;
  1025. X    
  1026. X    while(g != NULL) {
  1027. X        tmp = g->next;
  1028. X         g->next = *stack;
  1029. X        *stack = g;
  1030. X        g = tmp;
  1031. X        i++;
  1032. X    }
  1033. X    return(i);
  1034. X}
  1035. X
  1036. X
  1037. X/*
  1038. X *  Pushes the list of gels g onto the stack, AFTER popping off N
  1039. X *  elements. The N elements are then pushed back on. This is used by
  1040. X *  aborts, when a gel needs to be pushed back onto the stack, without
  1041. X *  disturbing the top undo elements. Note that the N returned MAY NOT
  1042. X *  be used for undo purposes, since it is not from the top of the
  1043. X *  stack. Note also that this does not completely solve the problem,
  1044. X *  because if you select one of the top undo elements, and then try an
  1045. X *  undo, things get confused, In short - don't undo too long after you
  1046. X *  do!
  1047. X */
  1048. Xint PushUnderUndo(stack, g, n)
  1049. Xregister Gel **stack;
  1050. Xregister Gel *g;
  1051. Xregister int n;
  1052. X{
  1053. X    Gel *tmp;
  1054. X
  1055. X    tmp = PopGel(stack, n);
  1056. X    n = PushGel(stack, g);
  1057. X    (void) PushGel(stack, tmp);
  1058. X    return(n);
  1059. X}
  1060. X
  1061. X    
  1062. X/*
  1063. X *  This pops N gels off the stack and returns a pointer to the list
  1064. X */
  1065. XGel *PopGel(stack, n)
  1066. Xregister Gel **stack;
  1067. Xint n;
  1068. X{
  1069. X    register Gel *g, *tmp;
  1070. X    register int i;
  1071. X
  1072. X    for(i = 0, g = NULL; i < n && *stack != NULL; i++) {
  1073. X        tmp = (*stack)->next;
  1074. X        (*stack)->next = g;
  1075. X        g = *stack;
  1076. X        *stack = tmp;
  1077. X    }
  1078. X    return(g);
  1079. X}
  1080. X
  1081. X
  1082. X/*
  1083. X *  Counts the number of Gels in a gellist
  1084. X */
  1085. Xint CountGel(gel)
  1086. Xregister Gel *gel;
  1087. X{
  1088. X    register int i = 0;
  1089. X    
  1090. X    for (; gel != NULL; gel = gel->next, i++)
  1091. X        ;
  1092. X    return(i);
  1093. X}
  1094. X/* 
  1095. X *  This returns the bounding box of a gel list. Since the bounding box is
  1096. X *  returned in a static struct, it must not be modified or changed.
  1097. X */
  1098. XBox *GetBBox(g)
  1099. Xregister Gel *g;
  1100. X{
  1101. X    static Box b;
  1102. X
  1103. X    b.ur.x = b.ur.y = 0;
  1104. X    b.ll.x = b.ll.y = MAXINT;
  1105. X    while (g != NULL) {
  1106. X        bigger_box(b, g->b_box);
  1107. X        g = g->next;
  1108. X    }
  1109. X    return(&b);
  1110. X}
  1111. X        
  1112. X
  1113. X/* 
  1114. X *  Just traverse the linked list, writing out all elements in the Gel
  1115. X *  list to outFile
  1116. X */
  1117. Xvoid WriteGel(g)
  1118. Xregister Gel *g;
  1119. X{
  1120. X    Conic *conic;
  1121. X    TextString *text;
  1122. X    Box *b;
  1123. X
  1124. X#ifdef MAGIC
  1125. X    /* Write out the magic string, using the appropriate invocation */
  1126. X    (void) fprintf(outFile, "#! %s\n", PROGRAMNAME);
  1127. X#endif MAGIC
  1128. X    /* First write out Gel bounding box */
  1129. X    CalcBBox(g, MAXINT);
  1130. X    b = GetBBox(g);
  1131. X    (void) fprintf(outFile, "%d %d %d %d %d\n", b->ll.x, b->ll.y,
  1132. X     b->ur.x, b->ur.y, gridSpacing);
  1133. X
  1134. X    /* Now write out the Gel list */
  1135. X    for (;g != NULL; g = g->next) {
  1136. X        (void) fprintf(outFile, "%d %d %d %d %d %d %x %d\n", g->type,
  1137. X         g->number, g->b_box.ll.x, g->b_box.ll.y,
  1138. X         g->b_box.ur.x, g->b_box.ur.y, g->attributes, g->linewidth);
  1139. X        switch (g->type) {
  1140. X        case BOX:
  1141. X            break;
  1142. X        case ELLIPSE:
  1143. X            conic = (Conic *) g->data;
  1144. X            (void) fprintf(outFile, "%d %d %d %d\n", conic->centre.x, 
  1145. X             conic->centre.y, conic->xrad, conic->yrad);
  1146. X            break;
  1147. X        case CIRCLE:
  1148. X            conic = (Conic *) g->data;
  1149. X            (void) fprintf(outFile, "%d %d %d\n", conic->centre.x, 
  1150. X             conic->centre.y, conic->xrad);
  1151. X            break;
  1152. X        case TEXT:
  1153. X            text = (TextString *) g->data;
  1154. X            (void) fprintf(outFile, "%d %d %d %s %d\n%s\n", text->x, text->y,
  1155. X             text->length, text->fontname, text->fontsize, text->str);
  1156. X            break;
  1157. X        case LINE:
  1158. X        case SPLINE:
  1159. X            WritePtList((PointList *) g->data, g->type);
  1160. X            break;
  1161. X        }
  1162. X    }
  1163. X}
  1164. X
  1165. X
  1166. Xstatic char *strsave(s)
  1167. Xchar *s;
  1168. X{
  1169. X    char *s1 = XtMalloc((unsigned) (strlen(s) + 1));
  1170. X
  1171. X    if (s1)
  1172. X        (void) strcpy(s1, s);
  1173. X    return(s1);
  1174. X}
  1175. X
  1176. X
  1177. X/*
  1178. X *  Read in and make a linked list of Gel items from inFile
  1179. X */
  1180. XGel *ReadGel()
  1181. X{
  1182. X    Gel *g;
  1183. X    int type;
  1184. X    int xc, yc, xr, yr, len, attr;
  1185. X    int size;
  1186. X    char font[MAXSTR];
  1187. X    int x1, y1, x2, y2, gs;
  1188. X    char *s;
  1189. X    int c;
  1190. X    int err, nf;
  1191. X    PointList *ptlist;
  1192. X    double scale;
  1193. X    int num, thickness;
  1194. X    FontFamily *fptr;
  1195. X    char *fontname;
  1196. X
  1197. X#define NOMEM 1
  1198. X#define INPERR 2
  1199. X#define INPEOF 3
  1200. X
  1201. X    err = 0;
  1202. X    g = NULL;
  1203. X    ASSERT(allock(), "test 1");
  1204. X#ifdef MAGIC
  1205. X    /* Check for the magic header that the new xpic puts out */
  1206. X    if ((c = getc(inFile)) == EOF) {
  1207. X        message("Incorrect input format");
  1208. X        return(NULL);
  1209. X    }
  1210. X    ASSERT(allock(), "test 2");
  1211. X    (void) ungetc(c, inFile);
  1212. X    if (c == '#') {
  1213. X        /* Magic header - ignore */
  1214. X        (void) fscanf(inFile, "%*[^\n]");
  1215. X    }
  1216. X#endif MAGIC
  1217. X    /* Read in (and ignore) the gel bounding box */
  1218. X    if (fscanf(inFile, " %d %d %d %d %d", &x1, &y1, &x2, &y2, &gs) != 5) {
  1219. X        message("Incorrect input format");
  1220. X        return(NULL);
  1221. X    }
  1222. X    
  1223. X    if (gs == 0) {
  1224. X        message("Incorrect input.");
  1225. X        return(NULL);
  1226. X    }
  1227. X
  1228. X    scale = ((double) gridSpacing) / gs;
  1229. X    
  1230. X    /* Read in the actual list */
  1231. X    do {
  1232. X        if ((nf = fscanf(inFile, " %d", &type)) != 1) {
  1233. X            err = INPEOF;
  1234. X            break;
  1235. X        }
  1236. X        nf = fscanf(inFile, " %d %d %d %d %d %x %d", &num, &x1, &y1, 
  1237. X         &x2, &y2, &attr, &thickness);
  1238. X        if (nf != 7) {
  1239. X            err = INPERR;
  1240. X            break;
  1241. X        }
  1242. X        x1 = round(x1 * scale);
  1243. X        x2 = round(x2 * scale);
  1244. X        y1 = round(y1 * scale);
  1245. X        y2 = round(y2 * scale);
  1246. X        switch (type) {
  1247. X        case BOX:
  1248. X            AddBoxGel(&g, x1, y1,x2, y2, attr, thickness);
  1249. X            break;
  1250. X        case ELLIPSE:
  1251. X            nf = fscanf(inFile, " %d %d %d %d", &xc, &yc, &xr, &yr) ;
  1252. X            if (nf != 4) {
  1253. X                err = INPERR;
  1254. X                break;
  1255. X            }
  1256. X            xc = round(xc * scale);
  1257. X            yc = round(yc * scale);
  1258. X            xr = round(xr * scale);
  1259. X            yr = round(yr * scale);
  1260. X            AddConicGel(&g, type, xc, yc, xr, yr, attr, x1, y1, x2, y2, thickness);
  1261. X            break;
  1262. X        case CIRCLE:
  1263. X            nf = fscanf(inFile, " %d %d %d", &xc, &yc, &xr);
  1264. X            if (nf != 3) {
  1265. X                err = INPERR;
  1266. X                break;
  1267. X            }
  1268. X            xc = round(xc * scale);
  1269. X            yc = round(yc * scale);
  1270. X            xr = round(xr * scale);
  1271. X            AddConicGel(&g, type, xc, yc, xr, xr, attr, x1, y1, x2, y2, thickness);
  1272. X            break;
  1273. X        case TEXT:
  1274. X            nf = fscanf(inFile, " %d %d %d %s %d", &xc, &yc, &len, font, 
  1275. X             &size);
  1276. X            if (nf != 5) {
  1277. X                err = INPERR;
  1278. X                break;
  1279. X            }
  1280. X            /*
  1281. X             *  For backward compatibility with the bad old days. The
  1282. X             *  old convention of storing font information was really
  1283. X             *  ugly - a font number from 0-3, (corresponding to Roman,
  1284. X             *  Bolld, Italic, Special) and a size from 0-9
  1285. X             *  (corresponding to point sizes 6 - 24)
  1286. X             */
  1287. X            if (font[1] == '\0') {
  1288. X                int oldfontconvention = TRUE;
  1289. X                
  1290. X                switch (font[0]) {
  1291. X                case '0':
  1292. X                    (void) strcpy(font, "Roman");
  1293. X                    break;
  1294. X                case '1':
  1295. X                    (void) strcpy(font, "Bold");
  1296. X                    break;
  1297. X                case '2':
  1298. X                    (void) strcpy(font, "Italic");
  1299. X                    break;
  1300. X                case '3':
  1301. X                    (void) strcpy(font, "Special");
  1302. X                    break;
  1303. X                default:
  1304. X                    /* Must a new font with a one letter name. Eeep! */
  1305. X                    oldfontconvention = FALSE;
  1306. X                }
  1307. X                if (oldfontconvention)
  1308. X                    /* Convert to pointsize */
  1309. X                    size = size * 2 + 6;
  1310. X            }
  1311. X            xc = round(xc * scale);
  1312. X            yc = round(yc * scale);
  1313. X            /* Go to the next line */
  1314. X            while ((c = fgetc(inFile)) != '\n' && c != EOF)
  1315. X                ;
  1316. X            if (c == EOF) {
  1317. X                err = INPERR;
  1318. X                break;
  1319. X            }
  1320. X            s = XtMalloc((unsigned) (len + 2));
  1321. X            if (fgets(s, len + 1, inFile) == NULL) {
  1322. X                free(s);
  1323. X                err = INPERR;
  1324. X                break;
  1325. X            }
  1326. X            s[len] = '\0';
  1327. X            if ((fptr = findfont(font, TRUE)) == NULL) {
  1328. X                fontname = strsave(font);
  1329. X                fptr = defaultFontFamily;
  1330. X            } else {
  1331. X                fontname = fptr->name;
  1332. X            }
  1333. X            AddTextGel(&g, s, len, fptr, findsize(fptr, size), fontname, size, 
  1334. X             attr, xc, yc, x1, y1, x2, y2);
  1335. X            break;
  1336. X        case LINE:
  1337. X        case SPLINE:
  1338. X            if ((ptlist = ReadPtList(scale, type)) == NULL) {
  1339. X                err = NOMEM;
  1340. X                break;
  1341. X            }
  1342. X            AddLineGel(&g, type, ptlist, attr, x1, y1, x2, y2, thickness);
  1343. X            ptlist = NULL;
  1344. X            break;
  1345. X        }
  1346. X    } while (err == 0);
  1347. X    if (err == NOMEM)
  1348. X        message("No more memory for elements");
  1349. X    else if (err == INPERR)
  1350. X        message("Incorrect input format");
  1351. X
  1352. X    CalcBBox(g, MAXINT);
  1353. X    return(g);
  1354. X#undef NOMEM
  1355. X#undef INPERR
  1356. X#undef INPEOF
  1357. X}
  1358. X
  1359. X
  1360. X/* 
  1361. X *  Creates a new cell, with appropriate filename and name, and giving it
  1362. X *  all the default values. It does not open the file, nor does it read
  1363. X *  anything in - the cell is empty
  1364. X */
  1365. XCell *NewCell(cellName, fileName)
  1366. Xchar *cellName;
  1367. Xchar *fileName;
  1368. X{
  1369. X    register Cell *thisCell;
  1370. X    
  1371. X    if ((thisCell = (Cell *) malloc(sizeof(Cell))) == NULL) {
  1372. X        message("NewCell: Can't create cell");
  1373. X        return( (Cell *)NULL);
  1374. X    }
  1375. X
  1376. X    thisCell->name = cellName;
  1377. X    thisCell->filename = fileName;
  1378. X    thisCell->gelList = NULL;
  1379. X    thisCell->saved = NEWFILE;
  1380. X    thisCell->undo = 0;
  1381. X    thisCell->undoList = NULL;
  1382. X    thisCell->next = NULL;
  1383. X    thisCell->mtime = 0;
  1384. X
  1385. X    return(thisCell);
  1386. X}
  1387. X
  1388. X
  1389. X/* Frees and destroys a cell */
  1390. Xvoid FreeCell(cell)
  1391. XCell *cell;
  1392. X{
  1393. X    if (!cell) 
  1394. X        return;
  1395. X    xfree(cell->name);
  1396. X    xfree(cell->filename);
  1397. X    FreeGel(cell->gelList);
  1398. X    FreeGel(cell->undoList);
  1399. X    free((char *) cell);
  1400. X}
  1401. X
  1402. X
  1403. X/*
  1404. X *  Prints a cell out to lpr
  1405. X */
  1406. XLPrintCell(cell)
  1407. XCell *cell;
  1408. X{
  1409. X    static char *cmdbuf = NULL;
  1410. X    char *buf;
  1411. X    extern char *lprcommand;
  1412. X    extern char *lprinter;
  1413. X    extern void SetWorkingCursor(), SetWaitCursor();
  1414. X    
  1415. X    if (cmdbuf == NULL) {
  1416. X        /* format default command */
  1417. X        cmdbuf = XtMalloc((unsigned)
  1418. X         (strlen(lprcommand) + strlen(lprinter) + 1));
  1419. X        (void) sprintf(cmdbuf, lprcommand, lprinter);
  1420. X    }
  1421. X    /* offer user a chance to change default printing command */
  1422. X    if ((buf = get_input("Print command % ", cmdbuf, FALSE)) == NULL)
  1423. X        return;
  1424. X    /* free default command and make new command from user the default */
  1425. X    XtFree(cmdbuf);
  1426. X    cmdbuf = buf;
  1427. X    /* open the pipe - Then write out the cell Gels. */
  1428. X    if ((outFile = popen(buf, "w")) == NULL) {
  1429. X        message("Can't open pipe for print");
  1430. X    } else {
  1431. X        SetWaitCursor();
  1432. X        WriteGel(cell->gelList);
  1433. X        (void) sprintf(errstring, "Print Complete");
  1434. X        message(errstring);
  1435. X        (void) pclose(outFile);
  1436. X        SetWorkingCursor();
  1437. X        outFile = NULL;
  1438. X    }
  1439. X}
  1440. X
  1441. X
  1442. X/*
  1443. X *  Writes a cell out - closely emulates the Jove save about making
  1444. X *  backups, checking if the file has been written to, etc
  1445. X */
  1446. Xint
  1447. XWriteCell(cell, backup)
  1448. XCell *cell;
  1449. X{
  1450. X    char *fname;
  1451. X    char buf[MAXPATHLEN];
  1452. X    struct stat stbuf;
  1453. X    int retval = 0;
  1454. X    extern void SetWorkingCursor(), SetWaitCursor();
  1455. X#ifdef MAGIC
  1456. X    int fperms;
  1457. X#endif MAGIC
  1458. X    
  1459. X    
  1460. X    if (!(cell->saved & MODIFIED)) {
  1461. X        message("No changes need to be written.");
  1462. X        return 1;
  1463. X    }
  1464. X
  1465. X    /* If no file name, ask for one - default is buffer name */
  1466. X    if (!cell->filename || STREQ(cell->filename, nullfile)) {
  1467. X        if ((fname = get_input("Save file name ? ", cell->name, TRUE)) == NULL)
  1468. X            return 0;
  1469. X        cell->filename = fname;
  1470. X        cell->saved |= NEWFILE;
  1471. X    }
  1472. X
  1473. X    /*
  1474. X     *  Check that it's safe to write the file, and make a backup if
  1475. X     *  necessary
  1476. X     */
  1477. X    if (!chk_mtime(cell, buf, backup))
  1478. X        return 0;
  1479. X
  1480. X    /* 
  1481. X     *  open the file - Then write out the cell Gels. Should sort the
  1482. X     *  cell gels before doing this
  1483. X     */
  1484. X    if ((outFile = fopen(buf, "w")) == NULL) {
  1485. X        (void) sprintf(errstring, "Can't open %s for save", buf);
  1486. X        message(errstring);
  1487. X        retval = 0;
  1488. X    } else {
  1489. X        SetWaitCursor();
  1490. X        WriteGel(cell->gelList);
  1491. X        SetWorkingCursor();
  1492. X        if (fclose(outFile) == 0) {
  1493. X            cell->saved = SAVED;
  1494. X            (void) sprintf(errstring, "Wrote %s", buf);
  1495. X            retval = 1;
  1496. X        } else {
  1497. X            (void) sprintf(errstring, "Error writing %s - cell not saved",
  1498. X             buf);
  1499. X            retval = 0;
  1500. X        }
  1501. X        message(errstring);
  1502. X        outFile = NULL;
  1503. X        if (stat(buf, &stbuf) == -1) {
  1504. X            (void) sprintf(errstring, "Cannot stat %s", buf);
  1505. X            message(errstring);
  1506. X        } else {
  1507. X            cell->mtime = stbuf.st_mtime;
  1508. X#ifdef MAGIC
  1509. X            /*
  1510. X             * Extract permissions - we set it to owner execuatble, and make
  1511. X             * it group/other executable only if it is group/other readable.
  1512. X             * Not sure if it needs to be that elaborate...
  1513. X             */
  1514. X            fperms = stbuf.st_mode & 0777;
  1515. X            fperms |= 0100;        /* Set owner executable */
  1516. X            if (fperms & 0040)
  1517. X                fperms |= 0010;    /* Set group executable */
  1518. X            if (fperms & 0004)
  1519. X                fperms |= 0001;    /* Set user executable */
  1520. X            if (chmod(buf, fperms) == -1) {
  1521. X                (void) sprintf(errstring, "Cannot chmod %s", buf);
  1522. X                message(errstring);
  1523. X            }
  1524. X#endif MAGIC
  1525. X        }
  1526. X    }
  1527. X    return(retval);
  1528. X}
  1529. X
  1530. X
  1531. X/* 
  1532. X *  Read Cell routine - when this is done for multiple buffers, it should
  1533. X *  check first to see if another buffer already has the file. It takes a
  1534. X *  filename as input - if this is NULL, then it asks the user for a
  1535. X *  filename.
  1536. X */
  1537. XCell *ReadCell(prompt, fname)
  1538. Xchar *prompt;
  1539. Xchar *fname;
  1540. X{
  1541. X    char *name, *StripName();
  1542. X    Cell *cell;
  1543. X    char buf[MAXPATHLEN];
  1544. X    struct stat    stbuf;
  1545. X    extern void SetWorkingCursor(), SetWaitCursor();
  1546. X    
  1547. X    /* Get filename */
  1548. X    if (fname == NULL)
  1549. X        if ((fname = get_input(prompt, (char *) NULL, TRUE)) == NULL)
  1550. X            return((Cell *) NULL);
  1551. X    /*
  1552. X     *  create the cell
  1553. X     */
  1554. X    if ((name = StripName(fname)) == NULL) {
  1555. X        message("No memory for cell name");
  1556. X        return((Cell *) NULL);
  1557. X    }
  1558. X
  1559. X    if ((cell = NewCell(name, fname)) == NULL) {
  1560. X        message("No memory for new cell");
  1561. X        free(name);
  1562. X        free(fname);
  1563. X        return((Cell *) NULL);
  1564. X    }
  1565. X    PathParse(fname, buf);
  1566. X    /* if a file exists, then open it and read the Gels */
  1567. X    if ((inFile = fopen(buf, "r")) != NULL) {
  1568. X        SetWaitCursor();
  1569. X        cell->gelList = ReadGel();
  1570. X#ifdef DEBUG
  1571. X        if (cell->gelList != NULL) {
  1572. X            (void) sprintf(errstring, "Read file %s", buf);
  1573. X            message(errstring);
  1574. X        }
  1575. X#endif
  1576. X        if (fstat(fileno(inFile), &stbuf) == -1) {
  1577. X            (void) sprintf(errstring, "Can't fstat %s", buf);
  1578. X            message(errstring);
  1579. X        } else {
  1580. X            cell->mtime = stbuf.st_mtime;
  1581. X        }
  1582. X        (void) fclose(inFile);
  1583. X        SetWorkingCursor();
  1584. X        cell->saved = SAVED;
  1585. X        inFile = NULL;
  1586. X    } 
  1587. X#ifdef DEBUG
  1588. X    else {
  1589. X        (void) sprintf(errstring, "New file %s", buf);
  1590. X        message(errstring);
  1591. X    }
  1592. X#endif
  1593. X
  1594. X    return(cell);
  1595. X}
  1596. X
  1597. X
  1598. X/*
  1599. X *  expands and ~ in the cell filename and returns that in fname, stats
  1600. X *  the file, checks with the user if the file has been modified since
  1601. X *  it was last saved/read by the program, or if we'll be overwriting a
  1602. X *  file, and returns TRUE if things can proceed, FALSE if things can't!
  1603. X *  If backup is true, then it makes a backup copy of the file. All in
  1604. X *  one stat! This code has been adapted from similar code in JOVE.
  1605. X */
  1606. X
  1607. Xint
  1608. Xchk_mtime(cell, fname, backup)
  1609. XCell    *cell;
  1610. Xchar    *fname;
  1611. Xint        backup;
  1612. X{
  1613. X    struct stat    stbuf;
  1614. X    int exists;
  1615. X    static char    *badchars = "!$^&*()`{}\"'\\|<>? ";
  1616. X    register char *cp = cell->filename;
  1617. X    register int c;
  1618. X
  1619. X    while (c = *cp++)
  1620. X        if (c < ' ' || c == '\177' || index(badchars, c)) {
  1621. X            (void) sprintf(errstring,
  1622. X             "'%c': bad character in filename \"%s\".", 
  1623. X             c, cell->filename);
  1624. X            message(errstring);
  1625. X            return(FALSE);
  1626. X        }
  1627. X    PathParse(cell->filename, fname);
  1628. X    stbuf.st_mode = 0;
  1629. X    exists = stat(fname, &stbuf);
  1630. X    if ((!exists) && (cell->saved & NEWFILE)) {
  1631. X        /* We're about to overwrite something */
  1632. X        (void) sprintf(errstring,
  1633. X         "\"%s\" already exists; overwrite it (y/n)? ", 
  1634. X         cell->filename);
  1635. X        switch (confirm(errstring, "n")) {
  1636. X            case ABORT:
  1637. X            case NO:
  1638. X                return(FALSE);
  1639. X            case YES:
  1640. X                break;
  1641. X        }
  1642. X    }
  1643. X    if ((cell->mtime != 0) &&                /* if we care ... */
  1644. X     (!exists) &&                                /* and it exists */
  1645. X     (stbuf.st_mtime != cell->mtime)) {    /* and there's trouble. */
  1646. X         (void) sprintf(errstring,
  1647. X         "\"%s\" on disk is not what you last read/saved. Overwrite (y/n)? ",
  1648. X         cell->filename);
  1649. X        switch(confirm(errstring, "n")) {
  1650. X            case ABORT:
  1651. X            case NO:
  1652. X                return(FALSE);
  1653. X            case YES:
  1654. X                break;
  1655. X        }
  1656. X    }
  1657. X    if ((!exists) && backup)
  1658. X        /* Create backup file with same mode as input file */
  1659. X        if (file_backup(fname, stbuf.st_mode) == -1) {
  1660. X            message("Couldn't write backup file - save failed");
  1661. X            return(FALSE);
  1662. X        }
  1663. X        
  1664. X    return(TRUE);
  1665. X}
  1666. END_OF_FILE
  1667. if test 20476 -ne `wc -c <'xpic/xpic.c'`; then
  1668.     echo shar: \"'xpic/xpic.c'\" unpacked with wrong size!
  1669. fi
  1670. # end of 'xpic/xpic.c'
  1671. fi
  1672. echo shar: End of archive 14 \(of 15\).
  1673. cp /dev/null ark14isdone
  1674. MISSING=""
  1675. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  1676.     if test ! -f ark${I}isdone ; then
  1677.     MISSING="${MISSING} ${I}"
  1678.     fi
  1679. done
  1680. if test "${MISSING}" = "" ; then
  1681.     echo You have unpacked all 15 archives.
  1682.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1683. else
  1684.     echo You still need to unpack the following archives:
  1685.     echo "        " ${MISSING}
  1686. fi
  1687. ##  End of shell archive.
  1688. exit 0
  1689.