home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!island!argv
- From: argv@island.uu.net (Dan Heller)
- Newsgroups: comp.sources.x
- Subject: v04i079: xpic -- pic previewer for X11, Part14/15
- Message-ID: <927@island.uu.net>
- Date: 22 Jul 89 07:42:17 GMT
- Organization: Island Graphics, Marin County, California
- Lines: 1678
- Approved: island!argv@sun.com
-
- Submitted-by: Mark Moraes <moraes@ai.toronto.edu>
- Posting-number: Volume 4, Issue 79
- Archive-name: xpic/part14
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 14 (of 15)."
- # Contents: xpic/doc/xpic.doc xpic/xpic.c
- # Wrapped by moraes@neat.ai on Thu Jul 13 22:36:12 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'xpic/doc/xpic.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xpic/doc/xpic.doc'\"
- else
- echo shar: Extracting \"'xpic/doc/xpic.doc'\" \(29158 characters\)
- sed "s/^X//" >'xpic/doc/xpic.doc' <<'END_OF_FILE'
- X$Header: xpic.doc,v 1.11 89/02/10 04:12:27 xwindows Exp $
- X Using xpic.
- X -----------
- X
- X Mark Moraes
- X Computer Systems Research Institute
- X (moraes@csri.toronto.edu)
- X
- XXpic is a drawing package for the X Windows system, inspired
- Xstrongly by a similar, much-used package written by Bruno Preiss
- Xfor the BitGraph (bgpic). Xpic was not intended for painting, but
- Xdrawing diagrams, and figures. It was intended to produce output
- Xfor pic(1) and PostScript(tm), and some of its features stem from
- Xthat. But it outputs a simple file of object descriptions, which
- Xcan be translated to any device you like, if you write the
- Xappropriate filter. At present, filters exist for pic (the troff
- Xand TeX versions) and PostScript.
- X
- XUsage:
- Xxpic [host:display] [geometry] [iconGeometry] option ..... file ...
- X
- XThe list of options is shown below - either the short form, or the
- Xlong form is valid. The option is followed by a description, and the
- Xdefault.
- X
- XOption Resource name Action Default
- X
- X-grid, gridOn "off" Turns grid off (On)
- X+grid, gridOn "on" Turns grid on (On)
- X-gs, gridSpacing Grid spacing in pixels (8)
- X-ph, pageHeight PageHeight in 10*in. (110)
- X-pw, pageWidth PageWidth in 10*in. (85)
- X-rotate, rotate "on" swap page height and width
- X+rotate, rotate "off" normal page height and width
- X-backup, backup "off" No backup file on write(On)
- X+backup, backup "on" Make backup file on write(On)
- X-cr, cursorColor Sets cursor color (Black)
- X-hl, highlight Sets highlight color (Black)
- X
- XThanks to a sneak trick in the way xpic saves files, *executing* a file
- Xsaved by xpic will cause it to start up xpic on itself. This feature
- Xmay not be available on all systems.
- X
- X(Note that we refer to two types of buttons in this document - mouse
- Xbuttons, and screen buttons (which are pieces of text on the screen
- Xsurrounded by borders, which darken when the mouse cursor moves into
- Xthem, and highlight and select when the left mouse button is pressed
- Xin them. We will always call a mouse button a 'left button', 'right
- Xbutton', or 'middle button' or just a 'mouse button'. Any other use of
- Xbutton means a screen button)
- X
- XThe basic screen consists of three sections: the drawing window, the
- Xtext interaction window, and the button area.
- X
- X The Drawing Window
- X ------------------
- XThe drawing window has a grid, with crosses every five grid points. Each
- Xcross is supposed to be at 0.5 inch spacings - as such, the default page
- Xsize is supposed to represent an 8.5x11" page. Changing the size results
- Xin the picture window resizing as best as it can, while the menus and
- Xthe input window remain constant. (There is a minimum window size, which
- Xcan be discovered by experimentation) Resizing assumes the so-called
- X'quarter-plane' model - i.e. the upper-left corner of the picture is the
- Xorigin, and remains fixed; Increasing the size means that more room is
- Xavailable to draw, but the scale does NOT change. If you make the window
- Xsmaller, then stuff that may go outside the window boundaries will be
- Xclipped, but will still be part of the picture.
- X
- XThe cross-hairs cursor in the drawing window tracks the mouse. The
- Xtracking is done by the X server, and possesses all the disadvantages of
- XX tracking. However, the cursor position, as far as xpic is concerned,
- Xis "snapped" to the nearest grid point, (or a fraction thereof,
- Xdepending on the Snap setting - more on this later.)
- X
- XAll objects in the drawing window "rubber-band", i.e. they follow the
- Xmouse, re-drawing on each mouse movement. This means that hyper-speed
- Xmovement of the mouse is very unwise.
- X
- XThe mouse button convention is reasonably consistent:
- X
- XThe Left mouse button selects a point. This is really the action mouse button for
- Xmost tasks. (In edit mode, i.e. copy, move, delete, paste, adjust, this
- Xmouse button selects the nearest selectable object - 'nearest' means the
- Xobject whose bounding-box centre is closest to the mouse)
- X
- XThe Right mouse button ends lines, and splines at the last point at which the
- XLeft mouse button was clicked. i.e. the rubber-banded segment vanishes.
- X(In edit mode, this deselects the object that has been selected, and
- Xmakes it non-selectable. So a subsequent Left click will select the
- Xnext-nearest object. This selection cycles around)
- X
- XThe Middle mouse button aborts the operation, and erases the element being
- Xdrawn. Use with care - It cannot be undone. (Maybe this should become
- XSHIFT-Middle mouse button.) (In edit mode, in addition to aborting whatever
- Xoperation was in progress, it also makes all objects selectable again)
- X
- XSmall fonts are barely readable - they are meant to give an idea of size
- Xmore than anything. Using 6 point fonts requires considerable imagination.
- XThe fonts are not exact replicas of what you can get on paper, and are
- Xlimited to a small subset of fonts which I could scale and generate for
- XX.
- X
- X The Button Area
- X ---------------
- XThe buttons are grouped in button-boxes. Click the left mouse button on a
- Xbutton to select it. There are three types of buttons - radio-buttons,
- Xcommand buttons and updown buttons. The radio-buttons when clicked on, turn
- Xon, AND the button in the same button box which was on turns off - i.e. only
- Xone radio-button in any button box will be on at any one time. The selected
- Xbutton will be in inverse video, and will remain that way till another
- Xbutton is selected. The updown buttons have a "+" sign on the left and a "-"
- Xsign on the right - clicking the left mouse button will cause the updown
- Xbutton to advance to the next selection, which is displayed in the centre of
- Xthe button. Clicking the right mouse button will cause the updown button to
- Xmove to the previous selection.
- X
- XIn the command button boxes, no item remains permanantly selected.
- XWhen a button is pressed, it executes a command, and unhighlights
- Xautomatically.
- X
- X Button functions:
- X -----------------
- XThe top button box consists of basic functions - for drawing elements,
- Xand for editing them.
- X
- XThe basic element drawing functions are:
- X
- XBox:
- X Draws a rectangle. Select the button, and click the left mouse
- Xbutton in the drawing window to start the box, (this specifies one
- Xcorner) and move the mouse to the other corner of the desired box and
- Xclick the left mouse button again to end the box.
- X
- XLine:
- X This is a continuous "poly-line". To draw the line, select
- Xthis button, and go into the drawing window. Each left click puts down
- Xa point for the line, and clicking the right button ends the line.
- X(Note that the point where you click the right button is not part of
- Xthe line)
- X
- XSpline:
- X Works just like a line, except that it draws a quadratic
- XB-spline connecting the points instead of a line.
- X
- XCircle:
- X The first click of the left mouse button sets the centre, and
- Xthe second click sets the radius.
- X
- XEllipse:
- X The first click sets one corner of the box enclosing the
- Xellipse, and the second click sets the other corner.
- X
- X
- XText:
- X To put text, select the Text button. Then, click the left mouse
- Xbutton somewhere in the drawing window. The interaction window will
- Xprompt for text with a "?". After inputting the text, (and hitting
- Xreturn), move the mouse (which will now have the text string attached)
- Xto the place where the text should be and click the left mouse button
- Xagain. The way the text string is attached to the mouse depends on the
- Xtext positioning attributes (left justified, centred, right-justified,
- Xetc).
- X
- X Xpic tries to display onscreen text as a reasonable approximation of
- Xwhat you will see on the hardcopy output. This is subject to the
- Xavailability of reasonable fonts, and xpic's interfaces with the output
- Xdevices (the filter programs x2ps, x2pic, and x2tpic, documented below).
- XHowever, since the output medium (presently pic for troff, or PostScript) is
- Xlikely to have non-ascii characters which xpic cannot display easily on the
- Xscreen (not without putting the full pic or PostScript text semantics in
- Xxpic) there are bound to be differences. For example, the troff notation for
- Xbullet is \(bu - if you put this on screen, it will appear as such. If you
- Xprint it with pic and troff, it will come out on paper as a bullet. If you
- Xtry printing it with tpic and TeX, it will come out as \(bu. For tpic and
- XTeX, you have to say \bullet. For PostScript, you have to say \267. In all
- Xcases, xpic will not understand and will print \(bu, \bullet or \267 on the
- Xscreen respectively. The user is expected to understand this. If you want
- Xsnazzy effects like special characters or equations on your output device,
- Xbe sure you understand the output device - xpic will try not to get it the
- Xway - it won't help much either.
- X
- XObviously, if you want a real honest-to-goodness backslash, you have to
- Xescape it with another backslash, for TeX, troff and PostScript. Backslash,
- Xin xpic text, like in most other aspects of Unix, is magic - it unleashes
- Xspells and incantations that are wondrous to behold if you know what you are
- Xdoing, and devastating if you don't. Beware.
- X
- XThe text interaction window is used whenever text is needed, or
- Xfilenames, or such-like. It allows a decent subset of EMACS (actually,
- XJOVE) commands to edit the text in the line. The usual concepts of
- Xpoint and mark apply, and killing, and yanking back killed text. Note
- Xthat there is no kill ring, or mark stack - and C-X performs the
- Xfunction of C-X C-X (There are no prefixes!) The keys to which
- Xcommands are bound can be changed : the default bindings are:
- X
- X /* motion bindings */
- X
- X <Ctrl>F: forward-character
- X <Key>168: forward-character /* Cursor -> key */
- X <Ctrl>B: backward-character
- X <Key>167: backward-character /* Cursor <- key */
- X <Ctrl>A: beginning-of-line
- X <Ctrl>E: end-of-line
- X <Ctrl>U: universal-argument /* Multiplies by four */
- X
- X /* delete bindings */
- X
- X <Ctrl>D: delete-next-character
- X <Ctrl>H: delete-previous-character
- X <Key>113: delete-previous-character
- X <Key>188: delete-previous-character
- X
- X /* kill bindings */
- X
- X <Ctrl>X: exchange-point-and-mark
- X <Ctrl> : make-this-the-mark
- X <Ctrl>W: kill-region
- X <Ctrl>K: kill-to-end-of-line
- X <Meta>D: kill-to-beginning-of-line
- X
- X /* yank bindings */
- X
- X <Ctrl>Y: yank-killed-text
- X
- X /* exit quit stuff */
- X
- X <Ctrl>J: newline
- X <Key>115: newline
- X <Ctrl>M: newline
- X <Key>189: newline
- X <Ctrl>G: abort
- X <Ctrl>C: abort
- X
- X /* selection stuff */
- X
- X <BtnDown>left: set-cursor-to-mouse
- X <BtnDown>middle: set-mark-to-mouse
- X <BtnDown>right: get-x-buffer
- X
- XTheir functions should be sort-of obvious - if not, grab a Jove manual.
- X(USD-17 in the 4.3 manuals). vi users have my sympathies. The minibuf
- Xbecomes the Focus of input whenever it is required, so you need not move
- Xthe mouse into the interaction window to type. When input is over, Focus is
- Xgiven to the RootWindow, as it presumably was before the program
- Xstarted. (If it wasn't, tough!) Clicking the left mouse button at a point in
- Xthe interaction window moves the point there, clicking the middle
- Xmouse button sets the mark there, (indicated by the text cursor flashing there
- Xbriefly) Clicking the right mouse button extracts the text in the global X cut
- Xbuffer and pastes it in at the point.
- X
- XChanging these bindings can be done by putting a file of bindings in the
- Xabove format (without the C style comments) somewhere, and adding the
- Xline
- X xpic.Minibuf.eventBindings: filename
- X
- Xin you .Xdefaults file. 'filename' can be an absolute pathname (starting
- Xwith a '/') or a pathname relative to your home directory (starting without
- Xa '/'. i.e. the ~ character is implicit. ~ does not work, however.) See more
- Xon resources below.
- X
- XNote that xpic will not go on if it expects input from the input window,
- Xunless a newline (RETURN, LINE-FEED) or abort (^G) is input. It does
- Xnot, however, stop other applications from continuing.
- X
- XThe editing operations have two modes, selected in the second button
- Xbox - they should be discussed before the editing functions.
- X
- XElement:
- X This allows editing of individual objects. You select an
- Xobject to edit by going into the drawing window and clicking near
- Xit (after selecting one of the editing functions in the "Elements"
- Xbox) The selected object will highlight - lines, boxes, splines,
- Xellipses, circles by being redrawn thicker, and text will get a
- Xshaded box over it. If you happen to have selected the wrong
- Xobject, simply click the right mouse button (which will deselect
- Xthe object, i.e unhighlight it, and mark it rejected) and click the
- Xleft mouse button again. This time, it will select the second
- Xnearest object, since the first selection is marked as rejected.
- XYou can cycle through all objects on the screen without moving the
- Xmouse, simply by clicking the left and right button alternately.
- X
- X Once selected, you can perform the appropriate editing
- Xoperation on the object.
- X
- XBlock:
- X In this mode, you operate on all objects contained within a
- Xbox which you draw in the drawing window - first left mouse button
- Xclick sets one corner of the box, and the second mouse click sets the
- Xother corner. This will usually highlight all the elements within the
- Xbox, and put a box on the mouse cursor, which you can drag around and
- Xposition with another left click. The selected objects will be redrawn
- Xat the new position, and highlighted. You can keep dragging the box
- Xaround and repositioning it as long as you like - when you're
- Xsatisfied with the position/shape of the new object, click the right
- Xbutton and the objects unhighlight, and the drag box vanishes.
- X
- XThe editing operations available are:
- X
- XCopy:
- X This makes a copy of the selected object(s). In element mode, it
- Xputs the copy of the object on the mouse cursor and allows you to
- Xdrag it around and place it with another click of the mouse. In block
- Xmode, you can drag the enclosing box around, which is why you get
- Xmultiple chances to place it - since you can't see all the elements
- Xmove.
- X
- XMove:
- X Similar to copy, except the objects in question themselves
- Xmove, instead of making a copy.
- X
- XDelete:
- X The selected object(s) highlight, and you are prompted to
- Xclick again to confirm the delete. The most recently deleted
- Xelement/block is stored in a kill-buffer, and can be retrieved with a
- XPaste operation.
- X
- XPaste:
- X A left click in the drawing window puts the element/block most
- Xrecently deleted on the mouse cursor and allows it to be dragged
- Xaround and positioned. (one try for elements, multiple tries for
- Xblocks, as usual)
- X
- XAdjust:
- X This differs considerably in element and block modes. In
- Xelement mode, the selected object can be adjusted depending on the
- Xtype of object. For lines and splines, the nearest point in the
- Xline/spline is selected and moves with the mouse cursor, the object
- Xbeing redrawn appropriately. For boxes, the nearest corner is
- Xadjusted. In circles, the radius is changed. For ellipses, like boxes,
- Xthe nearest corner (of the enclosing box) is moved. Text is put in the
- Xminibuffer and can be edited - hitting return puts it back on the
- Xdrawing window.
- X
- X In block mode, adjustment is primarily useful for lines and
- Xsplines. (But works on other objects). All control points within the
- Xblock are moved around. (This is an exception to the strict
- Xcontainment rule which applies to all other block operations. Here,
- Xeven those elements which have only part of them in the selected block
- Xare selected). For lines/splines, the control points are any point,
- Xfor a boxes/ellipses, they are any corner enclosed, for circles, the
- Xcentres are the control points, and for text, the text origin is the
- Xcontrol point moved. This mode is best learnt by experimenting - it is
- Xmore easily seen than described.
- X
- XGet, Put:
- X These work only in block mode (and make loud and persistent
- Xcomplaints if selected in element mode). Get will prompt for the name
- Xof an xpic file when the left mouse button is cliecked in the drawing
- Xwindow, and will read it in, and put the enclosing box on the
- Xmouse cursor to be positioned. The elements from the file will be
- Xinserted into the figure.
- X
- X Put does exactly the reverse - it prompts for a file name to
- Xsave the selected block to. The saved file can be read in with the Get
- Xcommand, or used as a full xpic picture (xpicture?) in its own right.
- X
- XChange Attributes:
- X This will change the attributes of the selected object(s) to
- Xthe current set of attributes. Th eattributes are described below.
- X
- X Attributes
- X ----------
- X
- XThe following attributes affect all objects excpet Text. (i.e. Line,
- XSpline, Box, Circle, Ellipse).
- X
- XPatterns:
- X The five patterns are Solid, Dotted, Short-Dashed,
- XLong-Dashed, and Dot-Dashed.
- X
- XLine Thickness:
- X Ranges from 0 to 10. A zero line width means a thin line, that
- Xis half the width of a line of width 1, but is drawn with the same
- Xwidth as a line of width 1 because of screen resolution.
- X
- X This attribute affects only lines and splines:
- X
- XArrows:
- X Whether to draw arrows at the start of a line, the end of a
- Xline, both ends of a line, or not at all.
- X
- X
- XThe following attributes apply to only Text objects:
- X
- XFont:
- X This is an updown button - it will display the current font. By
- Xclicking the right or left button, one can cycle through the available fonts
- X- which are determined from the X server. See the section on fonts (later)
- Xfor more on this.
- X
- XPoint Size:
- X Also an updown button, which permits cycling through the
- Xavailable pointsizes for the current font.
- X
- XText Vertical, Horizontal Alignment:
- X These two boxes indicate how the text should be placed at the
- Xmouse position. The vertical alignment Top means that the mouse is at
- Xthe Top of the text, Middle is for the mouse at the bottom of the
- Xtext, and Bottom means that the mouse is below the text.
- X
- X The horizontal alignment decides if the mouse if to be to the
- XLeft, Centre, or Right of the text.
- X
- XThe next attribute decides how to round off the mouse position:
- X
- XSnap:
- X The grid points are 8 pixels apart. There are 10 grid points
- Xto every inch. (i.e 80 points per inch). The default snap value makes
- Xsure that all points in the diagram are rounded off to the nearest
- Xgrid point. This makes drawing precise figures much easier. If you
- Xneed more resolution, you can reduce the snap value (snap of 1 means
- Xthat there is no real snap) or increase it. Since X Windows does the
- Xmouse cursor tracking, you can move the cursor in between the grip
- Xpoints even at snap of 8. But the rubber banding of the objects will
- Xshow you the effect of snap - objects will not allow you to select a
- Xpixel in between two grid points if you have a snap of 8.
- X
- X Command Boxes
- X -------------
- X
- XThe file operations are:
- X
- XRead:
- X Reads in a new file and puts it into a new cell. (Eventually,
- Xyou should be able to switch between buffers easily. For now, it isn't
- Xpossible, so xpic insists you must save a file before reading in
- Xanother one).
- X
- XSave:
- X Saves the current cell in a file. If the cell has no filename
- Xassociated with it, it will prompt for a cell in the interaction
- Xwindow. When xpic saves a file, it makes a backup of the file before
- Xthe save in a file of the form filename~ for the file filename.
- X
- XSave As:
- X It will prompt for a filename in the interaction window, and
- Xsave the cell there. From then on, the new filename is th eone
- Xassociated with the cell.
- X
- X
- XThe miscellaneous operations are:
- X
- XUndo:
- X This extremely handy operation allows one level of undo - it
- Xwill exactly undo the last operation performed EXCEPT for File
- Xoperations. Also, undo is effective for block operations immediately
- Xafter the block operation only. The first edit operation performed
- X(even if it is aborted) after a block operation makes the undo
- Ximpossible (and strange things will happen if the undo is performed -
- Xthis is due to the way undo is implemented; unlikely to change). If
- Xundo is clicked twice, the first undo is undone.
- X
- XRedisplay:
- X Refreshes the drawing window, and cleans up internal data structures
- Xsomewhat. (xpic will automatically refresh itself if the window is
- Xobscured and later exposed)
- X
- XGrid:
- X Toggles the grid on and off. With th egrid off, you usually
- Xget a reasonable idea of what the picture will look when on paper.
- XThis wins the least used command sweepstakes hands-down.
- X
- XStatus:
- X Prints the status of the buffer, in the form
- X
- XXPIC version.patchlevel Buffer: buffername File: filename [Modified]
- X
- X The [Modified] flag indicates that changes have been made to
- Xthe picture since it was last saved.
- X
- XExit:
- X The advanced user will deduce what this is for.
- X
- X Resources
- X ---------
- X
- XThe buttons and button boxes used by xpic are standard toolkit items, their
- Xresources may be set easily. The interaction window and drawing window have
- Xthe following resource names:
- X
- X name class
- X Program: xpic XPic
- X Form enclosing it: form Form
- X Interaction window: minibuf Minibuf
- X Drawing Window: picture Window
- X Labels: label StaticText
- X ButtonBoxes: label.box RowCol
- X Buttons: button name PushButton
- X
- XProgram level resources are
- X Resource name Resource class default
- X name Name xpic
- X iconGeometry IconGeometry (none)
- X iconPixmap IconPixmap one is provided
- X pageWidth PageWidth 85
- X pageHeight PageHeight 105
- X gridSpacing GridSpacing 8
- X gridOn GridOn True
- X gridColor GridColor Black
- X cursorColor CursorColor Black
- X highlight Highlight Black
- X rotate Rotate False
- X backup Backup True
- X printer Printer PostScript
- X lprcommand LprCommand x2ps -w | lpr -P%s
- X
- XA sample resource file is:
- X
- X xpic*picture.background: #80cfdf
- X xpic*picture.foreground: black
- X xpic*RowCol.background: MediumTurquoise
- X xpic*RowCol.borderWidth: 0
- X xpic*PushButton.font: helv10b
- X xpic*PushButton.background: SkyBlue
- X xpic*PushButton.foreground: DarkSlateGrey
- X xpic*PushButton.border: MediumAquamarine
- X xpic*Minibuf.background: #13e5e5
- X xpic*Minibuf.foreground: black
- X xpic*Minibuf.font: 9x15
- X xpic*Minibuf.borderWidth: 0
- X xpic*StaticText.background: white
- X xpic*StaticText.font: fg-13
- X xpic*StaticText.borderWidth: 0
- X xpic*background: SkyBlue
- X
- X Output
- X ------
- X Xpic saves files in an internal, (ascii) easy to read/write
- Xformat (easy for xpic and me, that is!) This format can be translated
- Xinto PostScript and pic.
- X
- Xpic:
- X Use the program x2pic - no options etc. Just
- X x2pic [-s scale] [-f numfonts] [filename] ...
- X
- X-s scale
- Xscales the picture by 'scale', where scale can be a float. It tries to
- Xscale the fonts too, unlike pic's scale command, but don't expect
- Xmiracles.
- X
- X-f numfonts
- Xsets the maximum number of fonts in the font mapping table. See the
- Xsection on fonts below. The default is usually adequate unless the
- Xuser has lots of fonts in the ~/.x2pic or ~/.x2tpic file.
- X
- XEach file becomes a separate .PS/.PE and the pic output is written to
- Xstdout. If no filename is given, it is read from stdin.
- X
- XThen process it normally through pic. Note that the fonts on the screen
- Xmatch the output fonts closely, but not perfectly. So don't try to draw
- Xboxes/ellipses/stuff around text with no tolerance - be generous.
- X(Remember the old cartoonists adage - draw the bubble AFTER the text,
- Xnot before)
- X
- Xpic cannot do anything other than solid circles/ellipses/splines. It
- Xhas a silent limit of 50 points per spline which it enforces by core
- Xdump.
- X
- XThere is a similar program called x2tpic which generates almost
- Xexactly the same output, but with font style/size selection commands
- Xin TeX. It can be used with tpic.
- X
- XPostScript:
- X x2ps [-w] [-r] [-x] [-s scale] [-p prologuefile] [-t trailerfile]
- X [-f numfonts] [-h hoffset] [-v voffset] [filename] ....
- X
- X-w WYSIWYG mode, prints the figure as it was in the screen without moving the
- Xpicture so the picture's lower left corner is at the page lower left corner.
- XUseful for sending the picture straight to the printer. (The Print button on
- Xxpic uses this by default. If you don't have a PostScript printer, you
- Xmay want to change the printing command to use x2pic, pic, and troff)
- X
- X-r prints the figure in landscape mode, rotated by 90 degrees. It
- Xgoes together with the -r option on xpic.
- X
- X-x suppresses the showpage emitted by x2ps - LaTeX used to need this.
- X(Locally, we've fixed LaTeX by defining /showpage to be null in the
- Xspecial header).
- X
- X-s scale
- Xscales the picture by 'scale', where scale can be a float.
- X
- X-p prologuefile
- X-t trailerfile
- Xspecify the prologue and trailer to be used. The defaults are
- X/usr/local/lib/xpic/x2ps.pro and x2ps.tra. Use these only if you know
- Xwhat you're doing. Typically, you'd take x2ps.{pro,tra} and modify
- Xthem to change something you don't like - or you think is buggy. On
- Xyour own head be it.
- X
- X-h hoffset
- X-v voffset
- Xspecify the horizontal and vertical offset to add to the figure, in
- Xinches. hoffset and voffset may be floats.
- X
- X-f numfonts
- Xsets the maximum number of fonts in the font mapping table. See the
- Xsection on fonts below. The default is usually adequate unless the
- Xuser has lots of fonts in the ~/.x2ps file.
- X
- X FONTS
- X -----
- X xpic reads a font description file to decide what fonts it can use
- Xfrom the server, and to deal with differing resolutions of available screen
- Xfonts. The fontdesc file should be something like
- X
- X <Full name(used in label)> <prefix> <fontname-root>
- X
- XThe actual font name would be prefix.fontname-root.size[.<dots-per-inch>]
- Xwhere size is a point size, at the specified dots-per-inch.
- X
- X(eg)
- XItalic devsun i
- XRoman devsun r
- XBold devsun b
- XSpecial devsun s
- XItalic xpic i
- XBold xpic r
- XSpecial xpic s
- XRoman xpic r
- X
- Xsays that fonts of the form devsun.i.* (where the * is the point
- Xsize) are Italic fonts. Xpic will scale font point sizes to the
- Xscreen resolution. If more than one font of the same Full name,
- Xand effective point size at the current screen resolution exists,
- Xthen the first one gets used.
- X
- XTo set the default, a line of the form
- X default <Full name> <pointsize>
- Xcould be put in. (If it isn't there, the default is the first fontname
- Xand the first size of that font.
- X
- XThe default fontdesc file it reads is XPICLIBDIR/fontdesc/xpic. It also
- Xchecks for a ~/.xpic file, and anything in that overrides the system
- Xdefaults.
- X
- X x2pic uses a similar fontdesc file, which lists the mapping of
- Xxpic font names to pic (or really, troff) font changing commands.
- X
- X(eg)
- XRoman \fR
- XItalic \fI
- XBold \fB
- XSpecial \fS
- XBigBold \f(BB
- X
- XThe default x2pic fontdesc is in XPICLIBDIR/fontdesc/x2pic, and it also
- Xreads ~/.x2pic.
- X
- X x2ps does the same thing to map xpic font names to PostScript names.
- X
- X(eg)
- XRoman Times-Roman
- XItalic Times-Italic
- XBold Times-Bold
- XSpecial Symbol
- XBigBold Helvetica-Bold
- X
- XThe default x2ps fontdesc is in XPICLIBDIR/fontdesc/x2ps, and it also
- Xreads ~/.x2ps.
- X
- X
- X x2tpic has a slightly more complex font description file,
- Xwhich has the following fields:
- X <Full xpic name> <pointsize> <tex name> <tex font> <optional tex scale>
- X
- X(eg)
- XRoman 9 \Xninerm cmr9
- X
- X-- maps xpic Roman, 9 pt, to the name \Xninerm, corresponding to cmr9.
- X
- XRoman 11 \Xelevenrm cmr10 \magstephalf
- X
- X-- maps xpic Roman, 11 pt, to the name \Xelevenrm, corresponding to
- Xcmr10, scaled by magstephalf. (See the TeXbook for more in this)
- X
- XItalic 6 \Xsixit cmti7 857
- X
- X-- maps xpic Italic, 6 pt, to the name \Xsixit, corresponding to cmti7
- Xscaled 857.
- X
- XSpecial 6 \Xsixsp PS-Symbol pointsize6
- X
- X-- We store the .tfm file for PostScript(tm) fonts under the names
- XPS-postscriptname. (eg) PS-Symbol. Other sites may use different names
- X(eg) pssymbol. The above line generates the appropriate scaled at
- Xcommand to get 6 point Symbol.
- X
- Xx2tpic will search this table to find the closest font to the one
- Xrequested. It will find the closest size in either the same font style
- Xor Roman.
- X
- XIf you want to add to the table, keep the entries in ~/.x2tpic.
- XUsually, your system will have the right map of fonts in the default.
- XIf not, ask the person who installed xpic to talk to the person who
- Xlooks after TeX.
- X
- X BUGS
- X ----
- XPlease report bugs to me, as specifically as you can. Note that if
- Xthe system crashes, xpic cannot retrieve work like text editors.
- XIf xpic dies due to some unpleasant cause (program error, network
- Xerror, a signal), it dumps the current unsaved cell into some
- Xtemporary directory - usually /tmp.
- X
- XIf you make improvements, or think they should be made, tell me. If
- Xyou send code, please use context diffs - the -c flag on diff.
- X
- XGood luck.
- X
- X-----------
- X+ PostScript is a trademark of Adobe, Inc.
- END_OF_FILE
- if test 29158 -ne `wc -c <'xpic/doc/xpic.doc'`; then
- echo shar: \"'xpic/doc/xpic.doc'\" unpacked with wrong size!
- fi
- # end of 'xpic/doc/xpic.doc'
- fi
- if test -f 'xpic/xpic.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xpic/xpic.c'\"
- else
- echo shar: Extracting \"'xpic/xpic.c'\" \(20476 characters\)
- sed "s/^X//" >'xpic/xpic.c' <<'END_OF_FILE'
- X/* $Header: xpic.c,v 1.5 89/04/21 03:32:24 xwindows Exp $ */
- X/*
- X * This file contains lots of basic routines which manipulate the data
- X * and create/free/read/write various structures
- X */
- X
- X#include <strings.h>
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#ifndef MAXPATHLEN
- X# ifdef PATH_MAX
- X# define MAXPATHLEN PATH_MAX
- X# else
- X /* If you haven't got either MAXPATHLEN or PATH_MAX defined, ouch! */
- X# define MAXPATHLEN 256
- X# endif
- X#endif
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include <values.h>
- X
- X#include "xpic.h"
- X#include "windows.h"
- X#include "input.h"
- X#include "gels.h"
- X#include "tune.h"
- X#include "newfonts.h"
- X#include "assert.h"
- X
- X#define round(x) ((int) ((x) + 0.5))
- X#define xfree(x) if (x) free(x); else
- X
- X/*
- X * basic bounding box manipulation routines (may write them later as
- X * macros if I think the speed improvement warrants it.) Note that
- X * 'contains' means 'p' lying within or on the bounding box 'clip', hence
- X * 'intersects' means 'b' intersecting or touching 'clip'.
- X */
- X
- XBOOL containsXY(x, y, clip)
- Xregister int x, y;
- Xregister Box *clip;
- X{
- X return((x >= clip->ll.x) && (x <= clip->ur.x) &&
- X (y >= clip->ll.y )&& (y <= clip->ur.y));
- X}
- X
- XBOOL contains(p, clip)
- Xregister Point *p;
- Xregister Box *clip;
- X{
- X return((p->x >= clip->ll.x) && (p->x <= clip->ur.x) &&
- X (p->y >= clip->ll.y )&& (p->y <= clip->ur.y));
- X}
- X
- X/*
- X * If two boxes intersect, then the area of intersection must be
- X * positive, i.e. ur.x of the intersection > ll.x AND ur.y > ll.y where
- X * ur.x of the intersection is the minimum of the ur.x of the two
- X * boxes, and the ll.x is the maximum of the ll.x of the two boxes
- X * (similarly for y). (Assuming ll.x < ur.x, ll.y < ur.y ALWAYS for all
- X * boxes.)
- X */
- XBOOL intersects(b, clip)
- Xregister Box *b;
- Xregister Box *clip;
- X{
- X return ( (MAX(b->ll.x, clip->ll.x) <= MIN(b->ur.x, clip->ur.x)) &&
- X (MAX(b->ll.y, clip->ll.y) <= MIN(b->ur.y, clip->ur.y)) );
- X}
- X
- X
- X/* Returns TRUE if box 'b' lies ENTIRELY within 'clip' */
- XBOOL within(b, clip)
- Xregister Box *b;
- Xregister Box *clip;
- X{
- X return(contains(&(b->ll), clip) && contains(&(b->ur), clip));
- X}
- X
- X
- X/*
- X * Frees the vertex buffer of a pointlist, and the pointlist itself
- X */
- Xvoid FreePtList(pt)
- Xregister PointList *pt;
- X{
- X if (!pt)
- X return;
- X xfree((char *) pt->v);
- X free((char *) pt);
- X}
- X
- X
- X/*
- X * Takes a XPoint array, mallocs space for N points, and copies the first
- X * N points from the given XPoint array to the PointList
- X */
- XPointList *NewPtList(vertices, n)
- Xregister XPoint *vertices;
- Xint n;
- X{
- X PointList *thisPtList;
- X
- X if ((thisPtList = (PointList *) malloc(sizeof(PointList))) == NULL) {
- X message("NewPointList: Can't get memory for new pointlist element");
- X return( (PointList *) NULL);
- X }
- X
- X if ((thisPtList->v = (XPoint *) calloc((unsigned) n, sizeof(XPoint)))
- X == NULL) {
- X message("NewPointList: Can't get memory for new vertex list");
- X free((char *) thisPtList);
- X return( (PointList *) NULL);
- X }
- X
- X thisPtList->nVerts = n;
- X
- X (void) bcopy((char *) vertices, (char *) (thisPtList->v),
- X (int) (n * sizeof(XPoint)));
- X
- X return(thisPtList);
- X}
- X
- X
- X/* Reads in a pointlist from the current inFile */
- XPointList *ReadPtList(scale, type)
- Xdouble scale;
- Xint type;
- X{
- X PointList *thisPtList;
- X register XPoint *tmp;
- X register int i, n;
- X int x, y;
- X
- X if ((thisPtList = (PointList *) malloc(sizeof(PointList))) == NULL) {
- X message("Can't get memory for new pointlist");
- X return( (PointList *) NULL);
- X }
- X
- X if (fscanf(inFile, " %d", &(thisPtList->nVerts)) != 1) {
- X free((char *) thisPtList);
- X return( (PointList *) NULL);
- X }
- X
- X if (type == SPLINE)
- X thisPtList->nVerts += 2;
- X
- X n = thisPtList->nVerts;
- X
- X if ((thisPtList->v = (XPoint *) calloc((unsigned) n, sizeof(XPoint)))
- X == NULL) {
- X message("Can't get memory for new vertex list");
- X free((char *) thisPtList);
- X return( (PointList *) NULL);
- X }
- X
- X tmp = thisPtList->v;
- X if (type == SPLINE) {
- X tmp++;
- X n -= 2;
- X }
- X
- X for (i = 0; i < n; i++, tmp++) {
- X if (fscanf(inFile, " %d %d", &x, &y) != 2) {
- X FreePtList(thisPtList);
- X return((PointList *) NULL);
- X }
- X tmp->x = round(x * scale);
- X tmp->y = round(y * scale);
- X }
- X return(thisPtList);
- X}
- X
- X
- X/* writes out a pointlist to the current outFile */
- Xvoid WritePtList(pt, type)
- XPointList *pt;
- Xint type;
- X{
- X register int i, j, n;
- X register XPoint *vert;
- X
- X vert = pt->v;
- X n = pt->nVerts;
- X if (type == SPLINE) {
- X vert++;
- X n -= 2;
- X }
- X
- X (void) fprintf(outFile, "%d\n", n);
- X
- X for (i = 0, j = 1; i < n; i++, vert++, j++) {
- X (void) fprintf(outFile, " %d %d", vert->x, vert->y);
- X if (j == 4) {
- X j = 0;
- X (void) fputc('\n', outFile);
- X }
- X }
- X if (j != 1)
- X (void) fputc('\n', outFile);
- X}
- X
- X
- X/*
- X * makes a Gel
- X */
- XGel *NewGel()
- X{
- X Gel *thisGel;
- X
- X if ((thisGel = (Gel *) malloc(sizeof(Gel))) == NULL) {
- X message("NewGel: Can't get memory for new element");
- X return( (Gel *) NULL);
- X }
- X
- X /* Null the pointers, and other fields */
- X bzero((char *) thisGel, sizeof(Gel));
- X
- X thisGel->number = GelCounter++;
- X
- X return (thisGel);
- X}
- X
- X
- X/*
- X * Traverse the linked list, freeing each gel - for some items like line,
- X * may need to traverse sub-lists i.e ptlist
- X */
- Xvoid FreeGel(g)
- Xregister Gel *g;
- X{
- X register Gel *tmp = g;
- X
- X while (tmp != NULL) {
- X switch (tmp->type) {
- X case LINE:
- X case SPLINE:
- X FreePtList( (PointList *) tmp->data);
- X break;
- X case TEXT:
- X {
- X TextString *tmp_text = (TextString *) tmp->data;
- X if (tmp_text) xfree(tmp_text->str);
- X xfree( (char *) tmp_text);
- X }
- X break;
- X case CIRCLE:
- X case ELLIPSE:
- X xfree(tmp->data);
- X break;
- X default:
- X break;
- X }
- X tmp = tmp->next;
- X free ((char *) g);
- X g = tmp;
- X }
- X}
- X
- X
- X/*
- X * Pushes a list of Gels (g) onto another list of gels (stack). It
- X * returns the number of gels pushed onto the stack.
- X */
- Xint PushGel(stack, g)
- Xregister Gel *g, **stack;
- X{
- X register Gel *tmp;
- X register i = 0;
- X
- X while(g != NULL) {
- X tmp = g->next;
- X g->next = *stack;
- X *stack = g;
- X g = tmp;
- X i++;
- X }
- X return(i);
- X}
- X
- X
- X/*
- X * Pushes the list of gels g onto the stack, AFTER popping off N
- X * elements. The N elements are then pushed back on. This is used by
- X * aborts, when a gel needs to be pushed back onto the stack, without
- X * disturbing the top undo elements. Note that the N returned MAY NOT
- X * be used for undo purposes, since it is not from the top of the
- X * stack. Note also that this does not completely solve the problem,
- X * because if you select one of the top undo elements, and then try an
- X * undo, things get confused, In short - don't undo too long after you
- X * do!
- X */
- Xint PushUnderUndo(stack, g, n)
- Xregister Gel **stack;
- Xregister Gel *g;
- Xregister int n;
- X{
- X Gel *tmp;
- X
- X tmp = PopGel(stack, n);
- X n = PushGel(stack, g);
- X (void) PushGel(stack, tmp);
- X return(n);
- X}
- X
- X
- X/*
- X * This pops N gels off the stack and returns a pointer to the list
- X */
- XGel *PopGel(stack, n)
- Xregister Gel **stack;
- Xint n;
- X{
- X register Gel *g, *tmp;
- X register int i;
- X
- X for(i = 0, g = NULL; i < n && *stack != NULL; i++) {
- X tmp = (*stack)->next;
- X (*stack)->next = g;
- X g = *stack;
- X *stack = tmp;
- X }
- X return(g);
- X}
- X
- X
- X/*
- X * Counts the number of Gels in a gellist
- X */
- Xint CountGel(gel)
- Xregister Gel *gel;
- X{
- X register int i = 0;
- X
- X for (; gel != NULL; gel = gel->next, i++)
- X ;
- X return(i);
- X}
- X/*
- X * This returns the bounding box of a gel list. Since the bounding box is
- X * returned in a static struct, it must not be modified or changed.
- X */
- XBox *GetBBox(g)
- Xregister Gel *g;
- X{
- X static Box b;
- X
- X b.ur.x = b.ur.y = 0;
- X b.ll.x = b.ll.y = MAXINT;
- X while (g != NULL) {
- X bigger_box(b, g->b_box);
- X g = g->next;
- X }
- X return(&b);
- X}
- X
- X
- X/*
- X * Just traverse the linked list, writing out all elements in the Gel
- X * list to outFile
- X */
- Xvoid WriteGel(g)
- Xregister Gel *g;
- X{
- X Conic *conic;
- X TextString *text;
- X Box *b;
- X
- X#ifdef MAGIC
- X /* Write out the magic string, using the appropriate invocation */
- X (void) fprintf(outFile, "#! %s\n", PROGRAMNAME);
- X#endif MAGIC
- X /* First write out Gel bounding box */
- X CalcBBox(g, MAXINT);
- X b = GetBBox(g);
- X (void) fprintf(outFile, "%d %d %d %d %d\n", b->ll.x, b->ll.y,
- X b->ur.x, b->ur.y, gridSpacing);
- X
- X /* Now write out the Gel list */
- X for (;g != NULL; g = g->next) {
- X (void) fprintf(outFile, "%d %d %d %d %d %d %x %d\n", g->type,
- X g->number, g->b_box.ll.x, g->b_box.ll.y,
- X g->b_box.ur.x, g->b_box.ur.y, g->attributes, g->linewidth);
- X switch (g->type) {
- X case BOX:
- X break;
- X case ELLIPSE:
- X conic = (Conic *) g->data;
- X (void) fprintf(outFile, "%d %d %d %d\n", conic->centre.x,
- X conic->centre.y, conic->xrad, conic->yrad);
- X break;
- X case CIRCLE:
- X conic = (Conic *) g->data;
- X (void) fprintf(outFile, "%d %d %d\n", conic->centre.x,
- X conic->centre.y, conic->xrad);
- X break;
- X case TEXT:
- X text = (TextString *) g->data;
- X (void) fprintf(outFile, "%d %d %d %s %d\n%s\n", text->x, text->y,
- X text->length, text->fontname, text->fontsize, text->str);
- X break;
- X case LINE:
- X case SPLINE:
- X WritePtList((PointList *) g->data, g->type);
- X break;
- X }
- X }
- X}
- X
- X
- Xstatic char *strsave(s)
- Xchar *s;
- X{
- X char *s1 = XtMalloc((unsigned) (strlen(s) + 1));
- X
- X if (s1)
- X (void) strcpy(s1, s);
- X return(s1);
- X}
- X
- X
- X/*
- X * Read in and make a linked list of Gel items from inFile
- X */
- XGel *ReadGel()
- X{
- X Gel *g;
- X int type;
- X int xc, yc, xr, yr, len, attr;
- X int size;
- X char font[MAXSTR];
- X int x1, y1, x2, y2, gs;
- X char *s;
- X int c;
- X int err, nf;
- X PointList *ptlist;
- X double scale;
- X int num, thickness;
- X FontFamily *fptr;
- X char *fontname;
- X
- X#define NOMEM 1
- X#define INPERR 2
- X#define INPEOF 3
- X
- X err = 0;
- X g = NULL;
- X ASSERT(allock(), "test 1");
- X#ifdef MAGIC
- X /* Check for the magic header that the new xpic puts out */
- X if ((c = getc(inFile)) == EOF) {
- X message("Incorrect input format");
- X return(NULL);
- X }
- X ASSERT(allock(), "test 2");
- X (void) ungetc(c, inFile);
- X if (c == '#') {
- X /* Magic header - ignore */
- X (void) fscanf(inFile, "%*[^\n]");
- X }
- X#endif MAGIC
- X /* Read in (and ignore) the gel bounding box */
- X if (fscanf(inFile, " %d %d %d %d %d", &x1, &y1, &x2, &y2, &gs) != 5) {
- X message("Incorrect input format");
- X return(NULL);
- X }
- X
- X if (gs == 0) {
- X message("Incorrect input.");
- X return(NULL);
- X }
- X
- X scale = ((double) gridSpacing) / gs;
- X
- X /* Read in the actual list */
- X do {
- X if ((nf = fscanf(inFile, " %d", &type)) != 1) {
- X err = INPEOF;
- X break;
- X }
- X nf = fscanf(inFile, " %d %d %d %d %d %x %d", &num, &x1, &y1,
- X &x2, &y2, &attr, &thickness);
- X if (nf != 7) {
- X err = INPERR;
- X break;
- X }
- X x1 = round(x1 * scale);
- X x2 = round(x2 * scale);
- X y1 = round(y1 * scale);
- X y2 = round(y2 * scale);
- X switch (type) {
- X case BOX:
- X AddBoxGel(&g, x1, y1,x2, y2, attr, thickness);
- X break;
- X case ELLIPSE:
- X nf = fscanf(inFile, " %d %d %d %d", &xc, &yc, &xr, &yr) ;
- X if (nf != 4) {
- X err = INPERR;
- X break;
- X }
- X xc = round(xc * scale);
- X yc = round(yc * scale);
- X xr = round(xr * scale);
- X yr = round(yr * scale);
- X AddConicGel(&g, type, xc, yc, xr, yr, attr, x1, y1, x2, y2, thickness);
- X break;
- X case CIRCLE:
- X nf = fscanf(inFile, " %d %d %d", &xc, &yc, &xr);
- X if (nf != 3) {
- X err = INPERR;
- X break;
- X }
- X xc = round(xc * scale);
- X yc = round(yc * scale);
- X xr = round(xr * scale);
- X AddConicGel(&g, type, xc, yc, xr, xr, attr, x1, y1, x2, y2, thickness);
- X break;
- X case TEXT:
- X nf = fscanf(inFile, " %d %d %d %s %d", &xc, &yc, &len, font,
- X &size);
- X if (nf != 5) {
- X err = INPERR;
- X break;
- X }
- X /*
- X * For backward compatibility with the bad old days. The
- X * old convention of storing font information was really
- X * ugly - a font number from 0-3, (corresponding to Roman,
- X * Bolld, Italic, Special) and a size from 0-9
- X * (corresponding to point sizes 6 - 24)
- X */
- X if (font[1] == '\0') {
- X int oldfontconvention = TRUE;
- X
- X switch (font[0]) {
- X case '0':
- X (void) strcpy(font, "Roman");
- X break;
- X case '1':
- X (void) strcpy(font, "Bold");
- X break;
- X case '2':
- X (void) strcpy(font, "Italic");
- X break;
- X case '3':
- X (void) strcpy(font, "Special");
- X break;
- X default:
- X /* Must a new font with a one letter name. Eeep! */
- X oldfontconvention = FALSE;
- X }
- X if (oldfontconvention)
- X /* Convert to pointsize */
- X size = size * 2 + 6;
- X }
- X xc = round(xc * scale);
- X yc = round(yc * scale);
- X /* Go to the next line */
- X while ((c = fgetc(inFile)) != '\n' && c != EOF)
- X ;
- X if (c == EOF) {
- X err = INPERR;
- X break;
- X }
- X s = XtMalloc((unsigned) (len + 2));
- X if (fgets(s, len + 1, inFile) == NULL) {
- X free(s);
- X err = INPERR;
- X break;
- X }
- X s[len] = '\0';
- X if ((fptr = findfont(font, TRUE)) == NULL) {
- X fontname = strsave(font);
- X fptr = defaultFontFamily;
- X } else {
- X fontname = fptr->name;
- X }
- X AddTextGel(&g, s, len, fptr, findsize(fptr, size), fontname, size,
- X attr, xc, yc, x1, y1, x2, y2);
- X break;
- X case LINE:
- X case SPLINE:
- X if ((ptlist = ReadPtList(scale, type)) == NULL) {
- X err = NOMEM;
- X break;
- X }
- X AddLineGel(&g, type, ptlist, attr, x1, y1, x2, y2, thickness);
- X ptlist = NULL;
- X break;
- X }
- X } while (err == 0);
- X if (err == NOMEM)
- X message("No more memory for elements");
- X else if (err == INPERR)
- X message("Incorrect input format");
- X
- X CalcBBox(g, MAXINT);
- X return(g);
- X#undef NOMEM
- X#undef INPERR
- X#undef INPEOF
- X}
- X
- X
- X/*
- X * Creates a new cell, with appropriate filename and name, and giving it
- X * all the default values. It does not open the file, nor does it read
- X * anything in - the cell is empty
- X */
- XCell *NewCell(cellName, fileName)
- Xchar *cellName;
- Xchar *fileName;
- X{
- X register Cell *thisCell;
- X
- X if ((thisCell = (Cell *) malloc(sizeof(Cell))) == NULL) {
- X message("NewCell: Can't create cell");
- X return( (Cell *)NULL);
- X }
- X
- X thisCell->name = cellName;
- X thisCell->filename = fileName;
- X thisCell->gelList = NULL;
- X thisCell->saved = NEWFILE;
- X thisCell->undo = 0;
- X thisCell->undoList = NULL;
- X thisCell->next = NULL;
- X thisCell->mtime = 0;
- X
- X return(thisCell);
- X}
- X
- X
- X/* Frees and destroys a cell */
- Xvoid FreeCell(cell)
- XCell *cell;
- X{
- X if (!cell)
- X return;
- X xfree(cell->name);
- X xfree(cell->filename);
- X FreeGel(cell->gelList);
- X FreeGel(cell->undoList);
- X free((char *) cell);
- X}
- X
- X
- X/*
- X * Prints a cell out to lpr
- X */
- XLPrintCell(cell)
- XCell *cell;
- X{
- X static char *cmdbuf = NULL;
- X char *buf;
- X extern char *lprcommand;
- X extern char *lprinter;
- X extern void SetWorkingCursor(), SetWaitCursor();
- X
- X if (cmdbuf == NULL) {
- X /* format default command */
- X cmdbuf = XtMalloc((unsigned)
- X (strlen(lprcommand) + strlen(lprinter) + 1));
- X (void) sprintf(cmdbuf, lprcommand, lprinter);
- X }
- X /* offer user a chance to change default printing command */
- X if ((buf = get_input("Print command % ", cmdbuf, FALSE)) == NULL)
- X return;
- X /* free default command and make new command from user the default */
- X XtFree(cmdbuf);
- X cmdbuf = buf;
- X /* open the pipe - Then write out the cell Gels. */
- X if ((outFile = popen(buf, "w")) == NULL) {
- X message("Can't open pipe for print");
- X } else {
- X SetWaitCursor();
- X WriteGel(cell->gelList);
- X (void) sprintf(errstring, "Print Complete");
- X message(errstring);
- X (void) pclose(outFile);
- X SetWorkingCursor();
- X outFile = NULL;
- X }
- X}
- X
- X
- X/*
- X * Writes a cell out - closely emulates the Jove save about making
- X * backups, checking if the file has been written to, etc
- X */
- Xint
- XWriteCell(cell, backup)
- XCell *cell;
- X{
- X char *fname;
- X char buf[MAXPATHLEN];
- X struct stat stbuf;
- X int retval = 0;
- X extern void SetWorkingCursor(), SetWaitCursor();
- X#ifdef MAGIC
- X int fperms;
- X#endif MAGIC
- X
- X
- X if (!(cell->saved & MODIFIED)) {
- X message("No changes need to be written.");
- X return 1;
- X }
- X
- X /* If no file name, ask for one - default is buffer name */
- X if (!cell->filename || STREQ(cell->filename, nullfile)) {
- X if ((fname = get_input("Save file name ? ", cell->name, TRUE)) == NULL)
- X return 0;
- X cell->filename = fname;
- X cell->saved |= NEWFILE;
- X }
- X
- X /*
- X * Check that it's safe to write the file, and make a backup if
- X * necessary
- X */
- X if (!chk_mtime(cell, buf, backup))
- X return 0;
- X
- X /*
- X * open the file - Then write out the cell Gels. Should sort the
- X * cell gels before doing this
- X */
- X if ((outFile = fopen(buf, "w")) == NULL) {
- X (void) sprintf(errstring, "Can't open %s for save", buf);
- X message(errstring);
- X retval = 0;
- X } else {
- X SetWaitCursor();
- X WriteGel(cell->gelList);
- X SetWorkingCursor();
- X if (fclose(outFile) == 0) {
- X cell->saved = SAVED;
- X (void) sprintf(errstring, "Wrote %s", buf);
- X retval = 1;
- X } else {
- X (void) sprintf(errstring, "Error writing %s - cell not saved",
- X buf);
- X retval = 0;
- X }
- X message(errstring);
- X outFile = NULL;
- X if (stat(buf, &stbuf) == -1) {
- X (void) sprintf(errstring, "Cannot stat %s", buf);
- X message(errstring);
- X } else {
- X cell->mtime = stbuf.st_mtime;
- X#ifdef MAGIC
- X /*
- X * Extract permissions - we set it to owner execuatble, and make
- X * it group/other executable only if it is group/other readable.
- X * Not sure if it needs to be that elaborate...
- X */
- X fperms = stbuf.st_mode & 0777;
- X fperms |= 0100; /* Set owner executable */
- X if (fperms & 0040)
- X fperms |= 0010; /* Set group executable */
- X if (fperms & 0004)
- X fperms |= 0001; /* Set user executable */
- X if (chmod(buf, fperms) == -1) {
- X (void) sprintf(errstring, "Cannot chmod %s", buf);
- X message(errstring);
- X }
- X#endif MAGIC
- X }
- X }
- X return(retval);
- X}
- X
- X
- X/*
- X * Read Cell routine - when this is done for multiple buffers, it should
- X * check first to see if another buffer already has the file. It takes a
- X * filename as input - if this is NULL, then it asks the user for a
- X * filename.
- X */
- XCell *ReadCell(prompt, fname)
- Xchar *prompt;
- Xchar *fname;
- X{
- X char *name, *StripName();
- X Cell *cell;
- X char buf[MAXPATHLEN];
- X struct stat stbuf;
- X extern void SetWorkingCursor(), SetWaitCursor();
- X
- X /* Get filename */
- X if (fname == NULL)
- X if ((fname = get_input(prompt, (char *) NULL, TRUE)) == NULL)
- X return((Cell *) NULL);
- X /*
- X * create the cell
- X */
- X if ((name = StripName(fname)) == NULL) {
- X message("No memory for cell name");
- X return((Cell *) NULL);
- X }
- X
- X if ((cell = NewCell(name, fname)) == NULL) {
- X message("No memory for new cell");
- X free(name);
- X free(fname);
- X return((Cell *) NULL);
- X }
- X PathParse(fname, buf);
- X /* if a file exists, then open it and read the Gels */
- X if ((inFile = fopen(buf, "r")) != NULL) {
- X SetWaitCursor();
- X cell->gelList = ReadGel();
- X#ifdef DEBUG
- X if (cell->gelList != NULL) {
- X (void) sprintf(errstring, "Read file %s", buf);
- X message(errstring);
- X }
- X#endif
- X if (fstat(fileno(inFile), &stbuf) == -1) {
- X (void) sprintf(errstring, "Can't fstat %s", buf);
- X message(errstring);
- X } else {
- X cell->mtime = stbuf.st_mtime;
- X }
- X (void) fclose(inFile);
- X SetWorkingCursor();
- X cell->saved = SAVED;
- X inFile = NULL;
- X }
- X#ifdef DEBUG
- X else {
- X (void) sprintf(errstring, "New file %s", buf);
- X message(errstring);
- X }
- X#endif
- X
- X return(cell);
- X}
- X
- X
- X/*
- X * expands and ~ in the cell filename and returns that in fname, stats
- X * the file, checks with the user if the file has been modified since
- X * it was last saved/read by the program, or if we'll be overwriting a
- X * file, and returns TRUE if things can proceed, FALSE if things can't!
- X * If backup is true, then it makes a backup copy of the file. All in
- X * one stat! This code has been adapted from similar code in JOVE.
- X */
- X
- Xint
- Xchk_mtime(cell, fname, backup)
- XCell *cell;
- Xchar *fname;
- Xint backup;
- X{
- X struct stat stbuf;
- X int exists;
- X static char *badchars = "!$^&*()`{}\"'\\|<>? ";
- X register char *cp = cell->filename;
- X register int c;
- X
- X while (c = *cp++)
- X if (c < ' ' || c == '\177' || index(badchars, c)) {
- X (void) sprintf(errstring,
- X "'%c': bad character in filename \"%s\".",
- X c, cell->filename);
- X message(errstring);
- X return(FALSE);
- X }
- X PathParse(cell->filename, fname);
- X stbuf.st_mode = 0;
- X exists = stat(fname, &stbuf);
- X if ((!exists) && (cell->saved & NEWFILE)) {
- X /* We're about to overwrite something */
- X (void) sprintf(errstring,
- X "\"%s\" already exists; overwrite it (y/n)? ",
- X cell->filename);
- X switch (confirm(errstring, "n")) {
- X case ABORT:
- X case NO:
- X return(FALSE);
- X case YES:
- X break;
- X }
- X }
- X if ((cell->mtime != 0) && /* if we care ... */
- X (!exists) && /* and it exists */
- X (stbuf.st_mtime != cell->mtime)) { /* and there's trouble. */
- X (void) sprintf(errstring,
- X "\"%s\" on disk is not what you last read/saved. Overwrite (y/n)? ",
- X cell->filename);
- X switch(confirm(errstring, "n")) {
- X case ABORT:
- X case NO:
- X return(FALSE);
- X case YES:
- X break;
- X }
- X }
- X if ((!exists) && backup)
- X /* Create backup file with same mode as input file */
- X if (file_backup(fname, stbuf.st_mode) == -1) {
- X message("Couldn't write backup file - save failed");
- X return(FALSE);
- X }
- X
- X return(TRUE);
- X}
- END_OF_FILE
- if test 20476 -ne `wc -c <'xpic/xpic.c'`; then
- echo shar: \"'xpic/xpic.c'\" unpacked with wrong size!
- fi
- # end of 'xpic/xpic.c'
- fi
- echo shar: End of archive 14 \(of 15\).
- cp /dev/null ark14isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 15 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-