From 82a6e01af6c39e22855495b912c23efddfb17224 Mon Sep 17 00:00:00 2001 From: Kaleb Keithley Date: Fri, 14 Nov 2003 16:49:22 +0000 Subject: Initial revision --- Bugs | 11 + Written/FilledRects | 93 ++++++++ Written/Interface | 9 + Written/Jim | 255 ++++++++++++++++++++ Written/Notes | 296 ++++++++++++++++++++++++ Written/Notes2 | 68 ++++++ Written/Outline | 191 +++++++++++++++ Written/Widget | 26 +++ Xgc.ad | 2 + choice.c | 282 ++++++++++++++++++++++ constants.h | 76 ++++++ dashlist.c | 189 +++++++++++++++ getfile.c | 159 +++++++++++++ gram.y | 116 ++++++++++ interpret.c | 429 ++++++++++++++++++++++++++++++++++ lex.l | 169 ++++++++++++++ main.c | 510 ++++++++++++++++++++++++++++++++++++++++ main.h | 148 ++++++++++++ planemask.c | 198 ++++++++++++++++ record.c | 299 ++++++++++++++++++++++++ testfrac.c | 205 ++++++++++++++++ tests.c | 655 ++++++++++++++++++++++++++++++++++++++++++++++++++++ text.c | 209 +++++++++++++++++ tile | 17 ++ xgc.h | 64 +++++ xgc.man | 38 +++ 26 files changed, 4714 insertions(+) create mode 100644 Bugs create mode 100644 Written/FilledRects create mode 100644 Written/Interface create mode 100644 Written/Jim create mode 100644 Written/Notes create mode 100644 Written/Notes2 create mode 100644 Written/Outline create mode 100644 Written/Widget create mode 100644 Xgc.ad create mode 100644 choice.c create mode 100644 constants.h create mode 100644 dashlist.c create mode 100644 getfile.c create mode 100644 gram.y create mode 100644 interpret.c create mode 100644 lex.l create mode 100644 main.c create mode 100644 main.h create mode 100644 planemask.c create mode 100644 record.c create mode 100644 testfrac.c create mode 100644 tests.c create mode 100644 text.c create mode 100644 tile create mode 100644 xgc.h create mode 100644 xgc.man diff --git a/Bugs b/Bugs new file mode 100644 index 0000000..c8ed6f2 --- /dev/null +++ b/Bugs @@ -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. diff --git a/Xgc.ad b/Xgc.ad new file mode 100644 index 0000000..7695abb --- /dev/null +++ b/Xgc.ad @@ -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 +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#include + +#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 + ** 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 = + "CtrlJ: KillPopup() Done()\n\ + CtrlM: KillPopup() Done()\n\ + Linefeed: KillPopup() Done()\n\ + Return: KillPopup() Done()\n\ + CtrlO: Nothing()\n\ + MetaI: Nothing()\n\ + CtrlN: Nothing()\n\ + CtrlP: Nothing()\n\ + CtrlZ: Nothing()\n\ + MetaZ: Nothing()\n\ + CtrlV: Nothing()\n\ + MetaV: 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); +} diff --git a/gram.y b/gram.y new file mode 100644 index 0000000..e39d3d5 --- /dev/null +++ b/gram.y @@ -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 +#include +#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 STRING +%token NUMBER +%token RUN +%token FUNCTION FUNCTIONTYPE +%token TEST TESTTYPE +%token LINESTYLE LINESTYLETYPE +%token CAPSTYLE CAPSTYLETYPE +%token JOINSTYLE JOINSTYLETYPE +%token ROUND SOLID +%token FILLSTYLE FILLSTYLETYPE +%token FILLRULE FILLRULETYPE +%token ARCMODE ARCMODETYPE +%token FOREGROUND BACKGROUND LINEWIDTH PLANEMASK DASHLIST PERCENT +%token 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 +#include +#include +#include +#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 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< 100) return; + + X.percent = (float) percent / 100.0; + + if (feedback) update_slider(percent); +} diff --git a/lex.l b/lex.l new file mode 100644 index 0000000..52e5245 --- /dev/null +++ b/lex.l @@ -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 +#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 diff --git a/main.c b/main.c new file mode 100644 index 0000000..9d52b10 --- /dev/null +++ b/main.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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("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;ichoice.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); +} diff --git a/main.h b/main.h new file mode 100644 index 0000000..7b52d74 --- /dev/null +++ b/main.h @@ -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 +#include +#include +#include +#include +#include +#include +#include +#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< +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#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 = ": 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); +} diff --git a/tests.c b/tests.c new file mode 100644 index 0000000..4d552ef --- /dev/null +++ b/tests.c @@ -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 +#include +#include +#include +#include +#include +#include +#include "xgc.h" +#ifdef SVR4 +#define SYSV +#endif +#if !defined(SYSV) && !defined(QNX4) +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#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, + ": WriteText(%d)\n\ + CtrlJ: Nothing()\n\ + CtrlM: Nothing()\n\ + Linefeed: Nothing()\n\ + Return: Nothing()\n\ + CtrlO: Nothing()\n\ + MetaI: Nothing()\n\ + CtrlN: Nothing()\n\ + CtrlP: Nothing()\n\ + CtrlZ: Nothing()\n\ + MetaZ: Nothing()\n\ + CtrlV: Nothing()\n\ + MetaV: 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); +} + diff --git a/tile b/tile new file mode 100644 index 0000000..a66e6cb --- /dev/null +++ b/tile @@ -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 diff --git a/xgc.h b/xgc.h new file mode 100644 index 0000000..6d47439 --- /dev/null +++ b/xgc.h @@ -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; + +/************/ diff --git a/xgc.man b/xgc.man new file mode 100644 index 0000000..d4c2787 --- /dev/null +++ b/xgc.man @@ -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 -- cgit v1.2.3