diff options
-rw-r--r-- | Bugs | 11 | ||||
-rw-r--r-- | Written/FilledRects | 93 | ||||
-rw-r--r-- | Written/Interface | 9 | ||||
-rw-r--r-- | Written/Jim | 255 | ||||
-rw-r--r-- | Written/Notes | 296 | ||||
-rw-r--r-- | Written/Notes2 | 68 | ||||
-rw-r--r-- | Written/Outline | 191 | ||||
-rw-r--r-- | Written/Widget | 26 | ||||
-rw-r--r-- | Xgc.ad | 2 | ||||
-rw-r--r-- | choice.c | 282 | ||||
-rw-r--r-- | constants.h | 76 | ||||
-rw-r--r-- | dashlist.c | 189 | ||||
-rw-r--r-- | getfile.c | 159 | ||||
-rw-r--r-- | gram.y | 116 | ||||
-rw-r--r-- | interpret.c | 429 | ||||
-rw-r--r-- | lex.l | 169 | ||||
-rw-r--r-- | main.c | 510 | ||||
-rw-r--r-- | main.h | 148 | ||||
-rw-r--r-- | planemask.c | 198 | ||||
-rw-r--r-- | record.c | 299 | ||||
-rw-r--r-- | testfrac.c | 205 | ||||
-rw-r--r-- | tests.c | 655 | ||||
-rw-r--r-- | text.c | 209 | ||||
-rw-r--r-- | tile | 17 | ||||
-rw-r--r-- | xgc.h | 64 | ||||
-rw-r--r-- | xgc.man | 38 |
26 files changed, 4714 insertions, 0 deletions
@@ -0,0 +1,11 @@ +Bugs found with xbench +---------------------- +Lines, FillStyle Solid, Planemask 0, LineWidth 0 - draws lines anyways. + other FillStyles work correctly. +Rectangles - same problem. +Filled Rectangles, FillStyle other than OpaqueStippled, Planemask 0 - draws + rectangles anyways. + OpaqueStippled works fine. +Dashed Lines - sometimes hangs. + only happens when lots of lines/short dashes/long lines. +Lines, Function equiv, LineWidth > 1 - copies instead of equiving. diff --git a/Written/FilledRects b/Written/FilledRects new file mode 100644 index 0000000..d72849e --- /dev/null +++ b/Written/FilledRects @@ -0,0 +1,93 @@ +General concerns +---------------- + +Machine type +Display type +Display on different machine? +Visual +Clipping +Obscured by cursor +Background tiling +The whole software vs. hardware bit: computational overhead vs. time spent + drawing +Planemask + +PolyFillRectangle +----------------- +Use same test as PolyRectangle? +Perhaps give FillPoly some of these too, see if it special cases them. +Fill Rectangle vs. Fill Poly for same size areas would be an + interesting comparison. + +Things to look for: + All it's really doing is setting or unsetting planes. + When a whole word is filled, it should be quite fast (just + setting it to 0 or ~0). + Otherwise, the speed of a single rectangle should be about + equal to its size. + +Data: + Pixels per second. + Average size of rectangle. + +GC fields: + function: + Tiling: likely to be a lot slower, although for whole words + you're just setting it to a certain value, rather than 0. + (You also have to look at the y value). Strange width + tiles (are these allowed?) are likely to be real bad. + Stippling: also slower - I'm not sure whether or not this would + be slower than tiling. This probably has a greater + chance of being done in hardware. + + plane-mask: + plane of 0 would be real fast, since it doesn't modify + anything. plane of ~0 should be fast, since it doesn't + have to think. Anything else would probably be + proportional to the number of planes... + + subwindow-mode: I don't believe it matters. + + clip-x-origin + clip-y-origin + clip-mask: + Clipping in general should probably increase speed rather + than decrease it, unless the clipping region is strange. + Possible increase in speed because less change to the + display is being made; possible decrease in speed because + more thought has to be given to what is drawn or not. + Software vs. hardware, I suppose. + +Possibly + foreground: similar to plane-mask in its effect, I would think. + + tile: "nice" width tiles would probably be better. A width which + is not a divisor of the length of a word would be + significantly slower. A width the size of a word is + probably perfect. The actual contents of the tile + probably don't matter: Any code to check for tiles + which could be "simplified" would probably take too much + time to execute to do any good. + + stipple: like tile + +Other: + alignment on word bounaries: fastest when one is changing whole + words at a time. That way, you're just setting whole words to + 0 or ~0 and not doing any computation. A 32x1 rectangle should + be much faster than a 1x32 rectangle. + +--------- +Things to put in test: + +Check all alignments. +Perhaps some sort of comparison between thin rectangles oriented + horizontally and oriented vertically. +Small rectangles, big rectangles: compare pixels/second for each. + Good way of computing overhead costs. + +--------- +test +(1-32)x32 at all 32 bits in a word. +(97-128)x32 +(97-128)x128 diff --git a/Written/Interface b/Written/Interface new file mode 100644 index 0000000..7b40562 --- /dev/null +++ b/Written/Interface @@ -0,0 +1,9 @@ +The command buttons at the top - + + Benchmark Options, Graphics Options, etc. + +should just bring up the window, not force you to use it. + +1) It is nicer to the person who might want to have both up at once. + +2) It is nicer to the programmer who doesn't know how to focus events. diff --git a/Written/Jim b/Written/Jim new file mode 100644 index 0000000..e370cd5 --- /dev/null +++ b/Written/Jim @@ -0,0 +1,255 @@ +The Commands menu should contain the following items: + + Run [the selected benchmark] + Benchmark Options.../Hide Benchmark Options [toggle] + Graphics Options.../Hide Graphics Options [toggle] + Describe Test.../Hide Test Description [toggle] + Start Recording/Stop Recording [toggle] + Playback [pop up a dialogue box asking for filename] + -------- + Quit [pop up a dialogue box asking if we are really done] + + +The Benchmark Options sheet should contain the information shown below. The +list of graphics primitives was derived from the "Definition of the Porting +Layer for the X v11 Sample Server" by Angebranndt et al. and from the Protocol +document. + + + Benchmark Options + + + +-----------------------+-----------------------+ + Test | Copy Area | Copy Plane | + +-----------------------+-----------------------+ + | Points | Lines | + +-----------------------+-----------------------+ + | Segments | Rectangles | + +-----------------------+-----------------------+ + | Arcs | Filled Polygons | + +-----------------------+-----------------------+ + | Filled Rectangles | Filled Arcs | + +-----------------------+-----------------------+ + | Put Image | Get Image | + +-----------------------+-----------------------+ + | Text 8 | Image Text 8 | + +-----------------------+-----------------------+ + | Text 16 | Image Text 16 | + +-----------------------+-----------------------+ + + +---------+ + Iterations | 10000 | + +---------+ + + +----+-----+ +----+-----+ + Record | on | off | Describe Test | on | off | + +----+-----+ +----+-----+ + + +-----------------------------------------------+ + Filename | ./xbench.log | + +-----------------------------------------------+ + + +******************************************************************************* + + +The Graphics Options area would contain the following entries: + + Function - one-of { clear, and, andReverse, copy, andInverted, noop, xor, + or, nor, equiv, invert, orReverse, copyInverted, + orInverted, nand, set } + PlaneMask - unsigned value or many-of-n representing bits + Foreground - unsigned value in range 0..2^nplanes + Background - unsigned value in range 0..2^nplanes + ForegroundColor - set rgb value of Foreground + BackgroundColor - set rgb value of background + LineWidth - unsigned number in range 0..65535 + LineStyle - oneof { Solid, OnOffDash, DoubleDash } + CapStyle - one-of { NotLast, Butt, Round, Projecting } + JoinStyle - one-of { Miter, Round, Bevel } + FillStyle - one-of { Solid, Tiled, OpaqueStippled, Stippled } + FillRule - one-of { EvenOdd, Winding } + ArcMode - one-of { Chord, PieSlice } + # Tile - pixmap [probably not edittable in first version] + # Stipple - pixmap [probably not edittable in first version] + TileStipXOrigin - signed number in range -32768..32767 + TileStipYOrigin - signed number in range -32768..32767 + Font - name of font + ClipXOrigin - signed number in range -32768..32767 + ClipYOrigin - signed number in range -32768..32767 + ClipMask - one-of { None, select } [user selects by clicking in work area] + DashOffset - unsigned number in range -32768..32767 + DashList - many-of-n of 8 boxes for defining dashes + + + + + Graphics Options + + + +--------------+--------------+--------------+--------------+ + Function | clear | and | andReverse | copy | + +--------------+--------------+--------------+--------------+ + | andInverted | noop | xor | or | + +--------------+--------------+--------------+--------------+ + | nor | equiv | invert | orReverse | + +--------------+--------------+--------------+--------------+ + | copyInverted | orInverted | nand | set | + +--------------+--------------+--------------+--------------+ + + +-----+---------+ + Colormap | new | default | + +-----+---------+ + + +----------+ +--------+--------+--------+ + Foreground | 1 | ForegroundColor | ffff | ffff | ffff | + +----------+ +--------+--------+--------+ + + +----------+ +--------+--------+--------+ + Background | 0 | BackgroundColor | 0000 | 0000 | 0000 | + +----------+ +--------+--------+--------+ + + +------+ +-------+-----------+------------+ + LineWidth | 3 | LineStyle | Solid | OnOffDash | DoubleDash | + +------+ +-------+-----------+------------+ + + +---------+------+-------+------------+ + CapStyle | NotLast | Butt | Round | Projecting | + +---------+------+-------+------------+ + + +-------+-------+-------+ + JoinStyle | Miter | Round | Bevel | + +-------+-------+-------+ + + +-------+-------+----------+----------------+ + FillStyle | Solid | Tiled | Stippled | OpaqueStippled | + +-------+-------+----------+----------------+ + + +---------+---------+ + FillRule | EvenOdd | Winding | + +---------+---------+ + + +-------+----------+ + ArcMode | Chord | PieSlice | + +-------+----------+ + + +--------------+ + TStipOrigin | +####, +#### | + +--------------+ + + +-+-+-+-+-+-+-+-+ +-------+ + DashList | | |X|X| | |X|X| DashOffset | +#### | + +-+-+-+-+-+-+-+-+ +-------+ + + +----+-----+-----+-------+ +--------+ + ClipMask | on | off | set | clear | PlaneMask | ffff | + +----+-----+-----+-------+ +--------+ + + +******************************************************************************* + + Grammar + + +Both to support Record/Playback (used for debugging, demonstrations, and for +creating benchmark scripts), there needs to be a command line language that +can be used to set all options. Although we won't be doing anything as +sophisticated as what is provided in many UIMS's, it would be nice to keep +the application section of the benchmark as separate as possible from the +user interface. + + test { CopyArea, CopyPlane, PolyPoint, PolyLine, PolySegment, + PolyRectangle, PolyArc, FillPolygon, PolyFillRect, PolyFillArc, + PutImage, GetImage, ImageText8, PolyText8, ImageText16, + PolyText16 } + - selects the test to be performed. + + colormap { new, default } + - selects which colormap should be used for test + + iterations UNSIGNEDNUMBER + - specifies the number of times that the test should be run. + + record BOOLEAN + - indicates whether or not to record commands into the record-file. + + record-file FILENAME + - specifies the name of the file into which commands are recorded. + + describe BOOLEAN + - indicates whether or not a description of the test should be + displayed whenever a test is selected (or when this option is + specified). + + function { clear, and, andReverse, copy, andInverted, noop, xor, or, nor, + equiv, invert, orReverse, copyInverted, orInverted, nand, set } + - selects the alu function to use in the GC. + + foreground UNSIGNEDNUMBER + - selects the foreground pixel value to use in the GC; if a new + colormap is being used, the RGB value for this slot may be changed. + + background UNSIGNEDNUMBER + - selects the background pixel value to use in the GC; if a new + colormap is being used, the RGB value for this slot may be changed. + + forecolor COLORNAME + - specifies the RGB value or name of the color to be used for the + foreground pixel, if settable. + + backcolor COLORNAME + - specifies the RGB value or name of the color to be used for the + background pixel, if settable. + + linewidth NUMBER + - specifies width of lines to use in the GC. + + linestyle { Solid, OnOffDash, DoubleDash } + - selects the type of lines to use in the GC. + + capstyle { NotLast, Butt, Round, Projecting } + - selects the type of caps to use in the GC. + + joinstyle { Miter, Round, Bevel } + - selects the type of joins to use in the GC. + + fillstyle { Solid, Tiled, Stippled, OpaqueStippled } + - selects the type of fills to use in the GC. + + fillrule { EvenOdd, Winding } + - selects the fill rule to be used in the GC. + + arcmode { Chord, PieSlice } + - selects the type of arcs to be drawn in the GC. + + tsorigin NUMBER NUMBER + - specifies the X and Y values of the TileStippleOrigin in the GC. + + dashlist DASHPATTERN + - specifies a pattern of 8 binary digits to use in the dashlist + in the GC; the characters are given in big-endian order such that + they may be read in binary to form a number between 0 and 255. + + dashoffset NUMBER + - specifies the dashoffset to use in the GC. + + cliporigin NUMBER NUMBER + - specifies the X and Y values of the cliporigin in the GC. + + clipmask { on, off, set NUMBER NUMBER NUMBER NUMBER, clear } + - selects a clipping mode. If "on", then use the most recently + defined set of clipping rectangles; if "off", then do not do + any clipping but keep the clipping rectangles for future + reference; if "set", then add the rectangle specified by + the remaining numeric arguments as X1 Y1 X2 Y2 relative to the + cliporigin. + + planemask NUMBER + - specifies the set of planes on to which graphics may be drawn + in the GC. + + run + - run the currently configured test. + + quit + - exit the program diff --git a/Written/Notes b/Written/Notes new file mode 100644 index 0000000..3b9f416 --- /dev/null +++ b/Written/Notes @@ -0,0 +1,296 @@ + + +ClearArea +--------- +Basically a special case of PolyFillRect. Put up some sort of image first +so we can clear it away. Try both small areas and big areas, to give +credit to servers for optimizing small ones. + +Data: Pixels per second. + Breaking that down into large and small areas would probably not + be userful. + +GC Fields: None. + + +CopyArea +-------- +Putting up some image and then repeatedly copying from one part of it +to another would do the right thing and could look neat if done right. + +We probably want to see what happens when the source area is clipped, +as that as mentioned specifically in the protocol document. + +Data: Pixels per second. + +GC Fields: function (*) + plane-mask + subwindow-mode + graphics-exposures + clip-x-origin + clip-y-origin + clip-mask + + +CopyPlane +--------- +Special case of CopyArea again. + + +PolyPoint +--------- +Draw lots of points. +Either start out with an image that's 50/50 black and white +(preferred) or draw enough points that some points will get drawn at +least twice (to test functions other than copy). + +Data: Points per second. + +GC fields: function (*) + plane-mask + foreground + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask + + +PolyLine +-------- +Circular test like there is now. +Try clipping at window boundaries? + +Data: Lines per second. + Pixels per second (is this valid - do lines that are twice as + long take twice as long to draw? Also, is it valid to compare + thin lines and fat lines?) + +GC fields: function (*) + plane-mask + line-width (*) + line-style (*) + cap-style (*) + join-style (*) + fill-style (*) + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + tile (*) + stipple (*) + tile-stipple-x-origin + tile-stipple-y-origin + dash-offset + dashes (*) + + +PolySegment +----------- +Just like PolyLine but lines don't have to be connected. Crosshatching? + +Data: Lines per second, pixels per second(?) + +GC fields: function + plane-mask + line-width + line-style + cap-style + fill-style + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + tile + stipple + tile-stipple-x-origin + tile-stipple-y-origin + dash-offset + dashes + + +PolyRectangle +------------- +Lots of five point PolyLines. Partly concentric ones would look nice; we +also need overlap for testing different functions. + +Data: Rectangles per second. + Pixels per second? (divide by perimeter) + +GC fields: function + plane-mask + line-width + line-style + join-style + fill-style + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + tile + stipple + tile-stipple-x-origin + tile-stipple-y-origin + dash-offset + dashes + + +PolyArc +------- +Overlapping concentric things (ripples) would look cool. +Is it possible to special-case circles? Test for this? + +Data: Arcs per second? If we had the same test each time this might + be OK. + Pixels per second? Finding the length of an arc could be + annoying. + +GC fields: function + plane-mask + line-width + line-style + cap-style + join-style + fill-style + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + tile + stipple + tile-stipple-x-origin + tile-stipple-y-origin + dash-offset + dashes + + +FillPoly +-------- +Use the same test as PolyLine? +Overlapping is a must to test functions. +Convex vs. Concave polygons. + +Data: Pixels per second, I guess. + Data for convex vs. concave could be interesting. + +GC fields: function + plane-mask + fill-style + fill-rule + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + tile + stipple + tile-stipple-x-origin + tile-stipple-y-origin + + +PolyFillRectangle +----------------- +Use same test as PolyRectangle? +Perhaps give FillPoly some of these too, see if it special cases them. +Fill Rectangle vs. Fill Poly for same size areas would be an + interesting comparison. + +Data: Pixels per second. + +GC fields: function + plane-mask + fill-style + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + tile + stipple + tile-stipple-x-origin + tile-stipple-y-origin + + +PolyFillArc +----------- +Use same test as PolyArc? + +Data: Pixels per second would be hard to compute, but what else is there? + +GC fields: function + plane-mask + fill-style + arc-mode + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + tile + stipple + tile-stipple-x-origin + tile-stipple-y-origin + + +PutImage +-------- + +GC fields: function + plane-mask + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + + +GetImage +-------- + +PolyText8 +--------- + +GC fields: function + plane-mask + fill-style + font + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask +Possibly foreground + background + tile + stipple + tile-stipple-x-origin + tile-stipple-y-origin + + +PolyText16 +---------- + +ImageText8 +---------- + +GC fields: plane-mask + foreground + background + font + subwindow-mode + clip-x-origin + clip-y-origin + clip-mask + +ImageText16 +--------- diff --git a/Written/Notes2 b/Written/Notes2 new file mode 100644 index 0000000..cf3d99d --- /dev/null +++ b/Written/Notes2 @@ -0,0 +1,68 @@ + C |C |C |P |P |P |P |P |F |P |P |P |G |P |P |I |I | + l |o |o |o |o |o |o |o |i |o |o |u |e |o |o |m |m | + e |p |p |l |l |l |l |l |l |l |l |t |t |l |l |a |a | + a |y |y |y |y |y |y |y |l |y |y |I |I |y |y |g |g | + r |A |P |P |L |S |R |A |P |F |F |m |m |T |T |e |e | + A |r |l |o |i |e |e |r |o |i |i |a |a |e |e |T |T | + r |e |a |i |n |g |c |c |l |l |l |g |g |x |x |e |e | + e |a |n |n |e |m |t | |y |l |l |e |e |t |t |x |x | + a | |e |t | |e |a | | |R |A | | |8 |1 |t |t | + | | | | |n |n | | |e |r | | | |6 |8 |1 | + | | | | |t |g | | |c |c | | | | | |6 | + | | | | | |l | | |t | | | | | | | | + | | | | | |e | | |a | | | | | | | | + | | | | | | | | |n | | | | | | | | + | | | | | | | | |g | | | | | | | | + | | | | | | | | |l | | | | | | | | + | | | | | | | | |e | | | | | | | | + | | | | | | | | | | | | | | | | | + | | | | | | | | | | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +function |XX| |XX|XX|XX|XX|XX|XX|XX|XX|XX| |XX|XX| | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +plane_mask |XX| |XX|XX|XX|XX|XX|XX|XX|XX|XX| |XX|XX|XX|XX| +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +foreground | | |XX|**|**|**|**|**|**|**|**| |**|**|XX|XX| +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +background | | | |**|**|**|**|**|**|**|**| |**|**|XX|XX| +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +line_width | | | |XX|XX|XX|XX| | | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +line_style | | | |XX|XX|XX|XX| | | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +cap_style | | | |XX|XX| |XX| | | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +join_style | | | |XX| |XX|XX| | | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +fill_style | | | |XX|XX|XX|XX|XX|XX|XX| | |XX|XX| | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +fill_rule | | | | | | | |XX| | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +arc_mode | | | | | | | | | |XX| | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +tile | | | |**|**|**|**|**|**|**| | |**|**| | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +stipple | | | |**|**|**|**|**|**|**| | |**|**| | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +ts_x_origin | | | |**|**|**|**|**|**|**| | |**|**| | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +ts_y_origin | | | |**|**|**|**|**|**|**| | |**|**| | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +font | | | | | | | | | | | | |XX|XX|XX|XX| +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +subwindow_mode |XX| |XX|XX|XX|XX|XX|XX|XX|XX|XX| |XX|XX|XX|XX| +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +exposures |XX| | | | | | | | | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +clip_x_origin |XX| |XX|XX|XX|XX|XX|XX|XX|XX|XX| |XX|XX|XX|XX| +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +clip_y_origin |XX| |XX|XX|XX|XX|XX|XX|XX|XX|XX| |XX|XX|XX|XX| +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +clip_mask |XX| |XX|XX|XX|XX|XX|XX|XX|XX|XX| |XX|XX|XX|XX| +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +dash_offset | | | |**|**|**|**| | | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +dashes | | | |**|**|**|**| | | | | | | | | | +----------------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + + diff --git a/Written/Outline b/Written/Outline new file mode 100644 index 0000000..d83f3e5 --- /dev/null +++ b/Written/Outline @@ -0,0 +1,191 @@ + + Outline for Xbench + ------------------ + +GENERAL +------- + +Stuff starting with '-' are callbacks for that widget. +'<>' means whatever is appropriate. + +Choice widgets will either be implemented as a new type of widget or a +form containing a bunch of Command widgets. The automatic callbacks for +the commands are: + - set all children of parent to normal colors + - set oneself to reverse colors +There will be a + - put <> in buffer, specified by the parent widget +There will also be a + - put <>\n in buffer +specific to each command. + +In general, the buffer does not need to be looked at until the test is +actually run; however, if we decide to "gray out" choices in the Graphics +Options window that have nothing to do with the benchmark, then choosing +a benchmark must flush also. + +Widgets - we need to decide whether the windows that are turn-on-and-offable +should be children of Form, or of TopLevel. If they're children of Form, +then the user won't be able to stack them or have a say in where they go. +We also might run out of space. If they're children of TopLevel, the user +can decide where they go, but he's going to have to choose their location +(with the wm) every time they come up. I would vote for the latter approach. +(Uh oh... I don't think that the TopLevel widget can have more than one +child...) + +All choosing Widgets should write strings in the Xbench language to some +buffer, where the actual testing thing can pull them out. + + + +HIERARCHY OF WIDGETS +-------------------- + +Form (form) surrounding the whole thing (owned by TopLevel) +Title (label) on top describing version & current test (owned by Form) +MenuLine (form) under Title giving top level choices (owned by Form) +MenuLine contains these Commands: + Run + - flush the buffer + - run benchmark + BenchmarkOptionsOn + - map benchmark options window (BenchmarkOptions) + BenchmarkOptionsOff + - unmap benchmark options window + GraphicsOptionsOn + - map graphics options window (GraphicsOptions) + GraphicsOptionsOff + - unmap graphics options window + DescriptionOn + - map description window (Description) + DescriptionOff + - unmap description window + RecordingOn + - bring up dialog box for name of file + - start saving commands into file (set a global boolean TRUE) + RecordingOff + - stop saving commands into file (set the global boolean FALSE) + Playback + - bring up dialog box for name of file + - read from file until EOF + Quit + - quit + +The toggling command buttons exist in pairs, of which only one is visible at +any one point. This makes callbacks/names of buttons easier to implement. + +--- + +BenchmarkOptions (form) describing benchmark options (owned by Toplevel?) +BenchmarkOptions contains: + TestChoice (choice) the 16 different test choices. + - put "test <>" in buffer + - put description of test in Description window + - call disable_gc_choices() with the GC field flags + Iterations (text) the number of times to run. + - put "iterations <>" in buffer + +--- + +GraphicsOptions (form) describing graphics options (owned by Toplevel?) +GraphicsOptions contains: + ChooseFunction (choice) + - put "function <>" in buffer + ChooseColormap (choice) + - put "colormap <>" in buffer + Foreground (text) + - put "foreground <>" in buffer + Background (text) + - put "background <>" in buffer + LineWidth (text) + - put "linewidth <>" in buffer + LineStyle (choice) + - put "linestyle <>" in buffer + CapStyle (choice) + - put "capstyle <>" in buffer + JoinStyle (choice) + - put "joinstyle <>" in buffer + FillStyle (choice) + - put "fillstyle <>" in buffer + FillRule (choice) + - put "fillrule <>" in buffer + ArcMode (choice) + - put "arcmode <>" in buffer + TStipOrigin (text * 2) + - put "tsorigin <>" in buffer + DashList (???) + - put "dashlist <>" in buffer + DashOffset (text?) + - put "dashoffset <>" in buffer + ClipMask (choice) + - put "clipmask <>" in buffer + Planemask (text) + - put "planemask <>" in buffer + +We need specialized widgets for DashList, possibly TStipOrigin and DashOffset. + +Still to be decided: can one choose GC options that have no meaning for that + particular benchmark? I don't think it should be a problem. + +--- + +Description (text) describing the current test (owned by Toplevel?) + +I really need to find out how to use sources and sinks for Text widgets - +the documentation does not say how to do it. + +Every test will have a block of text associated with it. When a new +benchmark is chosen, its associated text will become the source for the +Description widget. Note that we don't have to worry about whether +Description is mapped or not; we're just setting a source. + +--- + +Analysis (text) describing the results of the current test (owned by Form - +we always want this to be around) + +This will display the name of the test, the important values of the GC, +the results of the test, and a short analysis thereof. If more than +one test of a particular benchmark is performed, it will be appended to +the analysis source (not replacing it). This will allow for comparing +results obtained with different GC's. + +--- + +Test (core + expose event handler) for doing the test. + +All this really needs to do, besides actually doing the test, is to +time it and make sure the Analysis part knows about it. + +--- + +RecordingOn / RecordingOff / Playback + +When the user presses Playback, pretty much all we have to do is to +1) change the buffer to the file that he wants, and 2) start reading. +The rest should be taken care of the buffer-interpreting module. + +RecordingOn changes the output buffer _and_ the input buffer to the +desired file. + +RecordingOff changes them both back to the usual. + + + + + + + + + + + + + + + + + + + + diff --git a/Written/Widget b/Written/Widget new file mode 100644 index 0000000..c653dfd --- /dev/null +++ b/Written/Widget @@ -0,0 +1,26 @@ +What we need is a widget which presents a collection of buttons. The user +can select only one of them at a time. When one is selected, its +foreground and background colors should be reversed and stay that way +until another one is selected. Exactly one button can be selected at +any one time. + +Possible implementations: + +1. As a new kind of widget. bleah. + + +2. Box surrounding a lot of command buttons. The command buttons have + the appropriate callbacks. + +Callbacks: a) set all buttons to normal colors + b) set this button to reverse colors + c) change the appropriate variable to the desired value. + + This can all be done at the time of creation, thus the buttons would + be invisible to the rest of the program (a good thing). + + + +(2) would be a heck of a lot easier to program, since creating widgets is +a bitch. However, (1) could come in handy outside of this program. Perhaps +write it using (2) and switch to (1) if/when we can get the widget working. @@ -0,0 +1,2 @@ +*planemask*ShapeStyle: rectangle +*dashlist*ShapeStyle: rectangle diff --git a/choice.c b/choice.c new file mode 100644 index 0000000..57cf80d --- /dev/null +++ b/choice.c @@ -0,0 +1,282 @@ +/* +** xgc +** +** choice.c +** +** All the generic stuff for dealing with choice widgets. +*/ + +#include <stdio.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/Toggle.h> + +#include "xgc.h" + +static void print_text_to_buffer( +#if NeedFunctionPrototypes + Widget, caddr_t, caddr_t +#endif +); +extern void interpret(); + +extern XStuff X; + +/* create_choice(w,info) +** --------------------- +** What a choice widget is: A collection of toggle buttons placed inside +** a form widget. Exactly one of these toggle buttons can be "on" at +** any given time; the rest are "off". "On" toggle buttons have +** the foreground and background colors reversed. +** Also, specifically because it comes in handy in xgc, choosing one +** of the buttons causes a string associated with it to be printed out +** (and interpreted). Half of the string is global to the whole form +** and the other half is local to each button. +** +** For example, pressing the "xor" button in the "function" form would +** cause xgc to interpret the string "function xor", thus changing the +** function in the GC to xor. +** +** There's also a label widget to the left of that mess, with an +** incredibly descriptive title. +** +** create_choice() makes one. +** +** w is the form widget (already created) into which we will place the +** toggle buttons. info contains lots of useful information, such +** as the names of the buttons and their strings (see xgc.h). +*/ + +ChoiceDesc * +create_choice(w,info) + Widget w; + XgcStuff *info; +{ + ChoiceDesc *choice; /* What we will return. Contains + ** Widget ID's of the label and toggles. */ + int i; /* Counter */ + char *text; /* Text to be interpreted when the + ** toggle widget is selected. */ + + /* ArgList for the label widget */ + static Arg labelargs[] = { + {XtNborderWidth, (XtArgVal) 0}, + {XtNjustify, (XtArgVal) XtJustifyRight}, + {XtNvertDistance, (XtArgVal) 4} + }; + + /* ArgList for the toggle widgets */ + static Arg toggleargs[] = { + {XtNfromHoriz, (XtArgVal) NULL}, + {XtNfromVert, (XtArgVal) NULL}, + {XtNhorizDistance, (XtArgVal) 4}, + {XtNvertDistance, (XtArgVal) 4}, + {XtNradioGroup, (XtArgVal) NULL}, + {XtNcallback, (XtArgVal) NULL} + }; + + /* Callback list for the toggle widgets */ + static XtCallbackRec callbacklist[] = { + {(XtCallbackProc) print_text_to_buffer, NULL}, + {NULL, NULL} + }; + + /* Allocate space for the widgets and initialize choice */ + choice = (ChoiceDesc *) XtMalloc(sizeof(ChoiceDesc)); + choice->widgets = (WidgetList) XtMalloc(sizeof(Widget) * + info->choice.num_toggles); + choice->size = info->choice.num_toggles; + choice->label = XtCreateManagedWidget(info->choice.name,labelWidgetClass,w, + labelargs,XtNumber(labelargs)); + + /* set up the toggle widgets */ + toggleargs[5].value = (XtArgVal) callbacklist; + for (i = 0; i < info->choice.num_toggles; ++i) { + if (i == 0) { + /* the upper left toggle; put it next to the label + and don't worry about radio groups */ + toggleargs[0].value = (XtArgVal) choice->label; + toggleargs[1].value = (XtArgVal) NULL; + toggleargs[2].value = (XtArgVal) 10; + toggleargs[3].value = (XtArgVal) 4; + toggleargs[4].value = (XtArgVal) NULL; + } + else { + toggleargs[4].value = (XtArgVal) choice->widgets[0]; + /* are we starting a new row? */ + if (info->choice.columns > 0 && + i > 1 && + (i % (info->choice.columns) == 0)) { + toggleargs[0].value = (XtArgVal) choice->label; + /* under the appropriate toggle */ + toggleargs[1].value = (XtArgVal) choice->widgets[i - info->choice.columns]; + toggleargs[2].value = (XtArgVal) 10; + toggleargs[3].value = (XtArgVal) 4; + } + else { /* we're in the middle of a row */ + /* to the right of the previous toggle */ + toggleargs[0].value = (XtArgVal) choice->widgets[i - 1]; + toggleargs[1].value = (XtArgVal) NULL; + toggleargs[2].value = (XtArgVal) -1; /* overlapping slightly */ + toggleargs[3].value = (XtArgVal) 4; + } + + if (info->choice.columns > 0 && + i >= info->choice.columns) { + /* correct vertical spacing */ + toggleargs[1].value = (XtArgVal) choice->widgets[i - info->choice.columns]; + toggleargs[3].value = (XtArgVal) -1; + } + } + + /* Put the correct stuff in the text field */ + text = (char *) XtMalloc((unsigned) (strlen(info->choice.text) + + strlen((info->data)[i].text) + 3)); + strcpy(text, info->choice.text); + strcat(text, " "); + strcat(text, (info->data)[i].text); + strcat(text, "\n"); + callbacklist[0].closure = (caddr_t) text; + + /* Create it finally */ + choice->widgets[i] = XtCreateManagedWidget((info->data[i]).name, + toggleWidgetClass, + w, + toggleargs, + XtNumber(toggleargs)); + } + + /* The toggle widgets have all been created; + ** now make the all the same width if that's + ** what we want to do. */ + + if (info->choice.columns > 0) { + Dimension maxwidth = 0; /* maximum width we've found */ + Dimension width; /* width of the current widget */ + static Arg args[] = { /* for getting and setting the width */ + {XtNwidth, (XtArgVal) NULL} + }; + + args[0].value = (XtArgVal) &width; + + /* Find the maximum width of any toggle widget */ + for (i = 0; i < info->choice.num_toggles; ++i) { + XtGetValues(choice->widgets[i],args,1); + maxwidth = max(maxwidth,width); + } + + /* Now set them all to that width */ + args[0].value = (XtArgVal) maxwidth; + for (i = 0; i < info->choice.num_toggles; ++i) + XtSetValues(choice->widgets[i],args,1); + } + + /* return the list of toggles that were just created */ + return (choice); +} + + + +/* select_button(choice,togglenum) +** ------------------------------- +** "Selects" the togglenumth toggle widget in the choice layout +** represented by choice. It simply turns the widget on, as if the +** user had selected it, without calling any callbacks. It's used +** to give feedback when reading from a script. +*/ + +void +select_button(choice,togglenum) + ChoiceDesc *choice; + int togglenum; +{ + static Arg toggleargs[] = { + {XtNstate, (XtArgVal) True} + }; + + XtSetValues(choice->widgets[togglenum],toggleargs,XtNumber(toggleargs)); +} + +/* line_up_labels(descs,numdescs) +** ------------------------------ +** descs represents a bunch of choice layouts (numdescs is the size of +** descs). This function sets each label in descs to the same width, +** thus making them line up nicely since they're all on the left margin. +*/ + +void +line_up_labels(descs,numdescs) + ChoiceDesc *descs[]; + int numdescs; +{ + int i; /* counter */ + Dimension width; /* current width */ + Dimension maxwidth = (Dimension) 0; /* max width found */ + + static Arg widthargs[] = { + {XtNwidth, (XtArgVal) NULL } + }; + + widthargs[0].value = (XtArgVal) &width; + + /* Find the maximum width */ + for (i = 0; i < numdescs; ++i) { + XtGetValues(descs[i]->label, widthargs, XtNumber(widthargs)); + maxwidth = max(maxwidth,width); + } + + /* Set all labels to that width */ + widthargs[0].value = (XtArgVal) maxwidth; + for (i = 0; i < numdescs; ++i) { + XtSetValues(descs[i]->label, widthargs, XtNumber(widthargs)); + } +} + +/* choose_defaults(descs,numdescs) +** ------------------------------- +** descs represents a bunch of choice layouts (numdescs is the size of +** descs). This function goes through all of descs and selects the +** appropriate toggle widget for each one. This includes calling +** the callbacks associated with that widget. +** +** This function ends up initializing both the screen and the GC, and +** ensures that they are consistent. +*/ + +void +choose_defaults(descs,numdescs) + ChoiceDesc *descs[]; + int numdescs; +{ + int i; /* which choice layout */ + int j; /* which toggle within it */ + + for (i = 0; i < numdescs; ++i) { + j = 0; + if (i == 0) + j = 3; + select_button(descs[i],j); + XtCallCallbacks(descs[i]->widgets[j], XtNcallback, (caddr_t) NULL); + } +} + + +/* print_text_to_buffer(w,closure,call_data) +** ----------------------------------------- +** This is also in the list of callbacks for the toggle buttons in a +** choice widget. It sends the string contained in closure (which +** was set way back in create_choice()) over to interpret(), which +** decides what to do with it. +*/ + +/*ARGSUSED*/ +static void +print_text_to_buffer(w,closure,call_data) + Widget w; + caddr_t closure; /* contains the string */ + caddr_t call_data; +{ + interpret((char *) closure); /* Gee, that was easy */ +} diff --git a/constants.h b/constants.h new file mode 100644 index 0000000..495ff94 --- /dev/null +++ b/constants.h @@ -0,0 +1,76 @@ +/* +** xgc +** +** constants.h +** +** Lots of constants which many files need. +*/ + +/* Find the max of two numbers */ +#ifndef max +#define max(x,y) (((x)>(y))?(x):(y)) +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAXCHOICES 16 /* Max # of choices for any option */ + +#define Black BlackPixel(X.dpy,0) +#define White WhitePixel(X.dpy,0) + +#define CopyArea 0 /* different tests */ +#define CopyPlane 1 +#define PolyPoint 2 +#define PolyLine 3 +#define PolySegment 4 +#define PolyRectangle 5 +#define PolyArc 6 +#define FillPolygon 7 +#define PolyFillRect 8 +#define PolyFillArc 9 +#define PutImage 10 +#define GetImage 11 +#define PolyText8 12 +#define ImageText8 13 +#define PolyText16 14 +#define ImageText16 15 + +#define CFunction 0 /* different GC things you can choose */ +#define CLinestyle 1 +#define CCapstyle 2 +#define CJoinstyle 3 +#define CFillstyle 4 +#define CFillrule 5 +#define CArcmode 6 +#define NUMCHOICES 7 +#define CTest 7 + +#define TLineWidth 0 /* different editable text widgets */ +#define TFont 1 +#define TForeground 2 +#define TBackground 3 +#define NUMTEXTWIDGETS 4 + +#define StartTimer 0 /* flags for timing tests */ +#define EndTimer 1 +#define start_timer() timer(StartTimer) +#define end_timer() timer(EndTimer) + +/* the number of toggle widgets in various groups */ +#define NUM_TESTS 16 +#define NUM_FUNCTIONS 16 +#define NUM_LINESTYLES 3 +#define NUM_CAPSTYLES 4 +#define NUM_JOINSTYLES 3 +#define NUM_FILLSTYLES 4 +#define NUM_FILLRULES 2 +#define NUM_ARCMODES 2 + +/* The number of bits in the dash description */ +#define DASHLENGTH 8 diff --git a/dashlist.c b/dashlist.c new file mode 100644 index 0000000..ddfcf09 --- /dev/null +++ b/dashlist.c @@ -0,0 +1,189 @@ +/* +** dashlist.c +** +** How to make a widget to choose a dashlist. +** +** NOTE: This file uses static variables. Therefore, trying to use these +** functions to create more than one of these dashlist choice things +** will fail in a big way. +*/ +/* $XFree86: xc/programs/xgc/dashlist.c,v 1.3 2001/07/29 21:23:21 tsi Exp $ */ + +#include <stdio.h> +#include <X11/Xos.h> +#include <stdlib.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/Toggle.h> +#include "xgc.h" + +static void change_dashlist( +#if NeedFunctionPrototypes + Widget, caddr_t, caddr_t +#endif +); +extern void interpret(); + +extern XStuff X; + +static short dashlist = 240; /* in binary, becomes the dashlist + (240 = XXXX____) */ +static Widget *dashes; /* the toggle widgets */ + +/* create_dashlist_choice(w) +** ------------------------- +** Inside w (a form widget), creates a bunch of little toggle buttons +** in a row, representing the dash list. There's also a label so +** the user knows what it is. +*/ + +void +create_dashlist_choice(w) + Widget w; +{ + /* callback list for the toggle widgets */ + static XtCallbackRec callbacklist[] = { + {(XtCallbackProc) change_dashlist, NULL}, + {NULL, NULL} + }; + + /* ArgList for the label */ + static Arg labelargs[] = { + {XtNborderWidth, (XtArgVal) 0}, + {XtNjustify, (XtArgVal) XtJustifyRight}, + {XtNvertDistance, (XtArgVal) 4} + }; + + /* ArgList for the toggles */ + static Arg dashargs[] = { + {XtNcallback, (XtArgVal) NULL}, + {XtNhorizDistance, (XtArgVal) NULL}, + {XtNfromHoriz, (XtArgVal) NULL}, + {XtNwidth, (XtArgVal) 10}, + {XtNheight, (XtArgVal) 10}, + {XtNhighlightThickness, (XtArgVal) 1}, + {XtNstate, (XtArgVal) False}, + {XtNlabel, (XtArgVal) ""} + }; + + static Widget label; /* the label, of course */ + static int *dashinfo; /* contains integers saying which bit + a particular button is; sent to + change_dashlist to tell it which + bit got changed */ + int i; /* counter */ + + char name[11]; + + /* allocate space for stuff that we don't know the size of yet */ + dashes = (Widget *) malloc(DASHLENGTH * sizeof(Widget)); + dashinfo = (int *) malloc(DASHLENGTH * sizeof(int)); + + /* make the label widget */ + label = XtCreateManagedWidget("dashlist",labelWidgetClass,w, + labelargs,XtNumber(labelargs)); + + dashargs[0].value = (XtArgVal) callbacklist; + + for (i=0;i<DASHLENGTH;++i) { /* go through all the buttons */ + if (i==0) { /* offset the first one from the label */ + dashargs[1].value = (XtArgVal) 10; + dashargs[2].value = (XtArgVal) label; + } + else { /* put it directly to the right of the + last one, no space in between */ + dashargs[1].value = (XtArgVal) -1; + dashargs[2].value = (XtArgVal) dashes[i-1]; + } + + /* set its original state depending on the state of that + ** bit of the dashlist */ + + if (dashlist&1<<i) + dashargs[6].value = (XtArgVal) True; + else + dashargs[6].value = (XtArgVal) False; + + sprintf(name,"dashlist%d",i); + + dashinfo[i] = i; /* which bit we're on; this is needed + in change_dashlist (the callback) */ + callbacklist[0].closure = (caddr_t) &dashinfo[i]; + + dashes[i] = XtCreateManagedWidget(name,toggleWidgetClass,w, + dashargs,XtNumber(dashargs)); + } +} + +/* change_dashlist(w,closure,call_data) +** ------------------------------------ +** This function is called when the user toggles a toggle widget. It +** makes the appropriate change to the dashlist and sends it off +** to interpret(). +** Funny args are because it's a callback. +*/ + +/*ARGSUSED*/ +static void +change_dashlist(w,closure,call_data) + Widget w; + caddr_t closure; + caddr_t call_data; +{ + int num; /* what number button it is */ + Boolean on; /* is it currently on or off? */ + + char buf[80]; /* string to send to interpret() */ + + static Arg args[] = { + {XtNstate, (XtArgVal) NULL} + }; + + /* set up ArgList so that 'on' will contain the state */ + args[0].value = (XtArgVal) &on; + + num = * (int *) closure; /* we put it here back in the last function */ + XtGetValues(w,args,XtNumber(args)); + + /* modify the dashlist as appropriate. */ + if (on) { + dashlist |= 1<<num; + } + else { + dashlist &= ~(1<<num); + } + + /* now tell interpret() about it */ + sprintf(buf,"dashlist %d\n",dashlist); + interpret(buf,FALSE); +} + +/* update_dashlist(newdash) +** ------------------------ +** Updates the display of the dashlist so that it corresponds to +** newdash. +*/ + +void +update_dashlist(newdash) + int newdash; +{ + int i; /* counter */ + static Arg dashargs[] = { /* Arglist for setting toggle state */ + {XtNstate, (XtArgVal) NULL} + }; + + /* first set the internal representation */ + dashlist = newdash; + + for (i = 0; i < DASHLENGTH; ++i) { + if (newdash & 1<<i) /* if it's set, make it look that way */ + dashargs[0].value = (XtArgVal) True; + else + dashargs[0].value = (XtArgVal) False; + + XtSetValues(dashes[i],dashargs,XtNumber(dashargs)); + } +} diff --git a/getfile.c b/getfile.c new file mode 100644 index 0000000..c72ad33 --- /dev/null +++ b/getfile.c @@ -0,0 +1,159 @@ +/* +** getfilename.c +** +*/ +/* $XFree86: xc/programs/xgc/getfile.c,v 1.3 2000/02/17 14:00:35 dawes Exp $ */ + +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/Command.h> +#include <X11/Xaw/Form.h> +#include <X11/Shell.h> +#include <X11/Xaw/AsciiText.h> +#include <stdio.h> + +#include "xgc.h" + +extern XStuff X; +extern Widget topform; + +static Widget popupshell = NULL; /* popup dialog box */ +Widget filename_text_widget; /* Widget containing the name of + the file the user has selected */ +extern XtAppContext appcontext; + +static void kill_popup_shell(); + +void +get_filename(success,failure) + void (*success)(); /* what function to call when a filename is + chosen */ + void (*failure)(); /* what function to call when the user + cancels */ +{ + static Widget popupform; /* form inside shell */ + static Widget label; /* "Filename :" */ + static Widget cancel; /* command, select to cancel */ + + Window dummy1, dummy2; + int x1,y1,x2,y2; + unsigned int mask; + + /* The translation table for the text widget. Things such as <RETURN> + ** confirm the user's choice. Other keys which would move out of + ** the range of a one-line window are disabled. */ + + static const char *translationtable = + "Ctrl<Key>J: KillPopup() Done()\n\ + Ctrl<Key>M: KillPopup() Done()\n\ + <Key>Linefeed: KillPopup() Done()\n\ + <Key>Return: KillPopup() Done()\n\ + Ctrl<Key>O: Nothing()\n\ + Meta<Key>I: Nothing()\n\ + Ctrl<Key>N: Nothing()\n\ + Ctrl<Key>P: Nothing()\n\ + Ctrl<Key>Z: Nothing()\n\ + Meta<Key>Z: Nothing()\n\ + Ctrl<Key>V: Nothing()\n\ + Meta<Key>V: Nothing()"; + + /* What the actions in the translation table correspond to. */ + + static XtActionsRec actiontable[] = { + {"KillPopup", (XtActionProc) kill_popup_shell}, + {"Done", NULL}, + {"Nothing", NULL} + }; + + static Arg popupshellargs[] = { /* Where to put the popup shell. */ + {XtNx, (XtArgVal) NULL}, + {XtNy, (XtArgVal) NULL} + }; + + static Arg labelargs[] = { /* ArgList for the label */ + {XtNborderWidth, (XtArgVal) 0}, + {XtNjustify, (XtArgVal) XtJustifyRight} + }; + + static Arg textargs[] = { /* ArgList for the text widget */ + {XtNeditType, (XtArgVal) XawtextEdit}, + {XtNwidth, (XtArgVal) 200}, + {XtNhorizDistance, (XtArgVal) 10}, + {XtNfromHoriz, (XtArgVal) NULL}, + }; + + static Arg cancelargs[] = { /* ArgList for the cancel button */ + {XtNfromHoriz, (XtArgVal) NULL}, + {XtNcallback, (XtArgVal) NULL} + }; + + /* Procedures to call when the user selects 'cancel' */ + static XtCallbackRec cancelcallbacklist[] = { + {(XtCallbackProc) kill_popup_shell, NULL}, + {NULL, NULL}, + {NULL, NULL} + }; + + if (popupshell != NULL) { + XtPopup(popupshell,XtGrabExclusive); + return; + } + + /* Find out where the pointer is, so we can put the popup window there */ + + (void) XQueryPointer(X.dpy,XtWindow(topform),&dummy1,&dummy2,&x1,&y1, + &x2,&y2,&mask); + + popupshellargs[0].value = (XtArgVal) x2; + popupshellargs[1].value = (XtArgVal) y2; + + popupshell = XtCreatePopupShell("popup",overrideShellWidgetClass, + topform,popupshellargs,XtNumber(popupshellargs)); + + popupform = XtCreateManagedWidget("form",formWidgetClass,popupshell, + NULL, 0); + + label = XtCreateManagedWidget("Filename: ",labelWidgetClass,popupform, + labelargs,XtNumber(labelargs)); + + textargs[3].value = (XtArgVal) label; + + filename_text_widget = XtCreateManagedWidget("text",asciiTextWidgetClass, + popupform, + textargs,XtNumber(textargs)); + + /* Complete the action table. We have to do it here because success + ** isn't known at compile time. */ + + actiontable[1].proc = (XtActionProc) success; + + /* Register actions, translations, callbacks */ + + XtAppAddActions(appcontext,actiontable,XtNumber(actiontable)); + XtOverrideTranslations(filename_text_widget, + XtParseTranslationTable(translationtable)); + cancelcallbacklist[1].callback = (XtCallbackProc) failure; + + cancelargs[0].value = (XtArgVal) filename_text_widget; + cancelargs[1].value = (XtArgVal) cancelcallbacklist; + + cancel = XtCreateManagedWidget("Cancel",commandWidgetClass,popupform, + cancelargs,XtNumber(cancelargs)); + + /* Bring up the popup. When the user presses cancel or the return key, + ** the function kill_popup_shell (below) will be called to remove it. */ + + XtPopup(popupshell,XtGrabExclusive); +} + +/* kill_popup_shell() +** ------------------ +** Remove the popup window that get_filename popped up. +*/ + +static void +kill_popup_shell() +{ + XtPopdown(popupshell); +} @@ -0,0 +1,116 @@ +/* +** grammar for xgc syntax +*/ +/* $XFree86: xc/programs/xgc/gram.y,v 1.3 2000/02/17 14:00:36 dawes Exp $ */ + +%{ +#define YYDEBUG 1 + +#include <stdio.h> +#include <X11/X.h> +#include "constants.h" + +extern int yylineno; +extern FILE *yyin; +int yylex(); +void yyerror(); + +extern void GC_change_function(); +extern void GC_change_foreground(); +extern void GC_change_background(); +extern void GC_change_linewidth(); +extern void GC_change_linestyle(); +extern void GC_change_capstyle(); +extern void GC_change_joinstyle(); +extern void GC_change_fillstyle(); +extern void GC_change_fillrule(); +extern void GC_change_arcmode(); +extern void GC_change_dashlist(); +extern void GC_change_planemask(); +extern void GC_change_font(); +extern void change_test(); +extern void change_percent(); +extern void run_test(); +%} + +%union +{ + int num; + char *ptr; +}; + +%token <ptr> STRING +%token <num> NUMBER +%token <num> RUN +%token <num> FUNCTION FUNCTIONTYPE +%token <num> TEST TESTTYPE +%token <num> LINESTYLE LINESTYLETYPE +%token <num> CAPSTYLE CAPSTYLETYPE +%token <num> JOINSTYLE JOINSTYLETYPE +%token <num> ROUND SOLID +%token <num> FILLSTYLE FILLSTYLETYPE +%token <num> FILLRULE FILLRULETYPE +%token <num> ARCMODE ARCMODETYPE +%token <num> FOREGROUND BACKGROUND LINEWIDTH PLANEMASK DASHLIST PERCENT +%token <num> FONT + +%% + +all : stmts + ; + +stmts : /* empty */ + | stmts '\n' + | stmts stmt '\n' + ; + +stmt : error + | RUN + { run_test(); } + | TEST TESTTYPE + { change_test ($2, TRUE); } + | FUNCTION FUNCTIONTYPE + { GC_change_function ($2, TRUE); } + | LINESTYLE LINESTYLETYPE + { GC_change_linestyle ($2, TRUE); } + | LINESTYLE SOLID + { GC_change_linestyle (LineSolid, TRUE); } + | CAPSTYLE CAPSTYLETYPE + { GC_change_capstyle ($2, TRUE); } + | CAPSTYLE ROUND + { GC_change_capstyle (CapRound, TRUE); } + | JOINSTYLE JOINSTYLETYPE + { GC_change_joinstyle ($2, TRUE); } + | JOINSTYLE ROUND + { GC_change_joinstyle (JoinRound, TRUE); } + | FILLSTYLE FILLSTYLETYPE + { GC_change_fillstyle ($2, TRUE); } + | FILLSTYLE SOLID + { GC_change_fillstyle (FillSolid, TRUE); } + | FILLRULE FILLRULETYPE + { GC_change_fillrule ($2, TRUE); } + | ARCMODE ARCMODETYPE + { GC_change_arcmode ($2, TRUE); } + | FOREGROUND NUMBER + { GC_change_foreground ($2, TRUE); } + | BACKGROUND NUMBER + { GC_change_background ($2, TRUE); } + | LINEWIDTH NUMBER + { GC_change_linewidth ($2, TRUE); } + | PLANEMASK NUMBER + { GC_change_planemask ($2, TRUE); } + | DASHLIST NUMBER + { GC_change_dashlist ($2, TRUE); } + | FONT STRING + { GC_change_font ($2, TRUE); } + | PERCENT NUMBER + { change_percent ($2, TRUE); } + ; + +%% +void +yyerror(s) + const char *s; +{ + fprintf(stderr, "xgc: syntax error, line %d\n", yylineno); +} diff --git a/interpret.c b/interpret.c new file mode 100644 index 0000000..d12922b --- /dev/null +++ b/interpret.c @@ -0,0 +1,429 @@ +/* +** interpret.c +** +** interprets and executes lines in the Xgc syntax. +*/ +/* $XFree86: xc/programs/xgc/interpret.c,v 1.4 2002/01/07 20:38:30 dawes Exp $ */ + +#include <stdio.h> +#include <stdlib.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include "xgc.h" +#include "tile" + +void change_text(); +void GC_change_function(); +void GC_change_foreground(); +void GC_change_background(); +void GC_change_linewidth(); +void GC_change_linestyle(); +void GC_change_capstyle(); +void GC_change_joinstyle(); +void GC_change_fillstyle(); +void GC_change_fillrule(); +void GC_change_arcmode(); +void GC_change_dashlist(); +void GC_change_planemask(); +void GC_change_font(); +void change_test(); +void change_percent(); + +extern void update_dashlist(); +extern void update_planemask(); +extern void update_slider(); +extern void select_button(); +extern void run_test(); +extern void print_if_recording(); + +extern XgcStuff TestStuff; +extern XgcStuff FunctionStuff; +extern XgcStuff LinestyleStuff; +extern XgcStuff CapstyleStuff; +extern XgcStuff JoinstyleStuff; +extern XgcStuff FillstyleStuff; +extern XgcStuff FillruleStuff; +extern XgcStuff ArcmodeStuff; + +extern XStuff X; +extern ChoiceDesc *GCdescs[]; +extern ChoiceDesc *testchoicedesc; +extern Widget test; +extern Widget GCform; +extern Widget foregroundtext; +extern Widget backgroundtext; +extern Widget linewidthtext; +extern Widget fonttext; +extern Widget dashlistchoice; +extern Widget planemaskchoice; +extern Widget testchoiceform; + +extern int fildes[2]; +extern FILE *outend; +extern FILE *yyin; + +/* interpret(string) +** ----------------- +** Takes string, which is a line written in the xgc syntax, figures +** out what it means, and passes the buck to the right procedure. +** That procedure gets called with feedback set to FALSE; interpret() +** is only called if the user is selecting things interactively. +** +** This procedure will go away when I can figure out how to make yacc +** and lex read from strings as well as files. +*/ + +void +interpret(string) + const char *string; +{ + char word1[20], word2[80]; + int i; + + sscanf(string,"%s",word1); + if (!strcmp(word1,"run")) run_test(); + + else { + sscanf(string,"%s %s",word1,word2); + print_if_recording(string); + + /* So word1 is the first word on the line and word2 is the second. + Now the fun begins... */ + + if (!strcmp(word1,TestStuff.choice.text)) { + for (i=0;i<NUM_TESTS;++i) { + if (!strcmp(word2,(TestStuff.data)[i].text)) { + change_test((TestStuff.data)[i].code,FALSE); + break; + } + } + } + else if (!strcmp(word1,FunctionStuff.choice.text)) { + for (i=0;i<NUM_FUNCTIONS;++i) { + if (!strcmp(word2,(FunctionStuff.data)[i].text)) { + GC_change_function((FunctionStuff.data)[i].code,FALSE); + break; + } + } + } + else if (!strcmp(word1,LinestyleStuff.choice.text)) { + for (i=0;i<NUM_LINESTYLES;++i) { + if (!strcmp(word2,(LinestyleStuff.data)[i].text)) { + GC_change_linestyle((LinestyleStuff.data)[i].code,FALSE); + break; + } + } + } + else if (!strcmp(word1,"linewidth")) + GC_change_linewidth(atoi(word2),FALSE); + else if (!strcmp(word1,CapstyleStuff.choice.text)) { + for (i=0;i<NUM_CAPSTYLES;++i) { + if (!strcmp(word2,(CapstyleStuff.data)[i].text)) { + GC_change_capstyle((CapstyleStuff.data)[i].code,FALSE); + break; + } + } + } + else if (!strcmp(word1,JoinstyleStuff.choice.text)) { + for (i=0;i<NUM_JOINSTYLES;++i) { + if (!strcmp(word2,(JoinstyleStuff.data)[i].text)) { + GC_change_joinstyle((JoinstyleStuff.data)[i].code,FALSE); + break; + } + } + } + else if (!strcmp(word1,FillstyleStuff.choice.text)) { + for (i=0;i<NUM_FILLSTYLES;++i) { + if (!strcmp(word2,(FillstyleStuff.data)[i].text)) { + GC_change_fillstyle((FillstyleStuff.data)[i].code,FALSE); + break; + } + } + } + else if (!strcmp(word1,FillruleStuff.choice.text)) { + for (i=0;i<NUM_FILLRULES;++i) { + if (!strcmp(word2,(FillruleStuff.data)[i].text)) { + GC_change_fillrule((FillruleStuff.data)[i].code,FALSE); + break; + } + } + } + else if (!strcmp(word1,ArcmodeStuff.choice.text)) { + for (i=0;i<NUM_ARCMODES;++i) { + if (!strcmp(word2,(ArcmodeStuff.data)[i].text)) { + GC_change_arcmode((ArcmodeStuff.data)[i].code,FALSE); + break; + } + } + } + else if (!strcmp(word1,"planemask")) + GC_change_planemask((unsigned long) atoi(word2),FALSE); + else if (!strcmp(word1,"dashlist")) + GC_change_dashlist(atoi(word2),FALSE); + else if (!strcmp(word1,"font")) + GC_change_font(word2,FALSE); + else if (!strcmp(word1,"foreground")) + GC_change_foreground((unsigned long) atoi(word2),FALSE); + else if (!strcmp(word1,"background")) + GC_change_background((unsigned long) atoi(word2),FALSE); + else if (!strcmp(word1,"percent")) + change_percent(atoi(word2), FALSE); + else fprintf(stderr,"Ack... %s %s\n",word1,word2); + } +} + +#ifdef notdef +void +interpret(instring) + const char *instring; +{ + FILE *inend; + + print_if_recording(instring); + yyin = outend; + inend = fdopen(fildes[1],"w"); + fprintf(inend,"%s",instring); + fclose(inend); + yyparse(); +} +#endif + +#define select_correct_button(which,number) \ + select_button(GCdescs[(which)],(number)); + +/* GC_change_blahzee(foo,feedback) +** --------------------- +** Changes the blahzee field in xgc's GC to foo. If feedback is TRUE, +** changes the display to reflect this (makes it look like the user +** selected the button, or typed in the text, or whatever). +*/ + +void +GC_change_function(function,feedback) + int function; + Boolean feedback; +{ + XSetFunction(X.dpy,X.gc,function); + X.gcv.function = function; + if (feedback) select_correct_button(CFunction,function); +} + +void +GC_change_foreground(foreground,feedback) + unsigned long foreground; + Boolean feedback; +{ + char text[40]; + + XSetForeground(X.dpy,X.miscgc,foreground); + XCopyPlane(X.dpy,X.stipple,X.tile,X.miscgc,0,0,tile_width,tile_height,0,0,1); + XSetForeground(X.dpy,X.gc,foreground); + X.gcv.foreground = foreground; + XSetTile(X.dpy,X.gc,X.tile); + XSetTile(X.dpy,X.miscgc,X.tile); + if (feedback) { + sprintf(text,"%lu",foreground); + change_text(foregroundtext,text); + } +} + +void +GC_change_background(background,feedback) + unsigned long background; + Boolean feedback; +{ + char text[40]; + + XSetBackground(X.dpy,X.miscgc,background); + XCopyPlane(X.dpy,X.stipple,X.tile,X.miscgc,0,0,tile_width,tile_height,0,0,1); + XSetBackground(X.dpy,X.gc,background); + X.gcv.background = background; + XSetTile(X.dpy,X.gc,X.tile); + XSetTile(X.dpy,X.miscgc,X.tile); + + /* Update the background of the test window NOW. */ + + XSetWindowBackground(X.dpy,XtWindow(test),background); + XClearWindow(X.dpy,XtWindow(test)); + + if (feedback) { + sprintf(text,"%lu",background); + change_text(backgroundtext,text); + } +} + +void +GC_change_linewidth(linewidth,feedback) + int linewidth; + Boolean feedback; +{ + char text[40]; + + X.gcv.line_width = linewidth; + XChangeGC(X.dpy,X.gc,GCLineWidth,&X.gcv); + if (feedback) { + sprintf(text,"%d",linewidth); + change_text(linewidthtext,text); + } +} + +void +GC_change_linestyle(linestyle,feedback) + int linestyle; + Boolean feedback; +{ + X.gcv.line_style = linestyle; + XChangeGC(X.dpy,X.gc,GCLineStyle,&X.gcv); + if (feedback) select_correct_button(CLinestyle,linestyle); +} + +void +GC_change_capstyle(capstyle,feedback) + int capstyle; + Boolean feedback; +{ + X.gcv.cap_style = capstyle; + XChangeGC(X.dpy,X.gc,GCCapStyle,&X.gcv); + if (feedback) select_correct_button(CCapstyle,capstyle); +} + +void +GC_change_joinstyle(joinstyle,feedback) + int joinstyle; + Boolean feedback; +{ + X.gcv.join_style = joinstyle; + XChangeGC(X.dpy,X.gc,GCJoinStyle,&X.gcv); + if (feedback) select_correct_button(CJoinstyle,joinstyle); +} + +void +GC_change_fillstyle(fillstyle,feedback) + int fillstyle; + Boolean feedback; +{ + XSetFillStyle(X.dpy,X.gc,fillstyle); + X.gcv.fill_style = fillstyle; + if (feedback) select_correct_button(CFillstyle,fillstyle); +} + +void +GC_change_fillrule(fillrule,feedback) + int fillrule; + Boolean feedback; +{ + XSetFillRule(X.dpy,X.gc,fillrule); + X.gcv.fill_rule = fillrule; + if (feedback) select_correct_button(CFillrule,fillrule); +} + +void +GC_change_arcmode(arcmode,feedback) + int arcmode; + Boolean feedback; +{ + XSetArcMode(X.dpy,X.gc,arcmode); + X.gcv.arc_mode = arcmode; + if (feedback) select_correct_button(CArcmode,arcmode); +} + +/* GC_change_dashlist(dashlist) +** ---------------------------- +** Now this one's a bit tricky. dashlist gets passed in as an int, but we +** want to change it to an array of chars, like the GC likes it. +** For example: +** 119 => XXX_XXX_ => [3,1,3,1] +*/ + +void +GC_change_dashlist(dashlist,feedback) + int dashlist; + Boolean feedback; +{ + char dasharray[DASHLENGTH]; /* what we're gonna pass to XSetDashes */ + int dashnumber = 0; /* which element of dasharray we're currently + modifying */ + int i; /* which bit of the dashlist we're on */ + int state = 1; /* whether the list bit we checked was + on (1) or off (0) */ + + /* Initialize the dasharray */ + + for (i = 0; i < DASHLENGTH; ++i) dasharray[i] = 0; + + if (dashlist == 0) return; /* having no dashes at all is bogus */ + + /* XSetDashes expects the dashlist to start with an on bit, so if it + ** doesn't, we keep on rotating it until it does */ + + while (!(dashlist&1)) dashlist /= 2; + + /* Go through all the bits in dashlist, and update the dasharray + ** accordingly */ + + for (i = 0; i < DASHLENGTH; ++i) { + /* the following if statements checks to see if the bit we're looking + ** at as the same on or offness as the one before it (state). If + ** so, we increment the length of the current dash. */ + + if (((dashlist&1<<i) && state) || (!(dashlist&1<<i) && !state)) + ++dasharray[dashnumber]; + else { + state = state^1; /* reverse the state */ + ++dasharray[++dashnumber]; /* start a new dash */ + } + } + + XSetDashes(X.dpy,X.gc,0,dasharray,dashnumber+1); + X.gcv.dashes = dashlist; + + if (feedback) update_dashlist(dashlist); +} + +void +GC_change_planemask(planemask,feedback) + unsigned long planemask; + Boolean feedback; +{ + XSetPlaneMask(X.dpy,X.gc,planemask); + X.gcv.plane_mask = planemask; + if (feedback) update_planemask((long)planemask); +} + +void +change_test(test,feedback) + int test; + Boolean feedback; +{ + X.test = test; + if (feedback) select_button(testchoicedesc,test); +} + +void +GC_change_font(str,feedback) + const char *str; + Boolean feedback; +{ + int num_fonts; /* number of fonts that match the string */ + + XListFonts(X.dpy,str,1,&num_fonts); /* see if the font exists */ + + if (num_fonts) { + XSetFont(X.dpy,X.gc,XLoadFont(X.dpy,str)); + if (feedback) change_text(fonttext,str); + } +} + +void +change_percent(percent,feedback) + int percent; + Boolean feedback; +{ + /* Make sure that percent is valid */ + + if (percent < 1 || percent > 100) return; + + X.percent = (float) percent / 100.0; + + if (feedback) update_slider(percent); +} @@ -0,0 +1,169 @@ +/* $XConsortium: lex.l,v 1.8 94/03/31 20:40:44 rws Exp $ */ +/* $XFree86: xc/programs/xgc/lex.l,v 1.4 2002/05/31 18:46:13 dawes Exp $ */ +/* +** lex file for xgc syntax +*/ + +/* Lots of stuff stolen from gwm's wool.lex */ + +%{ + +#include <X11/X.h> +#include "gram.h" +#include "constants.h" +#if defined(FLEX_SCANNER) && !defined(YY_FLEX_LEX_COMPAT) && !defined(__UNIXOS2__) +int yylineno = 0; +#endif +%} + +%p 4000 +%a 3000 + +number [0-9]+ +word [^\n\t ]+ +string \"([^"]|\\.)*\" + +%% + +[Rr]un { return (RUN); } + +[Ff]unction { return (FUNCTION); } +[Cc]lear { yylval.num = GXclear; + return (FUNCTIONTYPE); } +[Aa]nd { yylval.num = GXand; + return (FUNCTIONTYPE); } +[Aa]ndReverse { yylval.num = GXandReverse; + return (FUNCTIONTYPE); } +[Cc]opy { yylval.num = GXcopy; + return (FUNCTIONTYPE); } +[Aa]ndInverted { yylval.num = GXandInverted; + return (FUNCTIONTYPE); } +[Nn]oop { yylval.num = GXnoop; + return (FUNCTIONTYPE); } +[Xx]or { yylval.num = GXxor; + return (FUNCTIONTYPE); } +[Oo]r { yylval.num = GXor; + return (FUNCTIONTYPE); } +[Nn]or { yylval.num = GXnor; + return (FUNCTIONTYPE); } +[Ee]quiv { yylval.num = GXequiv; + return (FUNCTIONTYPE); } +[Ii]nvert { yylval.num = GXinvert; + return (FUNCTIONTYPE); } +[Oo]rReverse { yylval.num = GXorReverse; + return (FUNCTIONTYPE); } +[Cc]opyInverted { yylval.num = GXcopyInverted; + return (FUNCTIONTYPE); } +[Oo]rInverted { yylval.num = GXorInverted; + return (FUNCTIONTYPE); } +[Nn]and { yylval.num = GXnand; + return (FUNCTIONTYPE); } +[Ss]et { yylval.num = GXset; + return (FUNCTIONTYPE); } + +[Tt]est { return (TEST); } +CopyArea { yylval.num = CopyArea; + return (TESTTYPE); } +CopyPlane { yylval.num = CopyPlane; + return (TESTTYPE); } +PolyPoint { yylval.num = PolyPoint; + return (TESTTYPE); } +PolyLine { yylval.num = PolyLine; + return (TESTTYPE); } +PolySegment { yylval.num = PolySegment; + return (TESTTYPE); } +PolyRectangle { yylval.num = PolyRectangle; + return (TESTTYPE); } +PolyArc { yylval.num = PolyArc; + return (TESTTYPE); } +FillPolygon { yylval.num = FillPolygon; + return (TESTTYPE); } +PolyFillRect { yylval.num = PolyFillRect; + return (TESTTYPE); } +PolyFillArc { yylval.num = PolyFillArc; + return (TESTTYPE); } +PutImage { yylval.num = PutImage; + return (TESTTYPE); } +GetImage { yylval.num = GetImage; + return (TESTTYPE); } +PolyText8 { yylval.num = PolyText8; + return (TESTTYPE); } +ImageText8 { yylval.num = ImageText8; + return (TESTTYPE); } +PolyText16 { yylval.num = PolyText16; + return (TESTTYPE); } +ImageText16 { yylval.num = ImageText16; + return (TESTTYPE); } + +[Ll]inestyle { return (LINESTYLE); } +OnOffDash { yylval.num = LineOnOffDash; + return (LINESTYLETYPE); } +DoubleDash { yylval.num = LineDoubleDash; + return (LINESTYLETYPE); } + +[Cc]apstyle { return (CAPSTYLE); } +NotLast { yylval.num = CapNotLast; + return (CAPSTYLETYPE); } +Butt { yylval.num = CapButt; + return (CAPSTYLETYPE); } +Projecting { yylval.num = CapProjecting; + return (CAPSTYLETYPE); } + +[Jj]oinstyle { return (JOINSTYLE); } +Miter { yylval.num = JoinMiter; + return (JOINSTYLETYPE); } +Bevel { yylval.num = JoinBevel; + return (JOINSTYLETYPE); } + +Round { return (ROUND); } + +[Ff]illstyle { return (FILLSTYLE); } +Tiled { yylval.num = FillTiled; + return (FILLSTYLETYPE); } +Stippled { yylval.num = FillStippled; + return (FILLSTYLETYPE); } +OpaqueStippled { yylval.num = FillOpaqueStippled; + return (FILLSTYLETYPE); } + +Solid { return (SOLID); } + +[Ff]illrule { return (FILLRULE); } +EvenOdd { yylval.num = EvenOddRule; + return (FILLRULETYPE); } +Winding { yylval.num = WindingRule; + return (FILLRULETYPE); } + +[Aa]rcmode { return (ARCMODE); } +Chord { yylval.num = ArcChord; + return (ARCMODETYPE); } +PieSlice { yylval.num = ArcPieSlice; + return (ARCMODETYPE); } + +[Ff]oreground { return (FOREGROUND); } +[Bb]ackground { return (BACKGROUND); } +[Ll]inewidth { return (LINEWIDTH); } +[Pp]lanemask { return (PLANEMASK); } +[Dd]ashlist { return (DASHLIST); } +[Ff]ont { return (FONT); } +[Pp]ercent { return (PERCENT); } + +{number} { (void) sscanf ((char *)yytext, "%d", &yylval.num); + return (NUMBER); } +{string} { yylval.ptr = (char *) yytext; + return (STRING); } +\#[^\n]*\n { ; } +[\t ] { ; } +\n { return ('\n'); } + +{word} { yylval.ptr = (char *) yytext; + return (STRING); } + +. { fprintf(stderr, + "xgc: bad character `%s', line %d\n", + yytext, yylineno); } + +%% + +#ifndef yywrap +int yywrap() { return (1); } +#endif @@ -0,0 +1,510 @@ +/* $XConsortium: main.c,v 1.22 94/04/17 20:45:30 rws Exp $ */ +/* + +Copyright (c) 1991 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from the X Consortium. + +*/ +/* $XFree86: xc/programs/xgc/main.c,v 1.5 2001/10/28 03:34:34 tsi Exp $ */ + +/* xgc +** +** main.c +** +** Contains the bare minimum necessary to oversee the whole operation. +*/ + +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Command.h> +#include <X11/Xaw/AsciiText.h> +#include <X11/Shell.h> +#include <stdio.h> +#include <stdlib.h> + +#include "xgc.h" +#define DEFINE_TILE +#include "tile" +#include "main.h" + +static void fill_up_commandform(); +extern void run_test(); +static void quit(); +static void quitAction(); +static void clear_test_window(); +static void clear_result_window(); +extern void start_playback(); +extern void read_from_keyboard(); +extern void toggle_recordbutton(); +static void set_foreground_and_background(); +extern ChoiceDesc *create_choice(); +extern void choose_defaults(); +extern void line_up_labels(); +extern Widget create_text_choice(); +extern void create_planemask_choice(); +extern void create_dashlist_choice(); +extern void create_testfrac_choice(); +extern void GC_change_foreground(); +extern void GC_change_background(); +extern void GC_change_font(); +extern void close_file_if_recording(); +extern void set_text (Widget ww, char *string); + +#ifdef notdef +int fildes[2]; /* for pipe */ +FILE *outend; +#endif + +XStuff X; /* GC stuff plus some global variables */ +Boolean recording = FALSE; /* Whether we're recording into a file */ +XtAppContext appcontext; /* To make Xt happy */ +static Atom wm_delete_window; +static XtActionsRec actions[] = { + {"quit", quitAction} +}; + +static Widget bigdaddy; /* the top level widget */ + Widget topform; /* form surrounding the whole thing */ + Widget GCform; /* form in which you choose the GC */ +static Widget Testform; /* form in which you choose the test */ + Widget testchoiceform; /* form inside that */ + ChoiceDesc *testchoicedesc; /* record of what widgets are in the + test choice form */ +static Widget commandform; /* form with run, quit, clear, etc. */ + Widget test; /* where the test is run */ + Widget result; /* where the results are displayed */ +static Widget runbutton; /* command for running */ +static Widget quitbutton; /* command for quitting */ +static Widget clearbutton; /* command for clearing the test window */ + Widget recordbutton; /* start/stop recording */ +static Widget playbackbutton; /* playback from file */ +static Widget keyinputbutton; /* start reading from keyboard */ +static Widget GCchoices[NUMCHOICES]; /* all the forms that contain stuff + for changing GC's*/ + ChoiceDesc *GCdescs[NUMCHOICES]; /* record of the widgets inside + the choice widgets */ + Widget planemaskchoice; /* form for choosing the plane mask */ + Widget dashlistchoice; /* form for choosing the dash list */ +static Widget linewidthchoice; /* form for choosing line width */ + Widget linewidthtext; /* text widget within that */ +static Widget fontchoice; /* form for choosing the font */ + Widget fonttext; /* text widget within that */ +static Widget foregroundchoice; /* form for choosing foreground */ + Widget foregroundtext; /* text widget within that */ +static Widget backgroundchoice; /* form for choosing background */ + Widget backgroundtext; /* text widget within that */ +static Widget percentchoice; /* form for choosing percentage of test */ + +/* main(argc.argv) +** --------------- +** Initializes the toolkit, initializes data, puts up the widgets, +** starts the event loop. +*/ + +int +main(argc,argv) + int argc; + char **argv; +{ + static Arg shellargs[] = { + {XtNinput, (XtArgVal) True} + }; + + static Arg testformargs[] = { + {XtNfromVert, (XtArgVal) NULL} /* put it under GCform */ + }; + + static Arg commandformargs[] = { + {XtNfromVert, (XtArgVal) NULL}, /* put it under GCform */ + {XtNfromHoriz, (XtArgVal) NULL} /* and to the right of Testform */ + }; + + static Arg testargs[] = { + {XtNheight, (XtArgVal) 400}, + {XtNwidth, (XtArgVal) 400}, + {XtNfromHoriz, (XtArgVal) NULL} /* put it to the right of GCform */ + }; + + static Arg resultargs[] = { + {XtNheight, (XtArgVal) 50}, + {XtNwidth, (XtArgVal) 400}, + {XtNfromHoriz, (XtArgVal) NULL}, /* put it to the right of GCform */ + {XtNfromVert, (XtArgVal) NULL} /* and under test */ + }; + + static Arg gcchoiceargs[] = { + {XtNfromVert, (XtArgVal) NULL}, /* put it under the one above it */ + {XtNfromHoriz, (XtArgVal) NULL}, /* and next to that one */ + {XtNborderWidth, (XtArgVal) 0} /* no ugly borders */ + }; + + static Arg testchoiceargs[] = { + {XtNborderWidth, (XtArgVal) 0} + }; + + int i; /* counter */ + + /* Open the pipe */ + +#ifdef notdef + pipe(fildes); + outend = fdopen(fildes[0],"r"); +#endif + + /* Initialize toolkit stuff */ + + XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL); + + bigdaddy = XtAppInitialize(&appcontext, "Xgc", (XrmOptionDescList) NULL, + (Cardinal) 0, &argc, argv, (String *) NULL, + shellargs, XtNumber(shellargs)); + X.dpy = XtDisplay(bigdaddy); + XtAppAddActions(appcontext, actions, XtNumber(actions)); + XtOverrideTranslations + (bigdaddy, XtParseTranslationTable("<Message>WM_PROTOCOLS: quit()")); + + /* Initialize GC stuff */ + + X.scr = DefaultScreenOfDisplay(X.dpy); + X.gc = XCreateGC(X.dpy,RootWindowOfScreen(X.scr),0,(XGCValues *) NULL); + X.miscgc = XCreateGC(X.dpy,RootWindowOfScreen(X.scr),0,(XGCValues *) NULL); + + /* Find out what the foreground & background are, and update the GC + ** accordingly */ + + set_foreground_and_background(); + + topform = XtCreateManagedWidget("topform",formWidgetClass,bigdaddy, + NULL,0); + + GCform = XtCreateManagedWidget("GCform",formWidgetClass,topform, + NULL,0); + + /* create all the GCchoices forms */ + + for (i=0;i<NUMCHOICES;++i) { + if (i==0) /* on top */ + gcchoiceargs[0].value = (XtArgVal) NULL; + else /* under the last one */ + gcchoiceargs[0].value = (XtArgVal) GCchoices[i-1]; + + GCchoices[i] = XtCreateManagedWidget(Everything[i]->choice.text, + formWidgetClass,GCform, + gcchoiceargs,XtNumber(gcchoiceargs)); + + /* now fill up that form */ + GCdescs[i] = create_choice(GCchoices[i],Everything[i]); + } + + /* put the planemask choice under the bottom GC choice */ + gcchoiceargs[0].value = (XtArgVal) GCchoices[NUMCHOICES-1]; + planemaskchoice = XtCreateManagedWidget("planemask",formWidgetClass,GCform, + gcchoiceargs,XtNumber(gcchoiceargs)); + /* fill it up */ + create_planemask_choice(planemaskchoice); + + /* put the dashlist choice under the planemask choice */ + gcchoiceargs[0].value = (XtArgVal) planemaskchoice; + dashlistchoice = XtCreateManagedWidget("dashlist",formWidgetClass,GCform, + gcchoiceargs,XtNumber(gcchoiceargs)); + /* fill it up */ + create_dashlist_choice(dashlistchoice); + + /* put the linewidth choice under the dashlist choice */ + gcchoiceargs[0].value = (XtArgVal) dashlistchoice; + linewidthchoice = XtCreateManagedWidget("linewidth",formWidgetClass,GCform, + gcchoiceargs,XtNumber(gcchoiceargs)); + /* fill it up */ + linewidthtext = create_text_choice(linewidthchoice,TLineWidth,2,30); + + /* put the font choice under the linewidth choice */ + gcchoiceargs[0].value = (XtArgVal) linewidthchoice; + fontchoice = XtCreateManagedWidget("font",formWidgetClass,GCform, + gcchoiceargs,XtNumber(gcchoiceargs)); + /* fill it up */ + fonttext = create_text_choice(fontchoice,TFont,80,300); + + gcchoiceargs[0].value = (XtArgVal) fontchoice; + foregroundchoice = XtCreateManagedWidget("foreground",formWidgetClass,GCform, + gcchoiceargs,XtNumber(gcchoiceargs)); + foregroundtext = create_text_choice(foregroundchoice,TForeground,4,50); + + gcchoiceargs[1].value = (XtArgVal) foregroundchoice; + backgroundchoice = XtCreateManagedWidget("background",formWidgetClass,GCform, + gcchoiceargs,XtNumber(gcchoiceargs)); + backgroundtext = create_text_choice(backgroundchoice,TBackground,4,50); + + gcchoiceargs[1].value = (XtArgVal) NULL; + gcchoiceargs[0].value = (XtArgVal) foregroundchoice; + percentchoice = XtCreateManagedWidget("testpercent",formWidgetClass,GCform, + gcchoiceargs,XtNumber(gcchoiceargs)); + X.percent = 1.0; + create_testfrac_choice(percentchoice); + + /* make all the labels inside the choices line up nicely */ + line_up_labels(GCdescs,(int) XtNumber(GCdescs)); + + /* put the test form under the GC form */ + testformargs[0].value = (XtArgVal) GCform; + Testform = XtCreateManagedWidget("Testform",formWidgetClass,topform, + testformargs,XtNumber(testformargs)); + + testchoiceform = XtCreateManagedWidget("testchoiceform",formWidgetClass, + Testform,testchoiceargs,XtNumber(testchoiceargs)); + testchoicedesc = create_choice(testchoiceform,Everything[CTest]); + + commandformargs[0].value = (XtArgVal) GCform; + commandformargs[1].value = (XtArgVal) Testform; + commandform = XtCreateManagedWidget("commandform",formWidgetClass,topform, + commandformargs,XtNumber(commandformargs)); + + /* Put the appropriate command buttons in the command form */ + + fill_up_commandform(commandform); + + testargs[2].value = (XtArgVal) GCform; /* to the right of */ + test = XtCreateManagedWidget("test",widgetClass,topform, + testargs,XtNumber(testargs)); + + resultargs[2].value = (XtArgVal) GCform; /* to the right of */ + resultargs[3].value = (XtArgVal) test; /* under */ + result = XtCreateManagedWidget("result",asciiTextWidgetClass,topform, + resultargs,XtNumber(resultargs)); + + /* Now realize all the widgets */ + + XtRealizeWidget(bigdaddy); + + /* Now do things we couldn't do until we had a window available */ + + X.win = XtWindow(test); + X.tile = XCreatePixmap(X.dpy,X.win,tile_width,tile_height, + DefaultDepthOfScreen(X.scr)); + + X.tile = XCreatePixmapFromBitmapData(X.dpy,X.win, + (char *)tile_bits,tile_width, + tile_height,Black,White, + DefaultDepthOfScreen(X.scr)); + X.stipple = XCreateBitmapFromData(X.dpy,X.win,(char *)tile_bits,tile_width, + tile_height); + + XSetStipple(X.dpy,X.gc,X.stipple); + XSetStipple(X.dpy,X.miscgc,X.stipple); + + GC_change_foreground(X.foreground,TRUE); + GC_change_background(X.background,TRUE); + + wm_delete_window = XInternAtom(X.dpy, "WM_DELETE_WINDOW", False); + (void) XSetWMProtocols(X.dpy, XtWindow(bigdaddy), &wm_delete_window, 1); + + /* Act like the user picked the first choice in each group */ + + choose_defaults(GCdescs,(int)XtNumber(GCdescs)); + choose_defaults(&testchoicedesc,1); + + /* Loop forever, dealing with events */ + + XtAppMainLoop(appcontext); + + return 0; +} + +/* fill_up_commandform(w) +** ---------------------- +** Put the appropriate command buttons in the command form (w). +*/ + +static void +fill_up_commandform(w) + Widget w; +{ + static XtCallbackRec runcallbacklist[] = { + {(XtCallbackProc) run_test, NULL}, + {NULL, NULL} + }; + + static XtCallbackRec quitcallbacklist[] = { + {(XtCallbackProc) quit, NULL}, + {NULL, NULL} + }; + + static XtCallbackRec clearcallbacklist[] = { + {(XtCallbackProc) clear_test_window, NULL}, + {(XtCallbackProc) clear_result_window, NULL}, + {NULL, NULL} + }; + + static XtCallbackRec playbackcallbacklist[] = { + {(XtCallbackProc) start_playback, NULL}, + {NULL, NULL} + }; + + static XtCallbackRec keyinputcallbacklist[] = { + {(XtCallbackProc) read_from_keyboard, NULL}, + {NULL, NULL} + }; + + static XtCallbackRec recordcallbacklist[] = { + {(XtCallbackProc) toggle_recordbutton, NULL}, + {NULL, NULL} + }; + + static Arg runargs[] = { + {XtNcallback, (XtArgVal) NULL} + }; + + static Arg clearargs[] = { + {XtNcallback, (XtArgVal) NULL}, + {XtNfromVert, (XtArgVal) NULL}, /* put it under runbutton */ + {XtNvertDistance,(XtArgVal) 10} + }; + + static Arg recordargs[] = { + {XtNcallback, (XtArgVal) NULL}, + {XtNfromVert, (XtArgVal) NULL}, /* put it under clearbutton */ + {XtNvertDistance,(XtArgVal) 10}, + {XtNresizable, (XtArgVal) True} /* so we can change the name */ + }; + + static Arg playbackargs[] = { + {XtNcallback, (XtArgVal) NULL}, + {XtNfromVert, (XtArgVal) NULL} /* put it under recordbutton */ + }; + + static Arg keyinputargs[] = { + {XtNcallback, (XtArgVal) NULL}, + {XtNfromVert, (XtArgVal) NULL} /* put it under playbackbutton */ + }; + + static Arg quitargs[] = { + {XtNcallback, (XtArgVal) NULL}, + {XtNfromVert, (XtArgVal) NULL}, /* put it under keyinputbutton */ + {XtNvertDistance,(XtArgVal) 10} + }; + + runargs[0].value = (XtArgVal) runcallbacklist; + runbutton = XtCreateManagedWidget("Run",commandWidgetClass, + w,runargs,XtNumber(runargs)); + + clearargs[0].value = (XtArgVal) clearcallbacklist; + clearargs[1].value = (XtArgVal) runbutton; /* under */ + clearbutton = XtCreateManagedWidget("Clear window",commandWidgetClass, + w,clearargs,XtNumber(clearargs)); + + recordargs[0].value = (XtArgVal) recordcallbacklist; + recordargs[1].value = (XtArgVal) clearbutton; /* under */ + recordbutton = XtCreateManagedWidget("Record",commandWidgetClass, + w,recordargs,XtNumber(recordargs)); + + playbackargs[0].value = (XtArgVal) playbackcallbacklist; + playbackargs[1].value = (XtArgVal) recordbutton; /* under */ + playbackbutton = XtCreateManagedWidget("Playback",commandWidgetClass, + w,playbackargs,XtNumber(playbackargs)); + + keyinputargs[0].value = (XtArgVal) keyinputcallbacklist; + keyinputargs[1].value = (XtArgVal) playbackbutton; + keyinputbutton = XtCreateManagedWidget("Read Input",commandWidgetClass, + w,keyinputargs,XtNumber(keyinputargs)); + + quitargs[0].value = (XtArgVal) quitcallbacklist; + quitargs[1].value = (XtArgVal) keyinputbutton; /* under */ + quitbutton = XtCreateManagedWidget("Quit",commandWidgetClass, + w,quitargs,XtNumber(quitargs)); + +} +/* quit() +** ------ +** Leave the program nicely. +*/ + +static void +quit() +{ + close_file_if_recording(); + exit(0); +} + +static void quitAction(w, e, p, n) + Widget w; + XEvent *e; + String *p; + Cardinal *n; +{ + if (e->type == ClientMessage && e->xclient.data.l[0] != wm_delete_window) + XBell(XtDisplay(w), 0); + else + quit(); +} + +/* clear_test_window() +** ------------------- +** Clear the test window. +*/ + +static void +clear_test_window() +{ + XClearWindow(X.dpy,XtWindow(test)); +} + +/* clear_result_window() +** --------------------- +** Clear the result window. +*/ + +static void +clear_result_window() +{ + set_text(result, ""); +} + +/* set_foreground_and_background() +** ------------------------------- +** Finds the user-specified foreground and background by querying +** the resource manager, and sets state accordingly. Also specifies +** the initial font for text tests. +*/ + +static void +set_foreground_and_background() +{ + static XtResource resources[] = { + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XStuff, foreground), XtRString, XtDefaultForeground}, + {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), + XtOffsetOf(XStuff, background), XtRString, XtDefaultBackground} + }; + + XtGetApplicationResources(bigdaddy, (XtPointer) &X, resources, + XtNumber(resources), NULL, (Cardinal) 0); + + X.gcv.foreground = X.foreground; + X.gcv.background = X.background; + + X.fontname = "6x10"; + GC_change_font(X.fontname,FALSE); +} @@ -0,0 +1,148 @@ +/* +** xgc +** +** xgc.h +** +** Initialization of structures, etc. +*/ +/* $XFree86: xc/programs/xgc/main.h,v 1.3 2000/02/17 14:00:36 dawes Exp $ */ + +/* The three columns in the XgcData arrays are: +** name: the name of the toggle button +** text: the corresponding text in the xgc syntax +** code: the integer that the text corresponds to, for sending stuff +** to X calls, etc. +*/ + +XgcData FunctionData[NUM_FUNCTIONS] = { + {"clear", "clear", GXclear}, + {"and", "and", GXand}, + {"andReverse", "andReverse", GXandReverse}, + {"copy", "copy", GXcopy}, + {"andInverted", "andInverted", GXandInverted}, + {"noop", "noop", GXnoop}, + {"xor", "xor", GXxor}, + {"or", "or", GXor}, + {"nor", "nor", GXnor}, + {"equiv", "equiv", GXequiv}, + {"invert", "invert", GXinvert}, + {"orReverse", "orReverse", GXorReverse}, + {"copyInverted", "copyInverted", GXcopyInverted}, + {"orInverted", "orInverted", GXorInverted}, + {"nand", "nand", GXnand}, + {"set", "set", GXset} +}; + +/* The two rows in the XgcStuff structure are: +** name of label, xgc syntax text, # of toggles, # of columns of toggles +** (0 columns means 1 row, as many columns as necessary) +** appropriate XgcData +*/ + +XgcStuff FunctionStuff = { + {"Function","function",NUM_FUNCTIONS,4}, + FunctionData +}; + +XgcData TestData[NUM_TESTS] = { + {"Copy Area", "CopyArea", CopyArea}, + {"Copy Plane", "CopyPlane", CopyPlane}, + {"Points", "PolyPoint", PolyPoint}, + {"Lines", "PolyLine", PolyLine}, + {"Segments", "PolySegment", PolySegment}, + {"Rectangles", "PolyRectangle", PolyRectangle}, + {"Arcs", "PolyArc", PolyArc}, + {"(Filled Polygons)", "FillPolygon", FillPolygon}, + {"Filled Rectangles", "PolyFillRect", PolyFillRect}, + {"Filled Arcs", "PolyFillArc", PolyFillArc}, + {"Put Image", "PutImage", PutImage}, + {"(Get Image)", "GetImage", GetImage}, + {"Text 8", "PolyText8", PolyText8}, + {"Image Text 8", "ImageText8", ImageText8}, + {"Text 16", "PolyText16", PolyText16}, + {"Image Text 16", "ImageText16", ImageText16} +}; + +XgcStuff TestStuff = { + {"Test","test",NUM_TESTS,2}, + TestData +}; + +XgcData LinestyleData[NUM_LINESTYLES] = { + {"Solid", "Solid", LineSolid}, + {"OnOffDash", "OnOffDash", LineOnOffDash}, + {"DoubleDash", "DoubleDash", LineDoubleDash} +}; + +XgcStuff LinestyleStuff = { + {"LineStyle","linestyle",NUM_LINESTYLES,0}, + LinestyleData +}; + +XgcData CapstyleData[NUM_CAPSTYLES] = { + {"NotLast", "NotLast", CapNotLast}, + {"Butt", "Butt", CapButt}, + {"Round", "Round", CapRound}, + {"Projecting", "Projecting", CapProjecting} +}; + +XgcStuff CapstyleStuff = { + {"CapStyle","capstyle",NUM_CAPSTYLES,2}, + CapstyleData +}; + +XgcData JoinstyleData[NUM_JOINSTYLES] = { + {"Miter", "Miter", JoinMiter}, + {"Round", "Round", JoinRound}, + {"Bevel", "Bevel", JoinBevel} +}; + +XgcStuff JoinstyleStuff = { + {"JoinStyle","joinstyle",NUM_JOINSTYLES,0}, + JoinstyleData +}; + +XgcData FillstyleData[NUM_FILLSTYLES] = { + {"Solid", "Solid", FillSolid}, + {"Tiled", "Tiled", FillTiled}, + {"Stippled", "Stippled", FillStippled}, + {"OpaqueStippled", "OpaqueStippled", FillOpaqueStippled} +}; + +XgcStuff FillstyleStuff = { + {"FillStyle","fillstyle",NUM_FILLSTYLES,2}, + FillstyleData +}; + +XgcData FillruleData[NUM_FILLRULES] = { + {"EvenOdd", "EvenOdd", EvenOddRule}, + {"Winding", "Winding", WindingRule} +}; + +XgcStuff FillruleStuff = { + {"FillRule","fillrule",NUM_FILLRULES,0}, + FillruleData +}; + +XgcData ArcmodeData[NUM_ARCMODES] = { + {"Chord", "Chord", ArcChord}, + {"PieSlice", "PieSlice", ArcPieSlice} +}; + +XgcStuff ArcmodeStuff = { + {"ArcMode","arcmode",NUM_ARCMODES,0}, + ArcmodeData +}; + +/* Pointers to all the Xgcstuffs so we can run them through a loop */ + +static XgcStuff *Everything[8] = { + &FunctionStuff, + &LinestyleStuff, + &CapstyleStuff, + &JoinstyleStuff, + &FillstyleStuff, + &FillruleStuff, + &ArcmodeStuff, + &TestStuff +}; diff --git a/planemask.c b/planemask.c new file mode 100644 index 0000000..e904aa3 --- /dev/null +++ b/planemask.c @@ -0,0 +1,198 @@ +/* +** planemask.c +** +** How to make a widget to choose a planemask. +** +** NOTE: This file uses static variables. Therefore, trying to use these +** functions to create more than one of these planemask choice things +** will fail in a big way. +*/ +/* $XFree86: xc/programs/xgc/planemask.c,v 1.3 2000/02/17 14:00:37 dawes Exp $ */ + +#include <X11/Xos.h> +#include <stdio.h> +#include <stdlib.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/Toggle.h> +#include "xgc.h" + +static void choose_plane( +#if NeedFunctionPrototypes + Widget, caddr_t, caddr_t +#endif +); +extern void interpret(); + +extern XStuff X; + +static unsigned long planemask; +static Widget *pm; + +/* create_planemask_choice(w) +** ------------------------- +** Inside w (a form widget), creates a bunch of little toggle buttons +** in a row, representing the planemask. There's also a label so +** the user knows what it is. +*/ + +void +create_planemask_choice(w) + Widget w; +{ + /* callback list for the toggle widgets */ + static XtCallbackRec callbacklist[] = { + {(XtCallbackProc) choose_plane, NULL}, + {NULL, NULL} + }; + + /* ArgList for the label */ + static Arg labelargs[] = { + {XtNborderWidth, (XtArgVal) 0}, + {XtNjustify, (XtArgVal) XtJustifyRight}, + {XtNvertDistance, (XtArgVal) 4} + }; + + /* ArgList for the toggles */ + static Arg pmargs[] = { + {XtNcallback, (XtArgVal) NULL}, + {XtNhorizDistance, (XtArgVal) NULL}, + {XtNfromHoriz, (XtArgVal) NULL}, + {XtNwidth, (XtArgVal) 10}, + {XtNheight, (XtArgVal) 10}, + {XtNhighlightThickness,(XtArgVal) 1}, + {XtNstate, (XtArgVal) True}, + {XtNlabel, (XtArgVal) ""} + }; + + static Widget label; /* the label, of course */ + static int *pminfo; /* contains integers saying which bit + a particular button is; sent to + choose_plane to tell it which + bit got changed */ + + int i, num_planes; + + char buf[40]; + char name[12]; + + num_planes = PlanesOfScreen(X.scr); + + planemask = (1<<num_planes)-1; + sprintf(buf,"planemask %lu",planemask); + interpret(buf); + + /* Allocate space for stuff that we don't know the size of yet */ + + pm = (Widget *) malloc(num_planes * sizeof(Widget)); + pminfo = (int *) malloc(num_planes * sizeof(int)); + + /* Make the label widget */ + + label = XtCreateManagedWidget("planemask",labelWidgetClass,w, + labelargs,XtNumber(labelargs)); + + pmargs[0].value = (XtArgVal) callbacklist; + + for (i=0;i<num_planes;++i) { /* go through all the buttons */ + if (i==0) { /* offset the first one from the label */ + pmargs[1].value = (XtArgVal) 10; + pmargs[2].value = (XtArgVal) label; + } + else { /* put it directly to the right of the + last one, no space in between */ + pmargs[1].value = (XtArgVal) -1; + pmargs[2].value = (XtArgVal) pm[i-1]; + } + + /* set its original state depending on the state of that bit + ** of the planemask */ + + if (planemask & 1<<i) + pmargs[6].value = (XtArgVal) True; + else + pmargs[6].value = (XtArgVal) False; + + sprintf(name,"planemask%d",i); + + pminfo[i] = i; /* which bit we're on; this is needed in + choose_plane (the callback) */ + callbacklist[0].closure = (caddr_t) &pminfo[i]; + + pm[i] = XtCreateManagedWidget(name,toggleWidgetClass,w, + pmargs,XtNumber(pmargs)); + } +} + +/* choose_plane(w,closure,call_data) +** ------------------------------------ +** This function is called when the user toggles a toggle widget. It +** makes the appropriate change to the planemask and sends it off +** to interpret(). +** Funny args are because it's a callback. +*/ + +/*ARGSUSED*/ +static void +choose_plane(w,closure,call_data) + Widget w; + caddr_t closure; + caddr_t call_data; +{ + int num; /* what number button it is */ + Boolean on; /* is it currently on or off? */ + + char buf[80]; /* string to send to interpret() */ + + static Arg args[] = { + {XtNstate, (XtArgVal) NULL} + }; + + /* set up ArgList so that 'on' will contain the state */ + args[0].value = (XtArgVal) &on; + + num = * (int *) closure; /* we put it here back in the last function */ + XtGetValues(w,args,XtNumber(args)); + + /* Modify the planemask appropriately */ + + if (on) + planemask |= 1<<num; + else + planemask &= ~(1<<num); + + (void) sprintf(buf,"planemask %lu\n",planemask); + interpret(buf); +} + +/* update_planemask(mask) +** ---------------------- +** Updates the display of the planemask so that it corresponds to mask. +*/ + +void +update_planemask(mask) + long mask; +{ + int i; /* counter */ + static Arg maskargs[] = { /* ArgList for setting toggle state */ + {XtNstate, (XtArgVal) NULL} + }; + + /* First set the internal representation */ + + planemask = mask; + + for (i = 0; i < PlanesOfScreen(X.scr); ++i) { + if (planemask & 1<<i) { /* if it's set, make it look that way */ + maskargs[0].value = (XtArgVal) True; + } + else { + maskargs[0].value = (XtArgVal) False; + } + + XtSetValues(pm[i],maskargs,XtNumber(maskargs)); + } +} diff --git a/record.c b/record.c new file mode 100644 index 0000000..3884790 --- /dev/null +++ b/record.c @@ -0,0 +1,299 @@ +/* +** xgc +** +** record.c +*/ +/* $XFree86: xc/programs/xgc/record.c,v 1.3 2000/02/17 14:00:37 dawes Exp $ */ + +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/Command.h> +#include <X11/Xaw/Form.h> +#include <X11/Shell.h> +#include <X11/Xaw/AsciiText.h> +#include <stdio.h> + +#include "xgc.h" + +static void start_recording(); +static void stop_recording(); +static void print_out_gc_values(); +static void chose_playback_filename(); +static void cancel_playback(); +extern void get_filename(); +extern void yyparse(); + +extern XgcStuff TestStuff; +extern XgcStuff FunctionStuff; +extern XgcStuff LinestyleStuff; +extern XgcStuff CapstyleStuff; +extern XgcStuff JoinstyleStuff; +extern XgcStuff FillstyleStuff; +extern XgcStuff FillruleStuff; +extern XgcStuff ArcmodeStuff; + +extern XStuff X; +extern Boolean recording; +extern Widget filename_text_widget, recordbutton; + +static void cancel_record(); +static void done_choosing_filename(); + +FILE *recordfile; /* the file we're recording to */ +FILE *playbackfile; /* the file we're playing back from */ +extern FILE *yyin; /* for yyparse */ + +/* toggle_recordbutton(w,closure,call_data) +** ---------------------------------------- +** This function is called when the user presses the "Record" +** command button. If we're not recording, we start; if we are, +** we stop. Also change the label to reflect the change in the +** function of the button. +*/ + +/*ARGSUSED*/ +void +toggle_recordbutton(w,closure,call_data) + Widget w; + caddr_t closure; + caddr_t call_data; +{ + /* ArgList for changing the label */ + static Arg recordargs[] = { + {XtNlabel, (XtArgVal) NULL} + }; + + char tmp[20]; /* new label */ + + if (!recording) { + start_recording(); + } + else { + recording = FALSE; + stop_recording(); + sprintf(tmp,"Record"); + recordargs[0].value = (XtArgVal) tmp; + } + + XtSetValues(recordbutton,recordargs,XtNumber(recordargs)); +} + +/* start_recording() +** ----------------- +** Get the name of the file the user wants to record into, and +** start recording into it if he doesn't cancel. +*/ + +static void +start_recording() +{ + get_filename(done_choosing_filename,cancel_record); +} + +/* stop_recording() +** ---------------- +** Close the output file. +*/ + +static void +stop_recording() +{ + fclose(recordfile); +} + +/* cancel_record() +** --------------- +** What to do if the if the user canceled recording, i.e. nothing. +*/ + +static void +cancel_record() +{ +} + +/* done_choosing_filename() +** ------------------------ +** What to do after the user's chosen a file. Change the label on the +** command button, open the file, and dump the current contents of the +** GC into it. +*/ + +static void +done_choosing_filename() +{ + static Arg recordargs[] = { + {XtNlabel, (XtArgVal) NULL}, + {XtNresize, (XtArgVal) True} + }; + Arg args[1]; + char tmp[20], *filename; + + XtSetArg(args[0], XtNstring, &filename); + XtGetValues(filename_text_widget, args, (Cardinal) 1); + + if ((recordfile = fopen(filename,"w")) != NULL) { + recording = TRUE; + sprintf(tmp,"End Record"); + recordargs[0].value = (XtArgVal) tmp; + XtSetValues(recordbutton,recordargs,XtNumber(recordargs)); + + print_out_gc_values(); + } +} + +/* print_if_recording(str) +** ----------------------- +** If we're recording to a file, put str in it. +*/ + +void +print_if_recording(str) + char *str; +{ + if (recording) + fprintf(recordfile,"%s",str); +} + +/* close_file_if_recording() +** ------------------------- +** If we're recording, stop. +*/ + +void +close_file_if_recording() +{ + if (recording) + fclose(recordfile); +} + +/* print_out_gc_values() +** --------------------- +** Dump the contents of the GC to the file, so that when the file gets +** played back, it will be correctly initialized. +*/ + +static void +print_out_gc_values() +{ + int i; + for (i=0;i<NUM_TESTS;++i) { + if ((TestStuff.data)[i].code == X.test) { + fprintf(recordfile,"%s %s\n", + TestStuff.choice.text,(TestStuff.data)[i].text); + break; + } + } + for (i=0;i<NUM_FUNCTIONS;++i) { + if ((FunctionStuff.data)[i].code == X.gcv.function) { + fprintf(recordfile,"%s %s\n", + FunctionStuff.choice.text,(FunctionStuff.data)[i].text); + break; + } + } + for (i=0;i<NUM_LINESTYLES;++i) { + if ((LinestyleStuff.data)[i].code == X.gcv.line_style) { + fprintf(recordfile,"%s %s\n", + LinestyleStuff.choice.text,(LinestyleStuff.data)[i].text); + break; + } + } + for (i=0;i<NUM_CAPSTYLES;++i) { + if ((CapstyleStuff.data)[i].code == X.gcv.cap_style) { + fprintf(recordfile,"%s %s\n", + CapstyleStuff.choice.text,(CapstyleStuff.data)[i].text); + break; + } + } + for (i=0;i<NUM_JOINSTYLES;++i) { + if ((JoinstyleStuff.data)[i].code == X.gcv.join_style) { + fprintf(recordfile,"%s %s\n", + JoinstyleStuff.choice.text,(JoinstyleStuff.data)[i].text); + break; + } + } + for (i=0;i<NUM_FILLSTYLES;++i) { + if ((FillstyleStuff.data)[i].code == X.gcv.fill_style) { + fprintf(recordfile,"%s %s\n", + FillstyleStuff.choice.text,(FillstyleStuff.data)[i].text); + break; + } + } + for (i=0;i<NUM_FILLRULES;++i) { + if ((FillruleStuff.data)[i].code == X.gcv.fill_rule) { + fprintf(recordfile,"%s %s\n", + FillruleStuff.choice.text,(FillruleStuff.data)[i].text); + break; + } + } + for (i=0;i<NUM_ARCMODES;++i) { + if ((ArcmodeStuff.data)[i].code == X.gcv.arc_mode) { + fprintf(recordfile,"%s %s\n", + ArcmodeStuff.choice.text,(ArcmodeStuff.data)[i].text); + break; + } + } + fprintf(recordfile,"linewidth %d\n",X.gcv.line_width); + fprintf(recordfile,"foreground %ld\n",X.gcv.foreground); + fprintf(recordfile,"background %ld\n",X.gcv.background); + fprintf(recordfile,"planemask %ld\n",X.gcv.plane_mask); + fprintf(recordfile,"dashlist %d\n",X.gcv.dashes); + fprintf(recordfile,"font %s\n",X.fontname); +} + +/********************************************/ + +/* start_playback() +** ---------------- +** This gets called if the user wants to playback from a file. +** Get the file name and do the appropriate thing. +*/ + +void +start_playback() +{ + get_filename(chose_playback_filename,cancel_playback); +} + +/* cancel_playback() +** ----------------- +** What to do if the user canceled the playback request. +*/ + +static void +cancel_playback() +{ +} + +/* chose_playback_filename() +** ------------------------- +** What to do once the user's selected a filename to playback. +** Play it back. +*/ + +static void +chose_playback_filename() +{ + Arg args[1]; + char *filename; + + XtSetArg(args[0], XtNstring, &filename); + XtGetValues(filename_text_widget, args, (Cardinal) 1); + + if ((playbackfile = fopen(filename,"r")) != NULL) { + yyin = playbackfile; + yyparse(); + } +} + +/* read_from_keyboard() +** -------------------- +** Do a playback from the keyboard. +*/ + +void +read_from_keyboard() +{ + yyin = stdin; + yyparse(); +} diff --git a/testfrac.c b/testfrac.c new file mode 100644 index 0000000..56ba951 --- /dev/null +++ b/testfrac.c @@ -0,0 +1,205 @@ +/* +** testfrac.c +** +** How to make a widget to choose the fraction of tests to be run. +** +*/ +/* $XFree86: xc/programs/xgc/testfrac.c,v 1.3 2000/02/17 14:00:37 dawes Exp $ */ + +#include <stdio.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/Scrollbar.h> +#include "xgc.h" + +extern void interpret(); + +extern XtAppContext appcontext; + +#define SCROLLBAR_LENGTH 125 +#define SLIDER_LENGTH 0.2 /* proportion of scrollbar taken up + by the slider */ + +static Widget label; /* the label */ +static Widget slider; /* the scrollbar */ +static Widget percent; /* label with chosen percentage */ + +static float fraction; /* what percent has been chosen */ +static int oldpercent = -1; /* so we only update when the slider has + been moved */ + +/* slider_jump(w,data,position) +** ---------------------------- +** This function is called if the user moves the scrollbar to a new +** position (generally, by using the middle button). It updates +** information about where the scrollbar is. +*/ + +/*ARGSUSED*/ +static void +slider_jump(w, data, position) + Widget w; + caddr_t data; + caddr_t position; +{ + static Arg percentargs[] = { + {XtNlabel, (XtArgVal) NULL} + }; + + float oldpercent; /* where the scrollbar is */ + float newpercent; /* normalized scrollbar */ + char snewpercent[3]; /* string representation of scrollbar */ + + oldpercent = *(float *) position; + + /* We want the scrollbar to be at 100% when the right edge of the slider + ** hits the end of the scrollbar, not the left edge. When the right edge + ** is at 1.0, the left edge is at 1.0 - SLIDER_LENGTH. Normalize + ** accordingly. */ + + newpercent = oldpercent / (1.0 - SLIDER_LENGTH); + + /* If the slider's partially out of the scrollbar, move it back in. */ + + if (newpercent > 1.0) { + newpercent = 1.0; + XawScrollbarSetThumb( slider, 1.0 - SLIDER_LENGTH, SLIDER_LENGTH); + } + + /* Store the position of the silder where it can be found */ + + *(float *)data = newpercent; + + /* Update the label widget */ + + sprintf(snewpercent,"%d",(int)(newpercent*100)); + percentargs[0].value = (XtArgVal) snewpercent; + XtSetValues(percent, percentargs, XtNumber(percentargs)); +} + +/* slider_scroll(w,data,position) +** ------------------------------ +** This function is called when the user does incremental scrolling, +** generally with the left or right button. Right now it just ignores it. +*/ + +/*ARGSUSED*/ +static void +slider_scroll(w, data, position) + Widget w; + caddr_t data; + caddr_t position; +{} + +/*ARGSUSED*/ +static void +update(w,event,params,num_params) + Widget w; + XEvent *event; + String *params; + int *num_params; +{ + char buf[80]; + int newpercent; + + newpercent = (int)(fraction * 100.0); + if (newpercent != oldpercent) { + sprintf(buf, "percent %d\n", (int)(fraction * 100.0)); + interpret(buf); + oldpercent = newpercent; + } +} + +/* create_testfrac_choice(w) +** ------------------------- +** Inside w (a form widget), creates: +** 1. A label "Percentage of Test" +** 2. A scrollbar for the user to choose the percentage (from 0 to 100) +** 3. A label with the current percentage displayed on it. +** The percentage starts at 100. +** +** When the pointer leaves the scrollbar, a string is sent to interpret() +** so that it knows the position of the scrollbar. +*/ + +void +create_testfrac_choice(w) + Widget w; +{ + static XtCallbackRec jumpcallbacks[] = { + {(XtCallbackProc) slider_jump, NULL}, + {NULL, NULL} + }; + + static XtCallbackRec scrollcallbacks[] = { + {(XtCallbackProc) slider_scroll, NULL}, + {NULL, NULL} + }; + + static Arg labelargs[] = { + {XtNborderWidth, (XtArgVal) 0}, + {XtNjustify, (XtArgVal) XtJustifyRight}, + {XtNvertDistance, (XtArgVal) 4} + }; + + static Arg percentargs[] = { + {XtNborderWidth, (XtArgVal) 1}, + {XtNhorizDistance, (XtArgVal) 10}, + {XtNfromHoriz, (XtArgVal) NULL} + }; + + static Arg scrollargs[] = { + {XtNorientation, (XtArgVal) XtorientHorizontal}, + {XtNlength, (XtArgVal) SCROLLBAR_LENGTH}, + {XtNthickness, (XtArgVal) 10}, + {XtNshown, (XtArgVal) 10}, + {XtNhorizDistance, (XtArgVal) 10}, + {XtNfromHoriz, (XtArgVal) NULL}, + {XtNjumpProc, (XtArgVal) NULL}, + {XtNscrollProc, (XtArgVal) NULL} + }; + + static const char *translationtable = "<Leave>: Update()"; + + static XtActionsRec actiontable[] = { + {"Update", (XtActionProc) update}, + {NULL, NULL} + }; + + /* Let the scrollbar know where to store information where we + ** can see it */ + + jumpcallbacks[0].closure = (caddr_t) &fraction; + + label = XtCreateManagedWidget("Percentage of Test",labelWidgetClass,w, + labelargs,XtNumber(labelargs)); + + percentargs[2].value = (XtArgVal) label; + + percent = XtCreateManagedWidget("100",labelWidgetClass,w, + percentargs,XtNumber(percentargs)); + + scrollargs[5].value = (XtArgVal) percent; + scrollargs[6].value = (XtArgVal) jumpcallbacks; + scrollargs[7].value = (XtArgVal) scrollcallbacks; + + slider = XtCreateManagedWidget("Slider",scrollbarWidgetClass,w, + scrollargs,XtNumber(scrollargs)); + + XtAppAddActions(appcontext,actiontable,XtNumber(actiontable)); + XtOverrideTranslations(slider,XtParseTranslationTable(translationtable)); + + /* Start the thumb out at 100% */ + + XawScrollbarSetThumb(slider, 1.0 - SLIDER_LENGTH, SLIDER_LENGTH); +} + +void +update_slider(newpercent) + int newpercent; +{ + fraction = (float) newpercent / 100.0; + XawScrollbarSetThumb(slider, fraction / (1.0-SLIDER_LENGTH), SLIDER_LENGTH); +} @@ -0,0 +1,655 @@ +/* +** $XConsortium: tests.c,v 1.20 91/06/08 18:57:07 rws Exp $ +** $XFree86: xc/programs/xgc/tests.c,v 1.10 2002/05/31 18:46:13 dawes Exp $ +** +*/ + +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/AsciiText.h> +#include <X11/Xos.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include "xgc.h" +#ifdef SVR4 +#define SYSV +#endif +#if !defined(SYSV) && !defined(QNX4) +#include <sys/timeb.h> +#include <sys/resource.h> +#endif + +#ifndef PI +#define PI 3.14159265 +#endif + +#ifdef SYSV +#define random lrand48 +#endif + +extern XStuff X; +extern Widget result; + +extern void GC_change_font(); +extern void print_if_recording(); +void show_result(); + +/* timer(flag) +** ----------- +** When called with StartTimer, starts the stopwatch and returns nothing. +** When called with EndTimer, stops the stopwatch and returns the time +** in microseconds since it started. +** +** Uses rusage() so we can subtract the time used by the system and user +** from our timer, and just concentrate on the time used in the X calls. +*/ + +static long +timer(flag) + int flag; +{ +#if !defined(SYSV) + static struct timeval starttime; /* starting time for gettimeofday() */ + struct timeval endtime; /* ending time for gettimeofday() */ +#if !defined(__UNIXOS2__) && !defined(QNX4) + static struct rusage startusage; /* starting time for getrusage() */ + struct rusage endusage; /* ending time for getrusage() */ +#endif + struct timezone tz; /* to make gettimeofday() happy */ + + long elapsedtime; /* how long since we started the timer */ + + switch (flag) { + case StartTimer: /* store initial values */ + gettimeofday(&starttime,&tz); +#if !defined(__UNIXOS2__) && !defined(QNX4) + getrusage(RUSAGE_SELF,&startusage); +#endif + return((long) NULL); + case EndTimer: + gettimeofday(&endtime,&tz); /* store final values */ +#if !defined(__UNIXOS2__) && !defined(QNX4) + getrusage(RUSAGE_SELF,&endusage); +#endif + + /* all the following line does is use the formula + elapsed time = ending time - starting time, but there are three + different timers and two different units of time, ack... */ + +#if !defined(__UNIXOS2__) && !defined(QNX4) + elapsedtime = (long) ((long) + ((endtime.tv_sec - endusage.ru_utime.tv_sec - endusage.ru_stime.tv_sec + - starttime.tv_sec + startusage.ru_utime.tv_sec + + startusage.ru_stime.tv_sec)) * 1000000) + (long) + ((endtime.tv_usec - endusage.ru_utime.tv_usec - endusage.ru_stime.tv_usec + - starttime.tv_usec + startusage.ru_utime.tv_usec + + startusage.ru_stime.tv_usec)); +#else + elapsedtime = (long)( ((long)endtime.tv_sec-(long)starttime.tv_sec)*1000000 + +((long)endtime.tv_usec-(long)starttime.tv_usec)); +#endif + return(elapsedtime); + + default: + fprintf(stderr,"Invalid flag in timer()\n"); + return((long) NULL); + } +#else + static long starttime; + + switch (flag) { + case StartTimer: + time(&starttime); + return((long) NULL); + case EndTimer: + return( (time(NULL) - starttime) * 1000000); + default: + fprintf(stderr,"Invalid flag in timer()\n"); + return((long) NULL); + } +#endif +} + + +void +copyarea_test() +{ + int num_copies = 200; + int i; + long totaltime; + char buf[80]; + + num_copies *= X.percent; + + XSetFillStyle(X.dpy,X.miscgc,FillTiled); + XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400); + + XSync(X.dpy,0); + timer(StartTimer); + for (i=0;i<num_copies;++i) + XCopyArea(X.dpy,X.win,X.win,X.gc,i,200-i, + 200,200,200-i,i); + XSync(X.dpy,0); + totaltime = timer(EndTimer); + + sprintf(buf,"%.2f seconds.",(double)totaltime/1000000.); + show_result(buf); +} + +void +copyplane_test() +{ + int num_copies = 200; + int i; + long totaltime; + char buf[80]; + + if(!X.gcv.plane_mask || (X.gcv.plane_mask & (X.gcv.plane_mask - 1))) { + show_result("exactly one bit in plane mask must be set for this test"); + return; + } + + + num_copies *= X.percent; + + XSetPlaneMask(X.dpy, X.gc, ~0L); + XSetFillStyle(X.dpy,X.miscgc,FillTiled); + XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400); + + XSync(X.dpy,0); + timer(StartTimer); + for (i=0;i<num_copies;++i) + XCopyPlane(X.dpy,X.win,X.win,X.gc,i,200-i, + 200,200,200-i,i,X.gcv.plane_mask); + XSync(X.dpy,0); + totaltime = timer(EndTimer); + XSetPlaneMask(X.dpy, X.gc, X.gcv.plane_mask); + + sprintf(buf,"%.2f seconds.",(double)totaltime/1000000.); + show_result(buf); +} + +void +circle_line_test(num_vertices,radius) + int num_vertices,radius; +{ + double theta, delta; + int length, centerx, centery, i; + int relative_angle; + long totaltime; + char buf[80]; + XPoint *coord; + + relative_angle = num_vertices*5/12+1; + delta = (double) relative_angle / (double) num_vertices * 2 * PI; + centerx = centery = 200; + + coord = (XPoint *) malloc (sizeof(XPoint)*(num_vertices+1)); + + length = (int) (2 * radius * (float) atan(delta/2.)); + + for (i=0;i<=num_vertices;++i) { + theta = (double) i * delta; + coord[i].x = centerx + (int) (radius * cos(theta)); + coord[i].y = centery + (int) (radius * sin(theta)); + } + + XSync(X.dpy,0); + timer(StartTimer); + XDrawLines(X.dpy,X.win,X.gc,coord,num_vertices+1,CoordModeOrigin); + XSync(X.dpy,0); + totaltime = timer(EndTimer); + + sprintf(buf,"%d lines of length %d in %.3f seconds.",num_vertices, + length,(double)totaltime/1000000.); + show_result(buf); + + free(coord); +} + + + +void +polyline_test() +{ + circle_line_test((int)(601*X.percent),190); +} + +void +polysegment_test() +{ + XSegment *segments; + int num_segments = 600; + long totaltime; + char buf[80]; + int i; + + num_segments *= X.percent; + + segments = (XSegment *) malloc(sizeof(XSegment) * num_segments); + + segments[0].x1 = random()%400; segments[0].y1 = random()%400; + segments[0].x2 = random()%400; segments[0].y2 = random()%400; + + for(i=1;i<num_segments;++i) { + segments[i].x1 = (segments[i-1].x1-segments[i-1].y2+400+i)%400; + segments[i].y1 = (segments[i-1].y1+segments[i-1].x2+i)%400; + segments[i].x2 = (segments[i-1].x1-segments[i-1].y1+400+i)%400; + segments[i].y2 = (segments[i-1].x2+segments[i-1].y2+i)%400; + } + + XSync(X.dpy,0); + start_timer(); + XDrawSegments(X.dpy,X.win,X.gc,segments,num_segments); + XSync(X.dpy,0); + totaltime = end_timer(); + + sprintf(buf,"%d segments in %.3f seconds.",num_segments, + (double)totaltime/1000000.); + show_result(buf); + + free(segments); +} + +void +polypoint_test() +{ + XPoint *points; + int num_points = 100000; + long totaltime; + char buf[80]; + int i; + + num_points *= X.percent; + + points = (XPoint *) malloc(sizeof(XPoint) * num_points); + + points[0].x = random()%400; points[0].y = random()%400; + points[1].x = random()%400; points[1].y = random()%400; + + for (i=2;i<num_points;++i) { + points[i].x = (points[i-1].x+points[i-2].y+i*3/200)%400; + points[i].y = (points[i-1].y+points[i-2].x+i*5/200)%400; + } + + XSync(X.dpy,0); + start_timer(); + XDrawPoints(X.dpy,X.win,X.gc,points,num_points,CoordModeOrigin); + XSync(X.dpy,0); + totaltime = end_timer(); + + sprintf(buf,"%d points in %.3f seconds.",num_points, + (double)totaltime/1000000.); + show_result(buf); + + free(points); +} + +void +genericrectangle_test(fill) + Boolean fill; +{ + XRectangle *rects; + int num_rects = 200; + int perimeter = 0, area = 0; + int i; + long totaltime; + char buf[80]; + + num_rects *= X.percent; + + rects = (XRectangle *) malloc(sizeof(XRectangle) * num_rects); + + for (i=0;i<num_rects;++i) { + rects[i].x = rects[i].y = 200 - i; + rects[i].width = rects[i].height = 2 * i; + perimeter += rects[i].width * 2 + rects[i].height * 2; + area += rects[i].width * rects[i].height; + } + + XSync(X.dpy,0); + start_timer(); + if (fill) XFillRectangles(X.dpy,X.win,X.gc,rects,num_rects); + else XDrawRectangles(X.dpy,X.win,X.gc,rects,num_rects); + XSync(X.dpy,0); + totaltime = end_timer(); + + if (fill) + sprintf(buf,"%d pixels in %.2f seconds.",area,(double)totaltime/1000000.); + else + sprintf(buf,"Total line length %d in %.3f seconds.",perimeter, + (double)totaltime/1000000.); + show_result(buf); + + free(rects); +} + +void +polyrectangle_test() +{ + genericrectangle_test(FALSE); +} + +void +polyfillrectangle_test() +{ + genericrectangle_test(TRUE); +} + +/*****************************/ + +void +fillpolygon_test() +{ + int i; + int points_per_side = 40; + int spacing; + XPoint *points; + XPoint polypoints[3]; + + points = (XPoint *) malloc (sizeof(XPoint) * points_per_side * 4); + spacing = 400 / points_per_side; + + for (i = 0; i < points_per_side; ++i) { + points[i].x = i * spacing; + points[i].y = 0; + + points[i + points_per_side].x = 400; + points[i + points_per_side].y = i * spacing; + + points[i + 2 * points_per_side].x = 400 - i * spacing; + points[i + 2 * points_per_side].y = 400; + + points[i + 3 * points_per_side].x = 0; + points[i + 3 * points_per_side].y = 400 - i * spacing; + } + + for (i = 0; i < 2 * points_per_side; i += 2) { + polypoints[0].x = points[i].x; + polypoints[0].y = points[i].y; + + polypoints[1].x = points[i + 2 * points_per_side].x; + polypoints[1].y = points[i + 2 * points_per_side].y; + + polypoints[2].x = points[i + 2 * points_per_side + 1].x; + polypoints[2].y = points[i + 2 * points_per_side + 1].y; + + XFillPolygon (X.dpy, X.win, X.gc, polypoints, 3, Convex, CoordModeOrigin); + } + free(points); +} + +/*****************************/ + +void +genericarc_test(fill) + Boolean fill; +{ + XArc *arcs; + int num_arcs = 180; + int i; + long totaltime; + char buf[80]; + + num_arcs *= X.percent; + + arcs = (XArc *) malloc(sizeof(XArc) * num_arcs); + + for (i=0;i<num_arcs;++i) { + arcs[i].x = i; + arcs[i].y = i; + arcs[i].width = i; + arcs[i].height = i; + arcs[i].angle1 = i * 128; + arcs[i].angle2 = i * 128; + } + + XSync(X.dpy,0); + start_timer(); + if (fill) XFillArcs(X.dpy,X.win,X.gc,arcs,num_arcs); + else XDrawArcs(X.dpy,X.win,X.gc,arcs,num_arcs); + XSync(X.dpy,0); + totaltime = end_timer(); + + sprintf(buf,"An uncounted number of pixels in %.3f seconds.", + (double)totaltime/1000000.); + show_result(buf); + + free(arcs); +} + +void +polyarc_test() +{ + genericarc_test(FALSE); +} + +void +polyfillarc_test() +{ + genericarc_test(TRUE); +} + +static const char string8[] = "pack my box with five dozen liquor jugs"; + +void +polytext8_test() +{ + int num_strings = 200; + int i; + long totaltime; + char buf[80]; + + num_strings *= X.percent; + + XSync(X.dpy,0); + start_timer(); + for (i=0;i<num_strings;++i) { + XDrawString(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),i, + string8,sizeof(string8)-1); + } + XSync(X.dpy,0); + totaltime = end_timer(); + + sprintf(buf,"%d strings in %.2f seconds.",num_strings, + (double) totaltime/1000000.); + show_result(buf); +} + +void +imagetext8_test() +{ + int num_strings = 200; + int i; + long totaltime; + char buf[80]; + + num_strings *= X.percent; + + XSync(X.dpy,0); + start_timer(); + for (i=0;i<num_strings;++i) { + XDrawImageString(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),i, + string8,sizeof(string8)-1); + } + XSync(X.dpy,0); + totaltime = end_timer(); + + sprintf(buf,"%d strings in %.2f seconds.",num_strings, + (double) totaltime/1000000.); + show_result(buf); +} + +static const char unicode_font[] = + "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1"; + +static const XChar2b string16[] = { + { 0x00, 0x20 }, { 0x00, 0x20 }, { 0x22, 0x2E }, { 0x00, 0x20 }, + { 0x00, 0x45 }, { 0x22, 0xC5 }, { 0x00, 0x64 }, { 0x00, 0x61 }, + { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x00, 0x51 }, + { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x00, 0x20 }, { 0x00, 0x6E }, + { 0x00, 0x20 }, { 0x21, 0x92 }, { 0x00, 0x20 }, { 0x22, 0x1E }, + { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x22, 0x11 }, { 0x00, 0x20 }, + { 0x00, 0x66 }, { 0x00, 0x28 }, { 0x00, 0x69 }, { 0x00, 0x29 }, + { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x22, 0x0F }, + { 0x00, 0x20 }, { 0x00, 0x67 }, { 0x00, 0x28 }, { 0x00, 0x69 }, + { 0x00, 0x29 }, { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x22, 0x00 }, + { 0x00, 0x78 }, { 0x22, 0x08 }, { 0x21, 0x1D }, { 0x00, 0x3A }, + { 0x00, 0x20 }, { 0x23, 0x08 }, { 0x00, 0x78 }, { 0x23, 0x09 }, + { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x22, 0x12 }, + { 0x23, 0x0A }, { 0x22, 0x12 }, { 0x00, 0x78 }, { 0x23, 0x0B }, + { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x03, 0xB1 }, { 0x00, 0x20 }, + { 0x22, 0x27 }, { 0x00, 0x20 }, { 0x00, 0xAC }, { 0x03, 0xB2 }, + { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x00, 0xAC }, + { 0x00, 0x28 }, { 0x00, 0xAC }, { 0x03, 0xB1 }, { 0x00, 0x20 }, + { 0x22, 0x28 }, { 0x00, 0x20 }, { 0x03, 0xB2 }, { 0x00, 0x29 }, + { 0x00, 0x2C } +}; + +void +polytext16_test() +{ + int num_strings = 50; + int i; + long totaltime; + char buf[80]; + + num_strings *= X.percent; + + GC_change_font(unicode_font,FALSE); + + XSync(X.dpy,0); + start_timer(); + for (i=0;i<num_strings;++i) { + XDrawString16(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),10*i, + string16,sizeof(string16)/sizeof(XChar2b)); + } + XSync(X.dpy,0); + totaltime = end_timer(); + + GC_change_font(X.fontname,FALSE); + + sprintf(buf,"%d strings in %.2f seconds.",num_strings, + (double) totaltime/1000000.); + show_result(buf); +} + +void +imagetext16_test() +{ + int num_strings = 50; + int i; + long totaltime; + char buf[80]; + + num_strings *= X.percent; + + GC_change_font(unicode_font,FALSE); + + XSync(X.dpy,0); + start_timer(); + for (i=0;i<num_strings;++i) { + XDrawImageString16(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),10*i, + string16,sizeof(string16)/sizeof(XChar2b)); + } + XSync(X.dpy,0); + totaltime = end_timer(); + + GC_change_font(X.fontname,FALSE); + + sprintf(buf,"%d strings in %.2f seconds.",num_strings, + (double) totaltime/1000000.); + show_result(buf); +} + +void +putimage_test() +{ + int num_copies = 200; + int i; + long totaltime; + char buf[80]; + + num_copies *= X.percent; + + XSetFillStyle(X.dpy,X.miscgc,FillTiled); + XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400); + + X.image = XGetImage(X.dpy,X.win,0,0,200,200,~0,XYPixmap); + + XSync(X.dpy,0); + timer(StartTimer); + for (i=0;i<num_copies;++i) + XPutImage(X.dpy,X.win,X.gc,X.image,0,0,i,i,200,200); + XSync(X.dpy,0); + totaltime = timer(EndTimer); + + sprintf(buf,"%.2f seconds.",(double)totaltime/1000000.); + show_result(buf); +} + + +/*****************************/ +/*****************************/ + +void +run_test() +{ + XClearWindow(X.dpy,X.win); + + print_if_recording("run\n"); + + switch (X.test) { + case CopyArea: copyarea_test(); break; + case CopyPlane: copyplane_test(); break; + case PolyPoint: polypoint_test(); break; + case PolyLine: polyline_test(); break; + case PolySegment: polysegment_test(); break; + case PolyRectangle: polyrectangle_test(); break; + case PolyArc: polyarc_test(); break; + case FillPolygon: fillpolygon_test(); break; + case PolyFillRect: polyfillrectangle_test(); break; + case PolyFillArc: polyfillarc_test(); break; + case PolyText8: polytext8_test(); break; + case ImageText8: imagetext8_test(); break; + case PolyText16: polytext16_test(); break; + case ImageText16: imagetext16_test(); break; + case PutImage: putimage_test(); break; + default: fprintf(stderr,"That test doesn't exist yet.\n"); + } +} + +/*****************************/ + +/* set_text(w,string) +** ------------------ +** Sets the text in a read-only text widget to the specified string. +*/ + +void +set_text(w,string) + Widget w; + char *string; +{ + static Arg args[2]; + + XtSetArg(args[0], XtNstring, string); + XtSetArg(args[1], XtNlength, strlen(string)); + XtSetValues(w, args, (Cardinal) 2 ); +} + +void +show_result(string) + char *string; +{ + char buf[80]; + + set_text(result,string); + + strcpy(buf,"# "); + strncat(buf,string,sizeof(buf) - 3); + buf[sizeof(buf) - 3] = '\0'; + strcat(buf,"\n"); + print_if_recording(buf); +} @@ -0,0 +1,209 @@ +/* +** xgc +** +** text.c +** +** How to make a text widget that returns a string when the cursor +** leaves its window. +*/ +/* $XFree86: xc/programs/xgc/text.c,v 1.3 2000/02/17 14:00:37 dawes Exp $ */ + +#include <stdio.h> +#include <stdlib.h> +#include <X11/Intrinsic.h> +#include <X11/StringDefs.h> +#include <X11/Xaw/Form.h> +#include <X11/Xaw/Label.h> +#include <X11/Xaw/AsciiText.h> +#include "xgc.h" + +static void WriteText(); +extern void interpret(); + +extern XStuff X; +extern XtAppContext appcontext; + +/* the strings which are displayed on the screen, edited, and sent + to interpret() */ +static char textstrings[NUMTEXTWIDGETS][80]; + +static char oldtextstrings[NUMTEXTWIDGETS][80]; + +static const char *defaultstrings[NUMTEXTWIDGETS] = {"0","6x10","0","1"}; + +/* The labels displayed next to them */ +static const char *labels[NUMTEXTWIDGETS] = {"Line Width","Font","Foreground", + "Background"}; + +/* the first half of what gets sent to interpret() */ +static const char *names[NUMTEXTWIDGETS] = {"linewidth ","font ","foreground ", + "background "}; + +/* create_text_choice(w,type,length,width) +** --------------------------------------- +** Inside w (a form), creates an editable text widget of width width. The +** user can enter a string of up to length characters. type is one of +** the constants defined in xgc.h; it decides things like the label, +** what string will be displayed and edited, etc. When the pointer leaves +** the widget, the widget does the appropriate thing with the text +** inside it; the user doesn't have to press an "enter" button or anything. +** Returns the text widget which the user will edit. +*/ + +Widget +create_text_choice(w,type,length,width) + Widget w; + int type; + int length, width; +{ + char translationtable[600]; /* for adding the new action (calling + WriteText() when the pointer leaves) */ + + static XtActionsRec actionTable[] = { /* likewise */ + {"WriteText", WriteText}, + {"Nothing", NULL} + }; + + static Arg labelargs[] = { + {XtNborderWidth, (XtArgVal) 0}, + {XtNjustify, (XtArgVal) XtJustifyRight} + }; + + static Arg textargs[] = { + {XtNeditType, (XtArgVal) XawtextEdit}, + {XtNstring, (XtArgVal) NULL}, + {XtNlength, (XtArgVal) NULL}, + {XtNwidth, (XtArgVal) NULL}, + {XtNhorizDistance, (XtArgVal) 10}, + {XtNfromHoriz, (XtArgVal) NULL}, + {XtNinsertPosition, (XtArgVal) NULL}, + {XtNuseStringInPlace, (XtArgVal) True} + }; + + static Widget text; /* the text widget */ + static Widget label; /* the label widget */ + + /* Disable keys which would cause the cursor to go off the single + ** line that we want to display. If the pointer leaves the window, + ** update the GC accordingly. The integer passed to WriteText is + ** so it knows what type of widget was just updated. */ + + sprintf(translationtable, + "<Leave>: WriteText(%d)\n\ + Ctrl<Key>J: Nothing()\n\ + Ctrl<Key>M: Nothing()\n\ + <Key>Linefeed: Nothing()\n\ + <Key>Return: Nothing()\n\ + Ctrl<Key>O: Nothing()\n\ + Meta<Key>I: Nothing()\n\ + Ctrl<Key>N: Nothing()\n\ + Ctrl<Key>P: Nothing()\n\ + Ctrl<Key>Z: Nothing()\n\ + Meta<Key>Z: Nothing()\n\ + Ctrl<Key>V: Nothing()\n\ + Meta<Key>V: Nothing()",type); + + /* label uses type to find out what its title is */ + label = XtCreateManagedWidget(labels[type],labelWidgetClass,w, + labelargs,XtNumber(labelargs)); + + /* text uses type to find out what its string is */ + switch (type) { + case TForeground: + sprintf(textstrings[type],"%d",(int) X.gcv.foreground); + sprintf(oldtextstrings[type],"%d",(int) X.gcv.foreground); + break; + case TBackground: + sprintf(textstrings[type],"%d",(int) X.gcv.background); + sprintf(oldtextstrings[type],"%d",(int) X.gcv.background); + break; + default: + strcpy(textstrings[type],defaultstrings[type]); + strcpy(oldtextstrings[type],defaultstrings[type]); + } + textargs[1].value = (XtArgVal) textstrings[type]; + textargs[2].value = (XtArgVal) length; + textargs[3].value = (XtArgVal) width; + textargs[5].value = (XtArgVal) label; + textargs[6].value = (XtArgVal) strlen(textstrings[type]); + + text = XtCreateManagedWidget("text", asciiTextWidgetClass,w, + textargs,XtNumber(textargs)); + + /* Register the actions and translations */ + + XtAppAddActions(appcontext,actionTable,XtNumber(actionTable)); + XtOverrideTranslations(text,XtParseTranslationTable(translationtable)); + + return(text); +} + +/* WriteText(w,event,params,num_params) +** ------------------------------------ +** Makes an appropriate string and sends it off to interpret(). +** It's an ActionProc, thus the funny arguments. +*/ + +/*ARGSUSED*/ +static void +WriteText(w,event,params,num_params) + Widget w; + XEvent *event; + String *params; /* the type is in here */ + Cardinal *num_params; +{ + char mbuf[80]; + int type; /* which string # to send */ + + type = atoi(params[0]); + if (strcmp(textstrings[type],oldtextstrings[type])) { + strcpy(oldtextstrings[type],textstrings[type]); + sprintf(mbuf,names[type]); /* the right first half */ + strcat(mbuf,textstrings[type]); /* the right second half */ + strcat(mbuf,"\n"); /* the right newline */ + interpret(mbuf); /* send it off */ + } +} + +/* change_text(w,type,newtext) +** ------------------------ +** Changes the text in the text widget w of type type to newtext. +*/ + +void +change_text(w,newtext) + Widget w; + String newtext; +{ + XawTextBlock text; /* the new text */ + XawTextPosition first, last; /* boundaries of the old text */ + String oldtext; /* the old text */ + + static Arg textargs[] = { + {XtNstring, (XtArgVal) 0} + }; + + /* Initialize the XawTextBlock. */ + + if (!newtext) + newtext = ""; + text.firstPos = 0; + text.length = strlen(newtext); + text.ptr = newtext; + text.format = FMT8BIT; + + /* Find the old text, so we can get its length, so we know how + ** much of it to update. */ + + textargs[0].value = (XtArgVal) &oldtext; + XtGetValues(w,textargs,XtNumber(textargs)); + first = XawTextTopPosition(w); + if (!oldtext) + oldtext = ""; + last = (XawTextPosition) strlen(oldtext)+1; + + /* Replace it with the new text. */ + + XawTextReplace(w, first, last, &text); +} + @@ -0,0 +1,17 @@ +/* $XFree86: xc/programs/xgc/tile,v 1.2 2001/10/28 03:34:34 tsi Exp $ */ + +#if !defined(tile_width) && !defined(tile_height) + +#define tile_width 16 +#define tile_height 16 + +#ifdef DEFINE_TILE + +static unsigned char tile_bits[] = { + 0xff, 0x80, 0xfc, 0x80, 0x70, 0xc0, 0xc0, 0xc0, 0xe0, 0xe3, 0xe0, 0xef, + 0xf0, 0xff, 0xf0, 0xdf, 0xfb, 0x0f, 0xff, 0x0f, 0xf7, 0x07, 0xc7, 0x07, + 0x03, 0x03, 0x03, 0x0e, 0x01, 0x3f, 0x01, 0xff}; + +#endif + +#endif @@ -0,0 +1,64 @@ +/* +** xgc +** +** xgc.h +*/ +/* $XFree86: xc/programs/xgc/xgc.h,v 1.3 2000/02/17 14:00:38 dawes Exp $ */ + +#include "constants.h" + +typedef struct { + Display *dpy; /* the display! */ + Screen *scr; /* the screen! */ + Window win; /* the window the test runs in */ + GC gc; /* the GC! */ + GC miscgc; /* used for doing stuff when we don't want + to change the normal GC */ + XGCValues gcv; /* a separate copy of what's in the GC, + since we're not allowed to look in it */ + Pixmap tile; /* what we tile with */ + Pixmap stipple; /* what we stipple with */ + XImage *image; /* image for GetImage & PutImage */ + int test; /* which test is being run */ + float percent; /* percentage of test to run */ + Pixel foreground; + Pixel background; + char *fontname; +} XStuff; /* All the stuff that only X needs to + know about */ + +typedef struct { + char name[40]; /* name as it will appear on the screen */ + char text[40]; /* Xgc command it translates to */ + int num_commands; /* number of command buttons inside it */ + int columns; /* how many columns of command buttons; if + 0, then there's only one row */ + struct { + char name[40]; /* name as it will appear on the screen */ + char text[40]; /* Xgc command it translates to */ + } command_data[MAXCHOICES]; +} ChoiceStuff; /* All the info needed to deal with a + choice widget */ +typedef struct { + const char *name; + const char *text; + int code; +} XgcData; + +typedef struct { + struct { + const char *name; + const char *text; + int num_toggles; + int columns; + } choice; + XgcData *data; +} XgcStuff; + +typedef struct { + Widget label; + int size; + WidgetList widgets; +} ChoiceDesc; + +/************/ @@ -0,0 +1,38 @@ +.\" $XConsortium: xgc.man,v 1.6 94/04/17 20:45:31 gildea Exp $ +.\" +.\" $XFree86: xc/programs/xgc/xgc.man,v 1.3 2001/01/27 18:21:15 dawes Exp $ +.\" +.TH XGC 1 __xorgversion__ +.SH NAME +xgc - X graphics demo +.SH SYNOPSIS +.ta 8n +\fBxgc\fP [-\fItoolkitoption\fP ...] +.SH DESCRIPTION +The +.I xgc +program demonstrates various features of the X graphics primitives. +Try the buttons, see what they do; we haven't the time to document +them, perhaps you do? +.SH OPTIONS +.I Xgc +accepts all of the standard X Toolkit command line options. +.SH X DEFAULTS +This program accepts the usual defaults for toolkit applications. +.SH ENVIRONMENT +.PP +.TP 8 +.B DISPLAY +to get the default host and display number. +.TP 8 +.B XENVIRONMENT +to get the name of a resource file that overrides the global resources +stored in the RESOURCE_MANAGER property. +.SH "SEE ALSO" +X(__miscmansuffix__) +.SH BUGS +This program isn't really finished yet. +.br +See \fIX(__miscmansuffix__)\fP for a full statement of rights and permissions. +.SH AUTHORS +Dan Schmidt, MIT |