summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Bugs11
-rw-r--r--Written/FilledRects93
-rw-r--r--Written/Interface9
-rw-r--r--Written/Jim255
-rw-r--r--Written/Notes296
-rw-r--r--Written/Notes268
-rw-r--r--Written/Outline191
-rw-r--r--Written/Widget26
-rw-r--r--Xgc.ad2
-rw-r--r--choice.c282
-rw-r--r--constants.h76
-rw-r--r--dashlist.c189
-rw-r--r--getfile.c159
-rw-r--r--gram.y116
-rw-r--r--interpret.c429
-rw-r--r--lex.l169
-rw-r--r--main.c510
-rw-r--r--main.h148
-rw-r--r--planemask.c198
-rw-r--r--record.c299
-rw-r--r--testfrac.c205
-rw-r--r--tests.c655
-rw-r--r--text.c209
-rw-r--r--tile17
-rw-r--r--xgc.h64
-rw-r--r--xgc.man38
26 files changed, 4714 insertions, 0 deletions
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 <stdio.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Toggle.h>
+
+#include "xgc.h"
+
+static void print_text_to_buffer(
+#if NeedFunctionPrototypes
+ Widget, caddr_t, caddr_t
+#endif
+);
+extern void interpret();
+
+extern XStuff X;
+
+/* create_choice(w,info)
+** ---------------------
+** What a choice widget is: A collection of toggle buttons placed inside
+** a form widget. Exactly one of these toggle buttons can be "on" at
+** any given time; the rest are "off". "On" toggle buttons have
+** the foreground and background colors reversed.
+** Also, specifically because it comes in handy in xgc, choosing one
+** of the buttons causes a string associated with it to be printed out
+** (and interpreted). Half of the string is global to the whole form
+** and the other half is local to each button.
+**
+** For example, pressing the "xor" button in the "function" form would
+** cause xgc to interpret the string "function xor", thus changing the
+** function in the GC to xor.
+**
+** There's also a label widget to the left of that mess, with an
+** incredibly descriptive title.
+**
+** create_choice() makes one.
+**
+** w is the form widget (already created) into which we will place the
+** toggle buttons. info contains lots of useful information, such
+** as the names of the buttons and their strings (see xgc.h).
+*/
+
+ChoiceDesc *
+create_choice(w,info)
+ Widget w;
+ XgcStuff *info;
+{
+ ChoiceDesc *choice; /* What we will return. Contains
+ ** Widget ID's of the label and toggles. */
+ int i; /* Counter */
+ char *text; /* Text to be interpreted when the
+ ** toggle widget is selected. */
+
+ /* ArgList for the label widget */
+ static Arg labelargs[] = {
+ {XtNborderWidth, (XtArgVal) 0},
+ {XtNjustify, (XtArgVal) XtJustifyRight},
+ {XtNvertDistance, (XtArgVal) 4}
+ };
+
+ /* ArgList for the toggle widgets */
+ static Arg toggleargs[] = {
+ {XtNfromHoriz, (XtArgVal) NULL},
+ {XtNfromVert, (XtArgVal) NULL},
+ {XtNhorizDistance, (XtArgVal) 4},
+ {XtNvertDistance, (XtArgVal) 4},
+ {XtNradioGroup, (XtArgVal) NULL},
+ {XtNcallback, (XtArgVal) NULL}
+ };
+
+ /* Callback list for the toggle widgets */
+ static XtCallbackRec callbacklist[] = {
+ {(XtCallbackProc) print_text_to_buffer, NULL},
+ {NULL, NULL}
+ };
+
+ /* Allocate space for the widgets and initialize choice */
+ choice = (ChoiceDesc *) XtMalloc(sizeof(ChoiceDesc));
+ choice->widgets = (WidgetList) XtMalloc(sizeof(Widget) *
+ info->choice.num_toggles);
+ choice->size = info->choice.num_toggles;
+ choice->label = XtCreateManagedWidget(info->choice.name,labelWidgetClass,w,
+ labelargs,XtNumber(labelargs));
+
+ /* set up the toggle widgets */
+ toggleargs[5].value = (XtArgVal) callbacklist;
+ for (i = 0; i < info->choice.num_toggles; ++i) {
+ if (i == 0) {
+ /* the upper left toggle; put it next to the label
+ and don't worry about radio groups */
+ toggleargs[0].value = (XtArgVal) choice->label;
+ toggleargs[1].value = (XtArgVal) NULL;
+ toggleargs[2].value = (XtArgVal) 10;
+ toggleargs[3].value = (XtArgVal) 4;
+ toggleargs[4].value = (XtArgVal) NULL;
+ }
+ else {
+ toggleargs[4].value = (XtArgVal) choice->widgets[0];
+ /* are we starting a new row? */
+ if (info->choice.columns > 0 &&
+ i > 1 &&
+ (i % (info->choice.columns) == 0)) {
+ toggleargs[0].value = (XtArgVal) choice->label;
+ /* under the appropriate toggle */
+ toggleargs[1].value = (XtArgVal) choice->widgets[i - info->choice.columns];
+ toggleargs[2].value = (XtArgVal) 10;
+ toggleargs[3].value = (XtArgVal) 4;
+ }
+ else { /* we're in the middle of a row */
+ /* to the right of the previous toggle */
+ toggleargs[0].value = (XtArgVal) choice->widgets[i - 1];
+ toggleargs[1].value = (XtArgVal) NULL;
+ toggleargs[2].value = (XtArgVal) -1; /* overlapping slightly */
+ toggleargs[3].value = (XtArgVal) 4;
+ }
+
+ if (info->choice.columns > 0 &&
+ i >= info->choice.columns) {
+ /* correct vertical spacing */
+ toggleargs[1].value = (XtArgVal) choice->widgets[i - info->choice.columns];
+ toggleargs[3].value = (XtArgVal) -1;
+ }
+ }
+
+ /* Put the correct stuff in the text field */
+ text = (char *) XtMalloc((unsigned) (strlen(info->choice.text) +
+ strlen((info->data)[i].text) + 3));
+ strcpy(text, info->choice.text);
+ strcat(text, " ");
+ strcat(text, (info->data)[i].text);
+ strcat(text, "\n");
+ callbacklist[0].closure = (caddr_t) text;
+
+ /* Create it finally */
+ choice->widgets[i] = XtCreateManagedWidget((info->data[i]).name,
+ toggleWidgetClass,
+ w,
+ toggleargs,
+ XtNumber(toggleargs));
+ }
+
+ /* The toggle widgets have all been created;
+ ** now make the all the same width if that's
+ ** what we want to do. */
+
+ if (info->choice.columns > 0) {
+ Dimension maxwidth = 0; /* maximum width we've found */
+ Dimension width; /* width of the current widget */
+ static Arg args[] = { /* for getting and setting the width */
+ {XtNwidth, (XtArgVal) NULL}
+ };
+
+ args[0].value = (XtArgVal) &width;
+
+ /* Find the maximum width of any toggle widget */
+ for (i = 0; i < info->choice.num_toggles; ++i) {
+ XtGetValues(choice->widgets[i],args,1);
+ maxwidth = max(maxwidth,width);
+ }
+
+ /* Now set them all to that width */
+ args[0].value = (XtArgVal) maxwidth;
+ for (i = 0; i < info->choice.num_toggles; ++i)
+ XtSetValues(choice->widgets[i],args,1);
+ }
+
+ /* return the list of toggles that were just created */
+ return (choice);
+}
+
+
+
+/* select_button(choice,togglenum)
+** -------------------------------
+** "Selects" the togglenumth toggle widget in the choice layout
+** represented by choice. It simply turns the widget on, as if the
+** user had selected it, without calling any callbacks. It's used
+** to give feedback when reading from a script.
+*/
+
+void
+select_button(choice,togglenum)
+ ChoiceDesc *choice;
+ int togglenum;
+{
+ static Arg toggleargs[] = {
+ {XtNstate, (XtArgVal) True}
+ };
+
+ XtSetValues(choice->widgets[togglenum],toggleargs,XtNumber(toggleargs));
+}
+
+/* line_up_labels(descs,numdescs)
+** ------------------------------
+** descs represents a bunch of choice layouts (numdescs is the size of
+** descs). This function sets each label in descs to the same width,
+** thus making them line up nicely since they're all on the left margin.
+*/
+
+void
+line_up_labels(descs,numdescs)
+ ChoiceDesc *descs[];
+ int numdescs;
+{
+ int i; /* counter */
+ Dimension width; /* current width */
+ Dimension maxwidth = (Dimension) 0; /* max width found */
+
+ static Arg widthargs[] = {
+ {XtNwidth, (XtArgVal) NULL }
+ };
+
+ widthargs[0].value = (XtArgVal) &width;
+
+ /* Find the maximum width */
+ for (i = 0; i < numdescs; ++i) {
+ XtGetValues(descs[i]->label, widthargs, XtNumber(widthargs));
+ maxwidth = max(maxwidth,width);
+ }
+
+ /* Set all labels to that width */
+ widthargs[0].value = (XtArgVal) maxwidth;
+ for (i = 0; i < numdescs; ++i) {
+ XtSetValues(descs[i]->label, widthargs, XtNumber(widthargs));
+ }
+}
+
+/* choose_defaults(descs,numdescs)
+** -------------------------------
+** descs represents a bunch of choice layouts (numdescs is the size of
+** descs). This function goes through all of descs and selects the
+** appropriate toggle widget for each one. This includes calling
+** the callbacks associated with that widget.
+**
+** This function ends up initializing both the screen and the GC, and
+** ensures that they are consistent.
+*/
+
+void
+choose_defaults(descs,numdescs)
+ ChoiceDesc *descs[];
+ int numdescs;
+{
+ int i; /* which choice layout */
+ int j; /* which toggle within it */
+
+ for (i = 0; i < numdescs; ++i) {
+ j = 0;
+ if (i == 0)
+ j = 3;
+ select_button(descs[i],j);
+ XtCallCallbacks(descs[i]->widgets[j], XtNcallback, (caddr_t) NULL);
+ }
+}
+
+
+/* print_text_to_buffer(w,closure,call_data)
+** -----------------------------------------
+** This is also in the list of callbacks for the toggle buttons in a
+** choice widget. It sends the string contained in closure (which
+** was set way back in create_choice()) over to interpret(), which
+** decides what to do with it.
+*/
+
+/*ARGSUSED*/
+static void
+print_text_to_buffer(w,closure,call_data)
+ Widget w;
+ caddr_t closure; /* contains the string */
+ caddr_t call_data;
+{
+ interpret((char *) closure); /* Gee, that was easy */
+}
diff --git a/constants.h b/constants.h
new file mode 100644
index 0000000..495ff94
--- /dev/null
+++ b/constants.h
@@ -0,0 +1,76 @@
+/*
+** xgc
+**
+** constants.h
+**
+** Lots of constants which many files need.
+*/
+
+/* Find the max of two numbers */
+#ifndef max
+#define max(x,y) (((x)>(y))?(x):(y))
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MAXCHOICES 16 /* Max # of choices for any option */
+
+#define Black BlackPixel(X.dpy,0)
+#define White WhitePixel(X.dpy,0)
+
+#define CopyArea 0 /* different tests */
+#define CopyPlane 1
+#define PolyPoint 2
+#define PolyLine 3
+#define PolySegment 4
+#define PolyRectangle 5
+#define PolyArc 6
+#define FillPolygon 7
+#define PolyFillRect 8
+#define PolyFillArc 9
+#define PutImage 10
+#define GetImage 11
+#define PolyText8 12
+#define ImageText8 13
+#define PolyText16 14
+#define ImageText16 15
+
+#define CFunction 0 /* different GC things you can choose */
+#define CLinestyle 1
+#define CCapstyle 2
+#define CJoinstyle 3
+#define CFillstyle 4
+#define CFillrule 5
+#define CArcmode 6
+#define NUMCHOICES 7
+#define CTest 7
+
+#define TLineWidth 0 /* different editable text widgets */
+#define TFont 1
+#define TForeground 2
+#define TBackground 3
+#define NUMTEXTWIDGETS 4
+
+#define StartTimer 0 /* flags for timing tests */
+#define EndTimer 1
+#define start_timer() timer(StartTimer)
+#define end_timer() timer(EndTimer)
+
+/* the number of toggle widgets in various groups */
+#define NUM_TESTS 16
+#define NUM_FUNCTIONS 16
+#define NUM_LINESTYLES 3
+#define NUM_CAPSTYLES 4
+#define NUM_JOINSTYLES 3
+#define NUM_FILLSTYLES 4
+#define NUM_FILLRULES 2
+#define NUM_ARCMODES 2
+
+/* The number of bits in the dash description */
+#define DASHLENGTH 8
diff --git a/dashlist.c b/dashlist.c
new file mode 100644
index 0000000..ddfcf09
--- /dev/null
+++ b/dashlist.c
@@ -0,0 +1,189 @@
+/*
+** dashlist.c
+**
+** How to make a widget to choose a dashlist.
+**
+** NOTE: This file uses static variables. Therefore, trying to use these
+** functions to create more than one of these dashlist choice things
+** will fail in a big way.
+*/
+/* $XFree86: xc/programs/xgc/dashlist.c,v 1.3 2001/07/29 21:23:21 tsi Exp $ */
+
+#include <stdio.h>
+#include <X11/Xos.h>
+#include <stdlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Toggle.h>
+#include "xgc.h"
+
+static void change_dashlist(
+#if NeedFunctionPrototypes
+ Widget, caddr_t, caddr_t
+#endif
+);
+extern void interpret();
+
+extern XStuff X;
+
+static short dashlist = 240; /* in binary, becomes the dashlist
+ (240 = XXXX____) */
+static Widget *dashes; /* the toggle widgets */
+
+/* create_dashlist_choice(w)
+** -------------------------
+** Inside w (a form widget), creates a bunch of little toggle buttons
+** in a row, representing the dash list. There's also a label so
+** the user knows what it is.
+*/
+
+void
+create_dashlist_choice(w)
+ Widget w;
+{
+ /* callback list for the toggle widgets */
+ static XtCallbackRec callbacklist[] = {
+ {(XtCallbackProc) change_dashlist, NULL},
+ {NULL, NULL}
+ };
+
+ /* ArgList for the label */
+ static Arg labelargs[] = {
+ {XtNborderWidth, (XtArgVal) 0},
+ {XtNjustify, (XtArgVal) XtJustifyRight},
+ {XtNvertDistance, (XtArgVal) 4}
+ };
+
+ /* ArgList for the toggles */
+ static Arg dashargs[] = {
+ {XtNcallback, (XtArgVal) NULL},
+ {XtNhorizDistance, (XtArgVal) NULL},
+ {XtNfromHoriz, (XtArgVal) NULL},
+ {XtNwidth, (XtArgVal) 10},
+ {XtNheight, (XtArgVal) 10},
+ {XtNhighlightThickness, (XtArgVal) 1},
+ {XtNstate, (XtArgVal) False},
+ {XtNlabel, (XtArgVal) ""}
+ };
+
+ static Widget label; /* the label, of course */
+ static int *dashinfo; /* contains integers saying which bit
+ a particular button is; sent to
+ change_dashlist to tell it which
+ bit got changed */
+ int i; /* counter */
+
+ char name[11];
+
+ /* allocate space for stuff that we don't know the size of yet */
+ dashes = (Widget *) malloc(DASHLENGTH * sizeof(Widget));
+ dashinfo = (int *) malloc(DASHLENGTH * sizeof(int));
+
+ /* make the label widget */
+ label = XtCreateManagedWidget("dashlist",labelWidgetClass,w,
+ labelargs,XtNumber(labelargs));
+
+ dashargs[0].value = (XtArgVal) callbacklist;
+
+ for (i=0;i<DASHLENGTH;++i) { /* go through all the buttons */
+ if (i==0) { /* offset the first one from the label */
+ dashargs[1].value = (XtArgVal) 10;
+ dashargs[2].value = (XtArgVal) label;
+ }
+ else { /* put it directly to the right of the
+ last one, no space in between */
+ dashargs[1].value = (XtArgVal) -1;
+ dashargs[2].value = (XtArgVal) dashes[i-1];
+ }
+
+ /* set its original state depending on the state of that
+ ** bit of the dashlist */
+
+ if (dashlist&1<<i)
+ dashargs[6].value = (XtArgVal) True;
+ else
+ dashargs[6].value = (XtArgVal) False;
+
+ sprintf(name,"dashlist%d",i);
+
+ dashinfo[i] = i; /* which bit we're on; this is needed
+ in change_dashlist (the callback) */
+ callbacklist[0].closure = (caddr_t) &dashinfo[i];
+
+ dashes[i] = XtCreateManagedWidget(name,toggleWidgetClass,w,
+ dashargs,XtNumber(dashargs));
+ }
+}
+
+/* change_dashlist(w,closure,call_data)
+** ------------------------------------
+** This function is called when the user toggles a toggle widget. It
+** makes the appropriate change to the dashlist and sends it off
+** to interpret().
+** Funny args are because it's a callback.
+*/
+
+/*ARGSUSED*/
+static void
+change_dashlist(w,closure,call_data)
+ Widget w;
+ caddr_t closure;
+ caddr_t call_data;
+{
+ int num; /* what number button it is */
+ Boolean on; /* is it currently on or off? */
+
+ char buf[80]; /* string to send to interpret() */
+
+ static Arg args[] = {
+ {XtNstate, (XtArgVal) NULL}
+ };
+
+ /* set up ArgList so that 'on' will contain the state */
+ args[0].value = (XtArgVal) &on;
+
+ num = * (int *) closure; /* we put it here back in the last function */
+ XtGetValues(w,args,XtNumber(args));
+
+ /* modify the dashlist as appropriate. */
+ if (on) {
+ dashlist |= 1<<num;
+ }
+ else {
+ dashlist &= ~(1<<num);
+ }
+
+ /* now tell interpret() about it */
+ sprintf(buf,"dashlist %d\n",dashlist);
+ interpret(buf,FALSE);
+}
+
+/* update_dashlist(newdash)
+** ------------------------
+** Updates the display of the dashlist so that it corresponds to
+** newdash.
+*/
+
+void
+update_dashlist(newdash)
+ int newdash;
+{
+ int i; /* counter */
+ static Arg dashargs[] = { /* Arglist for setting toggle state */
+ {XtNstate, (XtArgVal) NULL}
+ };
+
+ /* first set the internal representation */
+ dashlist = newdash;
+
+ for (i = 0; i < DASHLENGTH; ++i) {
+ if (newdash & 1<<i) /* if it's set, make it look that way */
+ dashargs[0].value = (XtArgVal) True;
+ else
+ dashargs[0].value = (XtArgVal) False;
+
+ XtSetValues(dashes[i],dashargs,XtNumber(dashargs));
+ }
+}
diff --git a/getfile.c b/getfile.c
new file mode 100644
index 0000000..c72ad33
--- /dev/null
+++ b/getfile.c
@@ -0,0 +1,159 @@
+/*
+** getfilename.c
+**
+*/
+/* $XFree86: xc/programs/xgc/getfile.c,v 1.3 2000/02/17 14:00:35 dawes Exp $ */
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Shell.h>
+#include <X11/Xaw/AsciiText.h>
+#include <stdio.h>
+
+#include "xgc.h"
+
+extern XStuff X;
+extern Widget topform;
+
+static Widget popupshell = NULL; /* popup dialog box */
+Widget filename_text_widget; /* Widget containing the name of
+ the file the user has selected */
+extern XtAppContext appcontext;
+
+static void kill_popup_shell();
+
+void
+get_filename(success,failure)
+ void (*success)(); /* what function to call when a filename is
+ chosen */
+ void (*failure)(); /* what function to call when the user
+ cancels */
+{
+ static Widget popupform; /* form inside shell */
+ static Widget label; /* "Filename :" */
+ static Widget cancel; /* command, select to cancel */
+
+ Window dummy1, dummy2;
+ int x1,y1,x2,y2;
+ unsigned int mask;
+
+ /* The translation table for the text widget. Things such as <RETURN>
+ ** confirm the user's choice. Other keys which would move out of
+ ** the range of a one-line window are disabled. */
+
+ static const char *translationtable =
+ "Ctrl<Key>J: KillPopup() Done()\n\
+ Ctrl<Key>M: KillPopup() Done()\n\
+ <Key>Linefeed: KillPopup() Done()\n\
+ <Key>Return: KillPopup() Done()\n\
+ Ctrl<Key>O: Nothing()\n\
+ Meta<Key>I: Nothing()\n\
+ Ctrl<Key>N: Nothing()\n\
+ Ctrl<Key>P: Nothing()\n\
+ Ctrl<Key>Z: Nothing()\n\
+ Meta<Key>Z: Nothing()\n\
+ Ctrl<Key>V: Nothing()\n\
+ Meta<Key>V: Nothing()";
+
+ /* What the actions in the translation table correspond to. */
+
+ static XtActionsRec actiontable[] = {
+ {"KillPopup", (XtActionProc) kill_popup_shell},
+ {"Done", NULL},
+ {"Nothing", NULL}
+ };
+
+ static Arg popupshellargs[] = { /* Where to put the popup shell. */
+ {XtNx, (XtArgVal) NULL},
+ {XtNy, (XtArgVal) NULL}
+ };
+
+ static Arg labelargs[] = { /* ArgList for the label */
+ {XtNborderWidth, (XtArgVal) 0},
+ {XtNjustify, (XtArgVal) XtJustifyRight}
+ };
+
+ static Arg textargs[] = { /* ArgList for the text widget */
+ {XtNeditType, (XtArgVal) XawtextEdit},
+ {XtNwidth, (XtArgVal) 200},
+ {XtNhorizDistance, (XtArgVal) 10},
+ {XtNfromHoriz, (XtArgVal) NULL},
+ };
+
+ static Arg cancelargs[] = { /* ArgList for the cancel button */
+ {XtNfromHoriz, (XtArgVal) NULL},
+ {XtNcallback, (XtArgVal) NULL}
+ };
+
+ /* Procedures to call when the user selects 'cancel' */
+ static XtCallbackRec cancelcallbacklist[] = {
+ {(XtCallbackProc) kill_popup_shell, NULL},
+ {NULL, NULL},
+ {NULL, NULL}
+ };
+
+ if (popupshell != NULL) {
+ XtPopup(popupshell,XtGrabExclusive);
+ return;
+ }
+
+ /* Find out where the pointer is, so we can put the popup window there */
+
+ (void) XQueryPointer(X.dpy,XtWindow(topform),&dummy1,&dummy2,&x1,&y1,
+ &x2,&y2,&mask);
+
+ popupshellargs[0].value = (XtArgVal) x2;
+ popupshellargs[1].value = (XtArgVal) y2;
+
+ popupshell = XtCreatePopupShell("popup",overrideShellWidgetClass,
+ topform,popupshellargs,XtNumber(popupshellargs));
+
+ popupform = XtCreateManagedWidget("form",formWidgetClass,popupshell,
+ NULL, 0);
+
+ label = XtCreateManagedWidget("Filename: ",labelWidgetClass,popupform,
+ labelargs,XtNumber(labelargs));
+
+ textargs[3].value = (XtArgVal) label;
+
+ filename_text_widget = XtCreateManagedWidget("text",asciiTextWidgetClass,
+ popupform,
+ textargs,XtNumber(textargs));
+
+ /* Complete the action table. We have to do it here because success
+ ** isn't known at compile time. */
+
+ actiontable[1].proc = (XtActionProc) success;
+
+ /* Register actions, translations, callbacks */
+
+ XtAppAddActions(appcontext,actiontable,XtNumber(actiontable));
+ XtOverrideTranslations(filename_text_widget,
+ XtParseTranslationTable(translationtable));
+ cancelcallbacklist[1].callback = (XtCallbackProc) failure;
+
+ cancelargs[0].value = (XtArgVal) filename_text_widget;
+ cancelargs[1].value = (XtArgVal) cancelcallbacklist;
+
+ cancel = XtCreateManagedWidget("Cancel",commandWidgetClass,popupform,
+ cancelargs,XtNumber(cancelargs));
+
+ /* Bring up the popup. When the user presses cancel or the return key,
+ ** the function kill_popup_shell (below) will be called to remove it. */
+
+ XtPopup(popupshell,XtGrabExclusive);
+}
+
+/* kill_popup_shell()
+** ------------------
+** Remove the popup window that get_filename popped up.
+*/
+
+static void
+kill_popup_shell()
+{
+ XtPopdown(popupshell);
+}
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 <stdio.h>
+#include <X11/X.h>
+#include "constants.h"
+
+extern int yylineno;
+extern FILE *yyin;
+int yylex();
+void yyerror();
+
+extern void GC_change_function();
+extern void GC_change_foreground();
+extern void GC_change_background();
+extern void GC_change_linewidth();
+extern void GC_change_linestyle();
+extern void GC_change_capstyle();
+extern void GC_change_joinstyle();
+extern void GC_change_fillstyle();
+extern void GC_change_fillrule();
+extern void GC_change_arcmode();
+extern void GC_change_dashlist();
+extern void GC_change_planemask();
+extern void GC_change_font();
+extern void change_test();
+extern void change_percent();
+extern void run_test();
+%}
+
+%union
+{
+ int num;
+ char *ptr;
+};
+
+%token <ptr> STRING
+%token <num> NUMBER
+%token <num> RUN
+%token <num> FUNCTION FUNCTIONTYPE
+%token <num> TEST TESTTYPE
+%token <num> LINESTYLE LINESTYLETYPE
+%token <num> CAPSTYLE CAPSTYLETYPE
+%token <num> JOINSTYLE JOINSTYLETYPE
+%token <num> ROUND SOLID
+%token <num> FILLSTYLE FILLSTYLETYPE
+%token <num> FILLRULE FILLRULETYPE
+%token <num> ARCMODE ARCMODETYPE
+%token <num> FOREGROUND BACKGROUND LINEWIDTH PLANEMASK DASHLIST PERCENT
+%token <num> FONT
+
+%%
+
+all : stmts
+ ;
+
+stmts : /* empty */
+ | stmts '\n'
+ | stmts stmt '\n'
+ ;
+
+stmt : error
+ | RUN
+ { run_test(); }
+ | TEST TESTTYPE
+ { change_test ($2, TRUE); }
+ | FUNCTION FUNCTIONTYPE
+ { GC_change_function ($2, TRUE); }
+ | LINESTYLE LINESTYLETYPE
+ { GC_change_linestyle ($2, TRUE); }
+ | LINESTYLE SOLID
+ { GC_change_linestyle (LineSolid, TRUE); }
+ | CAPSTYLE CAPSTYLETYPE
+ { GC_change_capstyle ($2, TRUE); }
+ | CAPSTYLE ROUND
+ { GC_change_capstyle (CapRound, TRUE); }
+ | JOINSTYLE JOINSTYLETYPE
+ { GC_change_joinstyle ($2, TRUE); }
+ | JOINSTYLE ROUND
+ { GC_change_joinstyle (JoinRound, TRUE); }
+ | FILLSTYLE FILLSTYLETYPE
+ { GC_change_fillstyle ($2, TRUE); }
+ | FILLSTYLE SOLID
+ { GC_change_fillstyle (FillSolid, TRUE); }
+ | FILLRULE FILLRULETYPE
+ { GC_change_fillrule ($2, TRUE); }
+ | ARCMODE ARCMODETYPE
+ { GC_change_arcmode ($2, TRUE); }
+ | FOREGROUND NUMBER
+ { GC_change_foreground ($2, TRUE); }
+ | BACKGROUND NUMBER
+ { GC_change_background ($2, TRUE); }
+ | LINEWIDTH NUMBER
+ { GC_change_linewidth ($2, TRUE); }
+ | PLANEMASK NUMBER
+ { GC_change_planemask ($2, TRUE); }
+ | DASHLIST NUMBER
+ { GC_change_dashlist ($2, TRUE); }
+ | FONT STRING
+ { GC_change_font ($2, TRUE); }
+ | PERCENT NUMBER
+ { change_percent ($2, TRUE); }
+ ;
+
+%%
+void
+yyerror(s)
+ const char *s;
+{
+ fprintf(stderr, "xgc: syntax error, line %d\n", yylineno);
+}
diff --git a/interpret.c b/interpret.c
new file mode 100644
index 0000000..d12922b
--- /dev/null
+++ b/interpret.c
@@ -0,0 +1,429 @@
+/*
+** interpret.c
+**
+** interprets and executes lines in the Xgc syntax.
+*/
+/* $XFree86: xc/programs/xgc/interpret.c,v 1.4 2002/01/07 20:38:30 dawes Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include "xgc.h"
+#include "tile"
+
+void change_text();
+void GC_change_function();
+void GC_change_foreground();
+void GC_change_background();
+void GC_change_linewidth();
+void GC_change_linestyle();
+void GC_change_capstyle();
+void GC_change_joinstyle();
+void GC_change_fillstyle();
+void GC_change_fillrule();
+void GC_change_arcmode();
+void GC_change_dashlist();
+void GC_change_planemask();
+void GC_change_font();
+void change_test();
+void change_percent();
+
+extern void update_dashlist();
+extern void update_planemask();
+extern void update_slider();
+extern void select_button();
+extern void run_test();
+extern void print_if_recording();
+
+extern XgcStuff TestStuff;
+extern XgcStuff FunctionStuff;
+extern XgcStuff LinestyleStuff;
+extern XgcStuff CapstyleStuff;
+extern XgcStuff JoinstyleStuff;
+extern XgcStuff FillstyleStuff;
+extern XgcStuff FillruleStuff;
+extern XgcStuff ArcmodeStuff;
+
+extern XStuff X;
+extern ChoiceDesc *GCdescs[];
+extern ChoiceDesc *testchoicedesc;
+extern Widget test;
+extern Widget GCform;
+extern Widget foregroundtext;
+extern Widget backgroundtext;
+extern Widget linewidthtext;
+extern Widget fonttext;
+extern Widget dashlistchoice;
+extern Widget planemaskchoice;
+extern Widget testchoiceform;
+
+extern int fildes[2];
+extern FILE *outend;
+extern FILE *yyin;
+
+/* interpret(string)
+** -----------------
+** Takes string, which is a line written in the xgc syntax, figures
+** out what it means, and passes the buck to the right procedure.
+** That procedure gets called with feedback set to FALSE; interpret()
+** is only called if the user is selecting things interactively.
+**
+** This procedure will go away when I can figure out how to make yacc
+** and lex read from strings as well as files.
+*/
+
+void
+interpret(string)
+ const char *string;
+{
+ char word1[20], word2[80];
+ int i;
+
+ sscanf(string,"%s",word1);
+ if (!strcmp(word1,"run")) run_test();
+
+ else {
+ sscanf(string,"%s %s",word1,word2);
+ print_if_recording(string);
+
+ /* So word1 is the first word on the line and word2 is the second.
+ Now the fun begins... */
+
+ if (!strcmp(word1,TestStuff.choice.text)) {
+ for (i=0;i<NUM_TESTS;++i) {
+ if (!strcmp(word2,(TestStuff.data)[i].text)) {
+ change_test((TestStuff.data)[i].code,FALSE);
+ break;
+ }
+ }
+ }
+ else if (!strcmp(word1,FunctionStuff.choice.text)) {
+ for (i=0;i<NUM_FUNCTIONS;++i) {
+ if (!strcmp(word2,(FunctionStuff.data)[i].text)) {
+ GC_change_function((FunctionStuff.data)[i].code,FALSE);
+ break;
+ }
+ }
+ }
+ else if (!strcmp(word1,LinestyleStuff.choice.text)) {
+ for (i=0;i<NUM_LINESTYLES;++i) {
+ if (!strcmp(word2,(LinestyleStuff.data)[i].text)) {
+ GC_change_linestyle((LinestyleStuff.data)[i].code,FALSE);
+ break;
+ }
+ }
+ }
+ else if (!strcmp(word1,"linewidth"))
+ GC_change_linewidth(atoi(word2),FALSE);
+ else if (!strcmp(word1,CapstyleStuff.choice.text)) {
+ for (i=0;i<NUM_CAPSTYLES;++i) {
+ if (!strcmp(word2,(CapstyleStuff.data)[i].text)) {
+ GC_change_capstyle((CapstyleStuff.data)[i].code,FALSE);
+ break;
+ }
+ }
+ }
+ else if (!strcmp(word1,JoinstyleStuff.choice.text)) {
+ for (i=0;i<NUM_JOINSTYLES;++i) {
+ if (!strcmp(word2,(JoinstyleStuff.data)[i].text)) {
+ GC_change_joinstyle((JoinstyleStuff.data)[i].code,FALSE);
+ break;
+ }
+ }
+ }
+ else if (!strcmp(word1,FillstyleStuff.choice.text)) {
+ for (i=0;i<NUM_FILLSTYLES;++i) {
+ if (!strcmp(word2,(FillstyleStuff.data)[i].text)) {
+ GC_change_fillstyle((FillstyleStuff.data)[i].code,FALSE);
+ break;
+ }
+ }
+ }
+ else if (!strcmp(word1,FillruleStuff.choice.text)) {
+ for (i=0;i<NUM_FILLRULES;++i) {
+ if (!strcmp(word2,(FillruleStuff.data)[i].text)) {
+ GC_change_fillrule((FillruleStuff.data)[i].code,FALSE);
+ break;
+ }
+ }
+ }
+ else if (!strcmp(word1,ArcmodeStuff.choice.text)) {
+ for (i=0;i<NUM_ARCMODES;++i) {
+ if (!strcmp(word2,(ArcmodeStuff.data)[i].text)) {
+ GC_change_arcmode((ArcmodeStuff.data)[i].code,FALSE);
+ break;
+ }
+ }
+ }
+ else if (!strcmp(word1,"planemask"))
+ GC_change_planemask((unsigned long) atoi(word2),FALSE);
+ else if (!strcmp(word1,"dashlist"))
+ GC_change_dashlist(atoi(word2),FALSE);
+ else if (!strcmp(word1,"font"))
+ GC_change_font(word2,FALSE);
+ else if (!strcmp(word1,"foreground"))
+ GC_change_foreground((unsigned long) atoi(word2),FALSE);
+ else if (!strcmp(word1,"background"))
+ GC_change_background((unsigned long) atoi(word2),FALSE);
+ else if (!strcmp(word1,"percent"))
+ change_percent(atoi(word2), FALSE);
+ else fprintf(stderr,"Ack... %s %s\n",word1,word2);
+ }
+}
+
+#ifdef notdef
+void
+interpret(instring)
+ const char *instring;
+{
+ FILE *inend;
+
+ print_if_recording(instring);
+ yyin = outend;
+ inend = fdopen(fildes[1],"w");
+ fprintf(inend,"%s",instring);
+ fclose(inend);
+ yyparse();
+}
+#endif
+
+#define select_correct_button(which,number) \
+ select_button(GCdescs[(which)],(number));
+
+/* GC_change_blahzee(foo,feedback)
+** ---------------------
+** Changes the blahzee field in xgc's GC to foo. If feedback is TRUE,
+** changes the display to reflect this (makes it look like the user
+** selected the button, or typed in the text, or whatever).
+*/
+
+void
+GC_change_function(function,feedback)
+ int function;
+ Boolean feedback;
+{
+ XSetFunction(X.dpy,X.gc,function);
+ X.gcv.function = function;
+ if (feedback) select_correct_button(CFunction,function);
+}
+
+void
+GC_change_foreground(foreground,feedback)
+ unsigned long foreground;
+ Boolean feedback;
+{
+ char text[40];
+
+ XSetForeground(X.dpy,X.miscgc,foreground);
+ XCopyPlane(X.dpy,X.stipple,X.tile,X.miscgc,0,0,tile_width,tile_height,0,0,1);
+ XSetForeground(X.dpy,X.gc,foreground);
+ X.gcv.foreground = foreground;
+ XSetTile(X.dpy,X.gc,X.tile);
+ XSetTile(X.dpy,X.miscgc,X.tile);
+ if (feedback) {
+ sprintf(text,"%lu",foreground);
+ change_text(foregroundtext,text);
+ }
+}
+
+void
+GC_change_background(background,feedback)
+ unsigned long background;
+ Boolean feedback;
+{
+ char text[40];
+
+ XSetBackground(X.dpy,X.miscgc,background);
+ XCopyPlane(X.dpy,X.stipple,X.tile,X.miscgc,0,0,tile_width,tile_height,0,0,1);
+ XSetBackground(X.dpy,X.gc,background);
+ X.gcv.background = background;
+ XSetTile(X.dpy,X.gc,X.tile);
+ XSetTile(X.dpy,X.miscgc,X.tile);
+
+ /* Update the background of the test window NOW. */
+
+ XSetWindowBackground(X.dpy,XtWindow(test),background);
+ XClearWindow(X.dpy,XtWindow(test));
+
+ if (feedback) {
+ sprintf(text,"%lu",background);
+ change_text(backgroundtext,text);
+ }
+}
+
+void
+GC_change_linewidth(linewidth,feedback)
+ int linewidth;
+ Boolean feedback;
+{
+ char text[40];
+
+ X.gcv.line_width = linewidth;
+ XChangeGC(X.dpy,X.gc,GCLineWidth,&X.gcv);
+ if (feedback) {
+ sprintf(text,"%d",linewidth);
+ change_text(linewidthtext,text);
+ }
+}
+
+void
+GC_change_linestyle(linestyle,feedback)
+ int linestyle;
+ Boolean feedback;
+{
+ X.gcv.line_style = linestyle;
+ XChangeGC(X.dpy,X.gc,GCLineStyle,&X.gcv);
+ if (feedback) select_correct_button(CLinestyle,linestyle);
+}
+
+void
+GC_change_capstyle(capstyle,feedback)
+ int capstyle;
+ Boolean feedback;
+{
+ X.gcv.cap_style = capstyle;
+ XChangeGC(X.dpy,X.gc,GCCapStyle,&X.gcv);
+ if (feedback) select_correct_button(CCapstyle,capstyle);
+}
+
+void
+GC_change_joinstyle(joinstyle,feedback)
+ int joinstyle;
+ Boolean feedback;
+{
+ X.gcv.join_style = joinstyle;
+ XChangeGC(X.dpy,X.gc,GCJoinStyle,&X.gcv);
+ if (feedback) select_correct_button(CJoinstyle,joinstyle);
+}
+
+void
+GC_change_fillstyle(fillstyle,feedback)
+ int fillstyle;
+ Boolean feedback;
+{
+ XSetFillStyle(X.dpy,X.gc,fillstyle);
+ X.gcv.fill_style = fillstyle;
+ if (feedback) select_correct_button(CFillstyle,fillstyle);
+}
+
+void
+GC_change_fillrule(fillrule,feedback)
+ int fillrule;
+ Boolean feedback;
+{
+ XSetFillRule(X.dpy,X.gc,fillrule);
+ X.gcv.fill_rule = fillrule;
+ if (feedback) select_correct_button(CFillrule,fillrule);
+}
+
+void
+GC_change_arcmode(arcmode,feedback)
+ int arcmode;
+ Boolean feedback;
+{
+ XSetArcMode(X.dpy,X.gc,arcmode);
+ X.gcv.arc_mode = arcmode;
+ if (feedback) select_correct_button(CArcmode,arcmode);
+}
+
+/* GC_change_dashlist(dashlist)
+** ----------------------------
+** Now this one's a bit tricky. dashlist gets passed in as an int, but we
+** want to change it to an array of chars, like the GC likes it.
+** For example:
+** 119 => XXX_XXX_ => [3,1,3,1]
+*/
+
+void
+GC_change_dashlist(dashlist,feedback)
+ int dashlist;
+ Boolean feedback;
+{
+ char dasharray[DASHLENGTH]; /* what we're gonna pass to XSetDashes */
+ int dashnumber = 0; /* which element of dasharray we're currently
+ modifying */
+ int i; /* which bit of the dashlist we're on */
+ int state = 1; /* whether the list bit we checked was
+ on (1) or off (0) */
+
+ /* Initialize the dasharray */
+
+ for (i = 0; i < DASHLENGTH; ++i) dasharray[i] = 0;
+
+ if (dashlist == 0) return; /* having no dashes at all is bogus */
+
+ /* XSetDashes expects the dashlist to start with an on bit, so if it
+ ** doesn't, we keep on rotating it until it does */
+
+ while (!(dashlist&1)) dashlist /= 2;
+
+ /* Go through all the bits in dashlist, and update the dasharray
+ ** accordingly */
+
+ for (i = 0; i < DASHLENGTH; ++i) {
+ /* the following if statements checks to see if the bit we're looking
+ ** at as the same on or offness as the one before it (state). If
+ ** so, we increment the length of the current dash. */
+
+ if (((dashlist&1<<i) && state) || (!(dashlist&1<<i) && !state))
+ ++dasharray[dashnumber];
+ else {
+ state = state^1; /* reverse the state */
+ ++dasharray[++dashnumber]; /* start a new dash */
+ }
+ }
+
+ XSetDashes(X.dpy,X.gc,0,dasharray,dashnumber+1);
+ X.gcv.dashes = dashlist;
+
+ if (feedback) update_dashlist(dashlist);
+}
+
+void
+GC_change_planemask(planemask,feedback)
+ unsigned long planemask;
+ Boolean feedback;
+{
+ XSetPlaneMask(X.dpy,X.gc,planemask);
+ X.gcv.plane_mask = planemask;
+ if (feedback) update_planemask((long)planemask);
+}
+
+void
+change_test(test,feedback)
+ int test;
+ Boolean feedback;
+{
+ X.test = test;
+ if (feedback) select_button(testchoicedesc,test);
+}
+
+void
+GC_change_font(str,feedback)
+ const char *str;
+ Boolean feedback;
+{
+ int num_fonts; /* number of fonts that match the string */
+
+ XListFonts(X.dpy,str,1,&num_fonts); /* see if the font exists */
+
+ if (num_fonts) {
+ XSetFont(X.dpy,X.gc,XLoadFont(X.dpy,str));
+ if (feedback) change_text(fonttext,str);
+ }
+}
+
+void
+change_percent(percent,feedback)
+ int percent;
+ Boolean feedback;
+{
+ /* Make sure that percent is valid */
+
+ if (percent < 1 || percent > 100) return;
+
+ X.percent = (float) percent / 100.0;
+
+ if (feedback) update_slider(percent);
+}
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 <X11/X.h>
+#include "gram.h"
+#include "constants.h"
+#if defined(FLEX_SCANNER) && !defined(YY_FLEX_LEX_COMPAT) && !defined(__UNIXOS2__)
+int yylineno = 0;
+#endif
+%}
+
+%p 4000
+%a 3000
+
+number [0-9]+
+word [^\n\t ]+
+string \"([^"]|\\.)*\"
+
+%%
+
+[Rr]un { return (RUN); }
+
+[Ff]unction { return (FUNCTION); }
+[Cc]lear { yylval.num = GXclear;
+ return (FUNCTIONTYPE); }
+[Aa]nd { yylval.num = GXand;
+ return (FUNCTIONTYPE); }
+[Aa]ndReverse { yylval.num = GXandReverse;
+ return (FUNCTIONTYPE); }
+[Cc]opy { yylval.num = GXcopy;
+ return (FUNCTIONTYPE); }
+[Aa]ndInverted { yylval.num = GXandInverted;
+ return (FUNCTIONTYPE); }
+[Nn]oop { yylval.num = GXnoop;
+ return (FUNCTIONTYPE); }
+[Xx]or { yylval.num = GXxor;
+ return (FUNCTIONTYPE); }
+[Oo]r { yylval.num = GXor;
+ return (FUNCTIONTYPE); }
+[Nn]or { yylval.num = GXnor;
+ return (FUNCTIONTYPE); }
+[Ee]quiv { yylval.num = GXequiv;
+ return (FUNCTIONTYPE); }
+[Ii]nvert { yylval.num = GXinvert;
+ return (FUNCTIONTYPE); }
+[Oo]rReverse { yylval.num = GXorReverse;
+ return (FUNCTIONTYPE); }
+[Cc]opyInverted { yylval.num = GXcopyInverted;
+ return (FUNCTIONTYPE); }
+[Oo]rInverted { yylval.num = GXorInverted;
+ return (FUNCTIONTYPE); }
+[Nn]and { yylval.num = GXnand;
+ return (FUNCTIONTYPE); }
+[Ss]et { yylval.num = GXset;
+ return (FUNCTIONTYPE); }
+
+[Tt]est { return (TEST); }
+CopyArea { yylval.num = CopyArea;
+ return (TESTTYPE); }
+CopyPlane { yylval.num = CopyPlane;
+ return (TESTTYPE); }
+PolyPoint { yylval.num = PolyPoint;
+ return (TESTTYPE); }
+PolyLine { yylval.num = PolyLine;
+ return (TESTTYPE); }
+PolySegment { yylval.num = PolySegment;
+ return (TESTTYPE); }
+PolyRectangle { yylval.num = PolyRectangle;
+ return (TESTTYPE); }
+PolyArc { yylval.num = PolyArc;
+ return (TESTTYPE); }
+FillPolygon { yylval.num = FillPolygon;
+ return (TESTTYPE); }
+PolyFillRect { yylval.num = PolyFillRect;
+ return (TESTTYPE); }
+PolyFillArc { yylval.num = PolyFillArc;
+ return (TESTTYPE); }
+PutImage { yylval.num = PutImage;
+ return (TESTTYPE); }
+GetImage { yylval.num = GetImage;
+ return (TESTTYPE); }
+PolyText8 { yylval.num = PolyText8;
+ return (TESTTYPE); }
+ImageText8 { yylval.num = ImageText8;
+ return (TESTTYPE); }
+PolyText16 { yylval.num = PolyText16;
+ return (TESTTYPE); }
+ImageText16 { yylval.num = ImageText16;
+ return (TESTTYPE); }
+
+[Ll]inestyle { return (LINESTYLE); }
+OnOffDash { yylval.num = LineOnOffDash;
+ return (LINESTYLETYPE); }
+DoubleDash { yylval.num = LineDoubleDash;
+ return (LINESTYLETYPE); }
+
+[Cc]apstyle { return (CAPSTYLE); }
+NotLast { yylval.num = CapNotLast;
+ return (CAPSTYLETYPE); }
+Butt { yylval.num = CapButt;
+ return (CAPSTYLETYPE); }
+Projecting { yylval.num = CapProjecting;
+ return (CAPSTYLETYPE); }
+
+[Jj]oinstyle { return (JOINSTYLE); }
+Miter { yylval.num = JoinMiter;
+ return (JOINSTYLETYPE); }
+Bevel { yylval.num = JoinBevel;
+ return (JOINSTYLETYPE); }
+
+Round { return (ROUND); }
+
+[Ff]illstyle { return (FILLSTYLE); }
+Tiled { yylval.num = FillTiled;
+ return (FILLSTYLETYPE); }
+Stippled { yylval.num = FillStippled;
+ return (FILLSTYLETYPE); }
+OpaqueStippled { yylval.num = FillOpaqueStippled;
+ return (FILLSTYLETYPE); }
+
+Solid { return (SOLID); }
+
+[Ff]illrule { return (FILLRULE); }
+EvenOdd { yylval.num = EvenOddRule;
+ return (FILLRULETYPE); }
+Winding { yylval.num = WindingRule;
+ return (FILLRULETYPE); }
+
+[Aa]rcmode { return (ARCMODE); }
+Chord { yylval.num = ArcChord;
+ return (ARCMODETYPE); }
+PieSlice { yylval.num = ArcPieSlice;
+ return (ARCMODETYPE); }
+
+[Ff]oreground { return (FOREGROUND); }
+[Bb]ackground { return (BACKGROUND); }
+[Ll]inewidth { return (LINEWIDTH); }
+[Pp]lanemask { return (PLANEMASK); }
+[Dd]ashlist { return (DASHLIST); }
+[Ff]ont { return (FONT); }
+[Pp]ercent { return (PERCENT); }
+
+{number} { (void) sscanf ((char *)yytext, "%d", &yylval.num);
+ return (NUMBER); }
+{string} { yylval.ptr = (char *) yytext;
+ return (STRING); }
+\#[^\n]*\n { ; }
+[\t ] { ; }
+\n { return ('\n'); }
+
+{word} { yylval.ptr = (char *) yytext;
+ return (STRING); }
+
+. { fprintf(stderr,
+ "xgc: bad character `%s', line %d\n",
+ yytext, yylineno); }
+
+%%
+
+#ifndef yywrap
+int yywrap() { return (1); }
+#endif
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 <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/AsciiText.h>
+#include <X11/Shell.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "xgc.h"
+#define DEFINE_TILE
+#include "tile"
+#include "main.h"
+
+static void fill_up_commandform();
+extern void run_test();
+static void quit();
+static void quitAction();
+static void clear_test_window();
+static void clear_result_window();
+extern void start_playback();
+extern void read_from_keyboard();
+extern void toggle_recordbutton();
+static void set_foreground_and_background();
+extern ChoiceDesc *create_choice();
+extern void choose_defaults();
+extern void line_up_labels();
+extern Widget create_text_choice();
+extern void create_planemask_choice();
+extern void create_dashlist_choice();
+extern void create_testfrac_choice();
+extern void GC_change_foreground();
+extern void GC_change_background();
+extern void GC_change_font();
+extern void close_file_if_recording();
+extern void set_text (Widget ww, char *string);
+
+#ifdef notdef
+int fildes[2]; /* for pipe */
+FILE *outend;
+#endif
+
+XStuff X; /* GC stuff plus some global variables */
+Boolean recording = FALSE; /* Whether we're recording into a file */
+XtAppContext appcontext; /* To make Xt happy */
+static Atom wm_delete_window;
+static XtActionsRec actions[] = {
+ {"quit", quitAction}
+};
+
+static Widget bigdaddy; /* the top level widget */
+ Widget topform; /* form surrounding the whole thing */
+ Widget GCform; /* form in which you choose the GC */
+static Widget Testform; /* form in which you choose the test */
+ Widget testchoiceform; /* form inside that */
+ ChoiceDesc *testchoicedesc; /* record of what widgets are in the
+ test choice form */
+static Widget commandform; /* form with run, quit, clear, etc. */
+ Widget test; /* where the test is run */
+ Widget result; /* where the results are displayed */
+static Widget runbutton; /* command for running */
+static Widget quitbutton; /* command for quitting */
+static Widget clearbutton; /* command for clearing the test window */
+ Widget recordbutton; /* start/stop recording */
+static Widget playbackbutton; /* playback from file */
+static Widget keyinputbutton; /* start reading from keyboard */
+static Widget GCchoices[NUMCHOICES]; /* all the forms that contain stuff
+ for changing GC's*/
+ ChoiceDesc *GCdescs[NUMCHOICES]; /* record of the widgets inside
+ the choice widgets */
+ Widget planemaskchoice; /* form for choosing the plane mask */
+ Widget dashlistchoice; /* form for choosing the dash list */
+static Widget linewidthchoice; /* form for choosing line width */
+ Widget linewidthtext; /* text widget within that */
+static Widget fontchoice; /* form for choosing the font */
+ Widget fonttext; /* text widget within that */
+static Widget foregroundchoice; /* form for choosing foreground */
+ Widget foregroundtext; /* text widget within that */
+static Widget backgroundchoice; /* form for choosing background */
+ Widget backgroundtext; /* text widget within that */
+static Widget percentchoice; /* form for choosing percentage of test */
+
+/* main(argc.argv)
+** ---------------
+** Initializes the toolkit, initializes data, puts up the widgets,
+** starts the event loop.
+*/
+
+int
+main(argc,argv)
+ int argc;
+ char **argv;
+{
+ static Arg shellargs[] = {
+ {XtNinput, (XtArgVal) True}
+ };
+
+ static Arg testformargs[] = {
+ {XtNfromVert, (XtArgVal) NULL} /* put it under GCform */
+ };
+
+ static Arg commandformargs[] = {
+ {XtNfromVert, (XtArgVal) NULL}, /* put it under GCform */
+ {XtNfromHoriz, (XtArgVal) NULL} /* and to the right of Testform */
+ };
+
+ static Arg testargs[] = {
+ {XtNheight, (XtArgVal) 400},
+ {XtNwidth, (XtArgVal) 400},
+ {XtNfromHoriz, (XtArgVal) NULL} /* put it to the right of GCform */
+ };
+
+ static Arg resultargs[] = {
+ {XtNheight, (XtArgVal) 50},
+ {XtNwidth, (XtArgVal) 400},
+ {XtNfromHoriz, (XtArgVal) NULL}, /* put it to the right of GCform */
+ {XtNfromVert, (XtArgVal) NULL} /* and under test */
+ };
+
+ static Arg gcchoiceargs[] = {
+ {XtNfromVert, (XtArgVal) NULL}, /* put it under the one above it */
+ {XtNfromHoriz, (XtArgVal) NULL}, /* and next to that one */
+ {XtNborderWidth, (XtArgVal) 0} /* no ugly borders */
+ };
+
+ static Arg testchoiceargs[] = {
+ {XtNborderWidth, (XtArgVal) 0}
+ };
+
+ int i; /* counter */
+
+ /* Open the pipe */
+
+#ifdef notdef
+ pipe(fildes);
+ outend = fdopen(fildes[0],"r");
+#endif
+
+ /* Initialize toolkit stuff */
+
+ XtSetLanguageProc(NULL, (XtLanguageProc) NULL, NULL);
+
+ bigdaddy = XtAppInitialize(&appcontext, "Xgc", (XrmOptionDescList) NULL,
+ (Cardinal) 0, &argc, argv, (String *) NULL,
+ shellargs, XtNumber(shellargs));
+ X.dpy = XtDisplay(bigdaddy);
+ XtAppAddActions(appcontext, actions, XtNumber(actions));
+ XtOverrideTranslations
+ (bigdaddy, XtParseTranslationTable("<Message>WM_PROTOCOLS: quit()"));
+
+ /* Initialize GC stuff */
+
+ X.scr = DefaultScreenOfDisplay(X.dpy);
+ X.gc = XCreateGC(X.dpy,RootWindowOfScreen(X.scr),0,(XGCValues *) NULL);
+ X.miscgc = XCreateGC(X.dpy,RootWindowOfScreen(X.scr),0,(XGCValues *) NULL);
+
+ /* Find out what the foreground & background are, and update the GC
+ ** accordingly */
+
+ set_foreground_and_background();
+
+ topform = XtCreateManagedWidget("topform",formWidgetClass,bigdaddy,
+ NULL,0);
+
+ GCform = XtCreateManagedWidget("GCform",formWidgetClass,topform,
+ NULL,0);
+
+ /* create all the GCchoices forms */
+
+ for (i=0;i<NUMCHOICES;++i) {
+ if (i==0) /* on top */
+ gcchoiceargs[0].value = (XtArgVal) NULL;
+ else /* under the last one */
+ gcchoiceargs[0].value = (XtArgVal) GCchoices[i-1];
+
+ GCchoices[i] = XtCreateManagedWidget(Everything[i]->choice.text,
+ formWidgetClass,GCform,
+ gcchoiceargs,XtNumber(gcchoiceargs));
+
+ /* now fill up that form */
+ GCdescs[i] = create_choice(GCchoices[i],Everything[i]);
+ }
+
+ /* put the planemask choice under the bottom GC choice */
+ gcchoiceargs[0].value = (XtArgVal) GCchoices[NUMCHOICES-1];
+ planemaskchoice = XtCreateManagedWidget("planemask",formWidgetClass,GCform,
+ gcchoiceargs,XtNumber(gcchoiceargs));
+ /* fill it up */
+ create_planemask_choice(planemaskchoice);
+
+ /* put the dashlist choice under the planemask choice */
+ gcchoiceargs[0].value = (XtArgVal) planemaskchoice;
+ dashlistchoice = XtCreateManagedWidget("dashlist",formWidgetClass,GCform,
+ gcchoiceargs,XtNumber(gcchoiceargs));
+ /* fill it up */
+ create_dashlist_choice(dashlistchoice);
+
+ /* put the linewidth choice under the dashlist choice */
+ gcchoiceargs[0].value = (XtArgVal) dashlistchoice;
+ linewidthchoice = XtCreateManagedWidget("linewidth",formWidgetClass,GCform,
+ gcchoiceargs,XtNumber(gcchoiceargs));
+ /* fill it up */
+ linewidthtext = create_text_choice(linewidthchoice,TLineWidth,2,30);
+
+ /* put the font choice under the linewidth choice */
+ gcchoiceargs[0].value = (XtArgVal) linewidthchoice;
+ fontchoice = XtCreateManagedWidget("font",formWidgetClass,GCform,
+ gcchoiceargs,XtNumber(gcchoiceargs));
+ /* fill it up */
+ fonttext = create_text_choice(fontchoice,TFont,80,300);
+
+ gcchoiceargs[0].value = (XtArgVal) fontchoice;
+ foregroundchoice = XtCreateManagedWidget("foreground",formWidgetClass,GCform,
+ gcchoiceargs,XtNumber(gcchoiceargs));
+ foregroundtext = create_text_choice(foregroundchoice,TForeground,4,50);
+
+ gcchoiceargs[1].value = (XtArgVal) foregroundchoice;
+ backgroundchoice = XtCreateManagedWidget("background",formWidgetClass,GCform,
+ gcchoiceargs,XtNumber(gcchoiceargs));
+ backgroundtext = create_text_choice(backgroundchoice,TBackground,4,50);
+
+ gcchoiceargs[1].value = (XtArgVal) NULL;
+ gcchoiceargs[0].value = (XtArgVal) foregroundchoice;
+ percentchoice = XtCreateManagedWidget("testpercent",formWidgetClass,GCform,
+ gcchoiceargs,XtNumber(gcchoiceargs));
+ X.percent = 1.0;
+ create_testfrac_choice(percentchoice);
+
+ /* make all the labels inside the choices line up nicely */
+ line_up_labels(GCdescs,(int) XtNumber(GCdescs));
+
+ /* put the test form under the GC form */
+ testformargs[0].value = (XtArgVal) GCform;
+ Testform = XtCreateManagedWidget("Testform",formWidgetClass,topform,
+ testformargs,XtNumber(testformargs));
+
+ testchoiceform = XtCreateManagedWidget("testchoiceform",formWidgetClass,
+ Testform,testchoiceargs,XtNumber(testchoiceargs));
+ testchoicedesc = create_choice(testchoiceform,Everything[CTest]);
+
+ commandformargs[0].value = (XtArgVal) GCform;
+ commandformargs[1].value = (XtArgVal) Testform;
+ commandform = XtCreateManagedWidget("commandform",formWidgetClass,topform,
+ commandformargs,XtNumber(commandformargs));
+
+ /* Put the appropriate command buttons in the command form */
+
+ fill_up_commandform(commandform);
+
+ testargs[2].value = (XtArgVal) GCform; /* to the right of */
+ test = XtCreateManagedWidget("test",widgetClass,topform,
+ testargs,XtNumber(testargs));
+
+ resultargs[2].value = (XtArgVal) GCform; /* to the right of */
+ resultargs[3].value = (XtArgVal) test; /* under */
+ result = XtCreateManagedWidget("result",asciiTextWidgetClass,topform,
+ resultargs,XtNumber(resultargs));
+
+ /* Now realize all the widgets */
+
+ XtRealizeWidget(bigdaddy);
+
+ /* Now do things we couldn't do until we had a window available */
+
+ X.win = XtWindow(test);
+ X.tile = XCreatePixmap(X.dpy,X.win,tile_width,tile_height,
+ DefaultDepthOfScreen(X.scr));
+
+ X.tile = XCreatePixmapFromBitmapData(X.dpy,X.win,
+ (char *)tile_bits,tile_width,
+ tile_height,Black,White,
+ DefaultDepthOfScreen(X.scr));
+ X.stipple = XCreateBitmapFromData(X.dpy,X.win,(char *)tile_bits,tile_width,
+ tile_height);
+
+ XSetStipple(X.dpy,X.gc,X.stipple);
+ XSetStipple(X.dpy,X.miscgc,X.stipple);
+
+ GC_change_foreground(X.foreground,TRUE);
+ GC_change_background(X.background,TRUE);
+
+ wm_delete_window = XInternAtom(X.dpy, "WM_DELETE_WINDOW", False);
+ (void) XSetWMProtocols(X.dpy, XtWindow(bigdaddy), &wm_delete_window, 1);
+
+ /* Act like the user picked the first choice in each group */
+
+ choose_defaults(GCdescs,(int)XtNumber(GCdescs));
+ choose_defaults(&testchoicedesc,1);
+
+ /* Loop forever, dealing with events */
+
+ XtAppMainLoop(appcontext);
+
+ return 0;
+}
+
+/* fill_up_commandform(w)
+** ----------------------
+** Put the appropriate command buttons in the command form (w).
+*/
+
+static void
+fill_up_commandform(w)
+ Widget w;
+{
+ static XtCallbackRec runcallbacklist[] = {
+ {(XtCallbackProc) run_test, NULL},
+ {NULL, NULL}
+ };
+
+ static XtCallbackRec quitcallbacklist[] = {
+ {(XtCallbackProc) quit, NULL},
+ {NULL, NULL}
+ };
+
+ static XtCallbackRec clearcallbacklist[] = {
+ {(XtCallbackProc) clear_test_window, NULL},
+ {(XtCallbackProc) clear_result_window, NULL},
+ {NULL, NULL}
+ };
+
+ static XtCallbackRec playbackcallbacklist[] = {
+ {(XtCallbackProc) start_playback, NULL},
+ {NULL, NULL}
+ };
+
+ static XtCallbackRec keyinputcallbacklist[] = {
+ {(XtCallbackProc) read_from_keyboard, NULL},
+ {NULL, NULL}
+ };
+
+ static XtCallbackRec recordcallbacklist[] = {
+ {(XtCallbackProc) toggle_recordbutton, NULL},
+ {NULL, NULL}
+ };
+
+ static Arg runargs[] = {
+ {XtNcallback, (XtArgVal) NULL}
+ };
+
+ static Arg clearargs[] = {
+ {XtNcallback, (XtArgVal) NULL},
+ {XtNfromVert, (XtArgVal) NULL}, /* put it under runbutton */
+ {XtNvertDistance,(XtArgVal) 10}
+ };
+
+ static Arg recordargs[] = {
+ {XtNcallback, (XtArgVal) NULL},
+ {XtNfromVert, (XtArgVal) NULL}, /* put it under clearbutton */
+ {XtNvertDistance,(XtArgVal) 10},
+ {XtNresizable, (XtArgVal) True} /* so we can change the name */
+ };
+
+ static Arg playbackargs[] = {
+ {XtNcallback, (XtArgVal) NULL},
+ {XtNfromVert, (XtArgVal) NULL} /* put it under recordbutton */
+ };
+
+ static Arg keyinputargs[] = {
+ {XtNcallback, (XtArgVal) NULL},
+ {XtNfromVert, (XtArgVal) NULL} /* put it under playbackbutton */
+ };
+
+ static Arg quitargs[] = {
+ {XtNcallback, (XtArgVal) NULL},
+ {XtNfromVert, (XtArgVal) NULL}, /* put it under keyinputbutton */
+ {XtNvertDistance,(XtArgVal) 10}
+ };
+
+ runargs[0].value = (XtArgVal) runcallbacklist;
+ runbutton = XtCreateManagedWidget("Run",commandWidgetClass,
+ w,runargs,XtNumber(runargs));
+
+ clearargs[0].value = (XtArgVal) clearcallbacklist;
+ clearargs[1].value = (XtArgVal) runbutton; /* under */
+ clearbutton = XtCreateManagedWidget("Clear window",commandWidgetClass,
+ w,clearargs,XtNumber(clearargs));
+
+ recordargs[0].value = (XtArgVal) recordcallbacklist;
+ recordargs[1].value = (XtArgVal) clearbutton; /* under */
+ recordbutton = XtCreateManagedWidget("Record",commandWidgetClass,
+ w,recordargs,XtNumber(recordargs));
+
+ playbackargs[0].value = (XtArgVal) playbackcallbacklist;
+ playbackargs[1].value = (XtArgVal) recordbutton; /* under */
+ playbackbutton = XtCreateManagedWidget("Playback",commandWidgetClass,
+ w,playbackargs,XtNumber(playbackargs));
+
+ keyinputargs[0].value = (XtArgVal) keyinputcallbacklist;
+ keyinputargs[1].value = (XtArgVal) playbackbutton;
+ keyinputbutton = XtCreateManagedWidget("Read Input",commandWidgetClass,
+ w,keyinputargs,XtNumber(keyinputargs));
+
+ quitargs[0].value = (XtArgVal) quitcallbacklist;
+ quitargs[1].value = (XtArgVal) keyinputbutton; /* under */
+ quitbutton = XtCreateManagedWidget("Quit",commandWidgetClass,
+ w,quitargs,XtNumber(quitargs));
+
+}
+/* quit()
+** ------
+** Leave the program nicely.
+*/
+
+static void
+quit()
+{
+ close_file_if_recording();
+ exit(0);
+}
+
+static void quitAction(w, e, p, n)
+ Widget w;
+ XEvent *e;
+ String *p;
+ Cardinal *n;
+{
+ if (e->type == ClientMessage && e->xclient.data.l[0] != wm_delete_window)
+ XBell(XtDisplay(w), 0);
+ else
+ quit();
+}
+
+/* clear_test_window()
+** -------------------
+** Clear the test window.
+*/
+
+static void
+clear_test_window()
+{
+ XClearWindow(X.dpy,XtWindow(test));
+}
+
+/* clear_result_window()
+** ---------------------
+** Clear the result window.
+*/
+
+static void
+clear_result_window()
+{
+ set_text(result, "");
+}
+
+/* set_foreground_and_background()
+** -------------------------------
+** Finds the user-specified foreground and background by querying
+** the resource manager, and sets state accordingly. Also specifies
+** the initial font for text tests.
+*/
+
+static void
+set_foreground_and_background()
+{
+ static XtResource resources[] = {
+ {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
+ XtOffsetOf(XStuff, foreground), XtRString, XtDefaultForeground},
+ {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
+ XtOffsetOf(XStuff, background), XtRString, XtDefaultBackground}
+ };
+
+ XtGetApplicationResources(bigdaddy, (XtPointer) &X, resources,
+ XtNumber(resources), NULL, (Cardinal) 0);
+
+ X.gcv.foreground = X.foreground;
+ X.gcv.background = X.background;
+
+ X.fontname = "6x10";
+ GC_change_font(X.fontname,FALSE);
+}
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 <X11/Xos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Toggle.h>
+#include "xgc.h"
+
+static void choose_plane(
+#if NeedFunctionPrototypes
+ Widget, caddr_t, caddr_t
+#endif
+);
+extern void interpret();
+
+extern XStuff X;
+
+static unsigned long planemask;
+static Widget *pm;
+
+/* create_planemask_choice(w)
+** -------------------------
+** Inside w (a form widget), creates a bunch of little toggle buttons
+** in a row, representing the planemask. There's also a label so
+** the user knows what it is.
+*/
+
+void
+create_planemask_choice(w)
+ Widget w;
+{
+ /* callback list for the toggle widgets */
+ static XtCallbackRec callbacklist[] = {
+ {(XtCallbackProc) choose_plane, NULL},
+ {NULL, NULL}
+ };
+
+ /* ArgList for the label */
+ static Arg labelargs[] = {
+ {XtNborderWidth, (XtArgVal) 0},
+ {XtNjustify, (XtArgVal) XtJustifyRight},
+ {XtNvertDistance, (XtArgVal) 4}
+ };
+
+ /* ArgList for the toggles */
+ static Arg pmargs[] = {
+ {XtNcallback, (XtArgVal) NULL},
+ {XtNhorizDistance, (XtArgVal) NULL},
+ {XtNfromHoriz, (XtArgVal) NULL},
+ {XtNwidth, (XtArgVal) 10},
+ {XtNheight, (XtArgVal) 10},
+ {XtNhighlightThickness,(XtArgVal) 1},
+ {XtNstate, (XtArgVal) True},
+ {XtNlabel, (XtArgVal) ""}
+ };
+
+ static Widget label; /* the label, of course */
+ static int *pminfo; /* contains integers saying which bit
+ a particular button is; sent to
+ choose_plane to tell it which
+ bit got changed */
+
+ int i, num_planes;
+
+ char buf[40];
+ char name[12];
+
+ num_planes = PlanesOfScreen(X.scr);
+
+ planemask = (1<<num_planes)-1;
+ sprintf(buf,"planemask %lu",planemask);
+ interpret(buf);
+
+ /* Allocate space for stuff that we don't know the size of yet */
+
+ pm = (Widget *) malloc(num_planes * sizeof(Widget));
+ pminfo = (int *) malloc(num_planes * sizeof(int));
+
+ /* Make the label widget */
+
+ label = XtCreateManagedWidget("planemask",labelWidgetClass,w,
+ labelargs,XtNumber(labelargs));
+
+ pmargs[0].value = (XtArgVal) callbacklist;
+
+ for (i=0;i<num_planes;++i) { /* go through all the buttons */
+ if (i==0) { /* offset the first one from the label */
+ pmargs[1].value = (XtArgVal) 10;
+ pmargs[2].value = (XtArgVal) label;
+ }
+ else { /* put it directly to the right of the
+ last one, no space in between */
+ pmargs[1].value = (XtArgVal) -1;
+ pmargs[2].value = (XtArgVal) pm[i-1];
+ }
+
+ /* set its original state depending on the state of that bit
+ ** of the planemask */
+
+ if (planemask & 1<<i)
+ pmargs[6].value = (XtArgVal) True;
+ else
+ pmargs[6].value = (XtArgVal) False;
+
+ sprintf(name,"planemask%d",i);
+
+ pminfo[i] = i; /* which bit we're on; this is needed in
+ choose_plane (the callback) */
+ callbacklist[0].closure = (caddr_t) &pminfo[i];
+
+ pm[i] = XtCreateManagedWidget(name,toggleWidgetClass,w,
+ pmargs,XtNumber(pmargs));
+ }
+}
+
+/* choose_plane(w,closure,call_data)
+** ------------------------------------
+** This function is called when the user toggles a toggle widget. It
+** makes the appropriate change to the planemask and sends it off
+** to interpret().
+** Funny args are because it's a callback.
+*/
+
+/*ARGSUSED*/
+static void
+choose_plane(w,closure,call_data)
+ Widget w;
+ caddr_t closure;
+ caddr_t call_data;
+{
+ int num; /* what number button it is */
+ Boolean on; /* is it currently on or off? */
+
+ char buf[80]; /* string to send to interpret() */
+
+ static Arg args[] = {
+ {XtNstate, (XtArgVal) NULL}
+ };
+
+ /* set up ArgList so that 'on' will contain the state */
+ args[0].value = (XtArgVal) &on;
+
+ num = * (int *) closure; /* we put it here back in the last function */
+ XtGetValues(w,args,XtNumber(args));
+
+ /* Modify the planemask appropriately */
+
+ if (on)
+ planemask |= 1<<num;
+ else
+ planemask &= ~(1<<num);
+
+ (void) sprintf(buf,"planemask %lu\n",planemask);
+ interpret(buf);
+}
+
+/* update_planemask(mask)
+** ----------------------
+** Updates the display of the planemask so that it corresponds to mask.
+*/
+
+void
+update_planemask(mask)
+ long mask;
+{
+ int i; /* counter */
+ static Arg maskargs[] = { /* ArgList for setting toggle state */
+ {XtNstate, (XtArgVal) NULL}
+ };
+
+ /* First set the internal representation */
+
+ planemask = mask;
+
+ for (i = 0; i < PlanesOfScreen(X.scr); ++i) {
+ if (planemask & 1<<i) { /* if it's set, make it look that way */
+ maskargs[0].value = (XtArgVal) True;
+ }
+ else {
+ maskargs[0].value = (XtArgVal) False;
+ }
+
+ XtSetValues(pm[i],maskargs,XtNumber(maskargs));
+ }
+}
diff --git a/record.c b/record.c
new file mode 100644
index 0000000..3884790
--- /dev/null
+++ b/record.c
@@ -0,0 +1,299 @@
+/*
+** xgc
+**
+** record.c
+*/
+/* $XFree86: xc/programs/xgc/record.c,v 1.3 2000/02/17 14:00:37 dawes Exp $ */
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Command.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Shell.h>
+#include <X11/Xaw/AsciiText.h>
+#include <stdio.h>
+
+#include "xgc.h"
+
+static void start_recording();
+static void stop_recording();
+static void print_out_gc_values();
+static void chose_playback_filename();
+static void cancel_playback();
+extern void get_filename();
+extern void yyparse();
+
+extern XgcStuff TestStuff;
+extern XgcStuff FunctionStuff;
+extern XgcStuff LinestyleStuff;
+extern XgcStuff CapstyleStuff;
+extern XgcStuff JoinstyleStuff;
+extern XgcStuff FillstyleStuff;
+extern XgcStuff FillruleStuff;
+extern XgcStuff ArcmodeStuff;
+
+extern XStuff X;
+extern Boolean recording;
+extern Widget filename_text_widget, recordbutton;
+
+static void cancel_record();
+static void done_choosing_filename();
+
+FILE *recordfile; /* the file we're recording to */
+FILE *playbackfile; /* the file we're playing back from */
+extern FILE *yyin; /* for yyparse */
+
+/* toggle_recordbutton(w,closure,call_data)
+** ----------------------------------------
+** This function is called when the user presses the "Record"
+** command button. If we're not recording, we start; if we are,
+** we stop. Also change the label to reflect the change in the
+** function of the button.
+*/
+
+/*ARGSUSED*/
+void
+toggle_recordbutton(w,closure,call_data)
+ Widget w;
+ caddr_t closure;
+ caddr_t call_data;
+{
+ /* ArgList for changing the label */
+ static Arg recordargs[] = {
+ {XtNlabel, (XtArgVal) NULL}
+ };
+
+ char tmp[20]; /* new label */
+
+ if (!recording) {
+ start_recording();
+ }
+ else {
+ recording = FALSE;
+ stop_recording();
+ sprintf(tmp,"Record");
+ recordargs[0].value = (XtArgVal) tmp;
+ }
+
+ XtSetValues(recordbutton,recordargs,XtNumber(recordargs));
+}
+
+/* start_recording()
+** -----------------
+** Get the name of the file the user wants to record into, and
+** start recording into it if he doesn't cancel.
+*/
+
+static void
+start_recording()
+{
+ get_filename(done_choosing_filename,cancel_record);
+}
+
+/* stop_recording()
+** ----------------
+** Close the output file.
+*/
+
+static void
+stop_recording()
+{
+ fclose(recordfile);
+}
+
+/* cancel_record()
+** ---------------
+** What to do if the if the user canceled recording, i.e. nothing.
+*/
+
+static void
+cancel_record()
+{
+}
+
+/* done_choosing_filename()
+** ------------------------
+** What to do after the user's chosen a file. Change the label on the
+** command button, open the file, and dump the current contents of the
+** GC into it.
+*/
+
+static void
+done_choosing_filename()
+{
+ static Arg recordargs[] = {
+ {XtNlabel, (XtArgVal) NULL},
+ {XtNresize, (XtArgVal) True}
+ };
+ Arg args[1];
+ char tmp[20], *filename;
+
+ XtSetArg(args[0], XtNstring, &filename);
+ XtGetValues(filename_text_widget, args, (Cardinal) 1);
+
+ if ((recordfile = fopen(filename,"w")) != NULL) {
+ recording = TRUE;
+ sprintf(tmp,"End Record");
+ recordargs[0].value = (XtArgVal) tmp;
+ XtSetValues(recordbutton,recordargs,XtNumber(recordargs));
+
+ print_out_gc_values();
+ }
+}
+
+/* print_if_recording(str)
+** -----------------------
+** If we're recording to a file, put str in it.
+*/
+
+void
+print_if_recording(str)
+ char *str;
+{
+ if (recording)
+ fprintf(recordfile,"%s",str);
+}
+
+/* close_file_if_recording()
+** -------------------------
+** If we're recording, stop.
+*/
+
+void
+close_file_if_recording()
+{
+ if (recording)
+ fclose(recordfile);
+}
+
+/* print_out_gc_values()
+** ---------------------
+** Dump the contents of the GC to the file, so that when the file gets
+** played back, it will be correctly initialized.
+*/
+
+static void
+print_out_gc_values()
+{
+ int i;
+ for (i=0;i<NUM_TESTS;++i) {
+ if ((TestStuff.data)[i].code == X.test) {
+ fprintf(recordfile,"%s %s\n",
+ TestStuff.choice.text,(TestStuff.data)[i].text);
+ break;
+ }
+ }
+ for (i=0;i<NUM_FUNCTIONS;++i) {
+ if ((FunctionStuff.data)[i].code == X.gcv.function) {
+ fprintf(recordfile,"%s %s\n",
+ FunctionStuff.choice.text,(FunctionStuff.data)[i].text);
+ break;
+ }
+ }
+ for (i=0;i<NUM_LINESTYLES;++i) {
+ if ((LinestyleStuff.data)[i].code == X.gcv.line_style) {
+ fprintf(recordfile,"%s %s\n",
+ LinestyleStuff.choice.text,(LinestyleStuff.data)[i].text);
+ break;
+ }
+ }
+ for (i=0;i<NUM_CAPSTYLES;++i) {
+ if ((CapstyleStuff.data)[i].code == X.gcv.cap_style) {
+ fprintf(recordfile,"%s %s\n",
+ CapstyleStuff.choice.text,(CapstyleStuff.data)[i].text);
+ break;
+ }
+ }
+ for (i=0;i<NUM_JOINSTYLES;++i) {
+ if ((JoinstyleStuff.data)[i].code == X.gcv.join_style) {
+ fprintf(recordfile,"%s %s\n",
+ JoinstyleStuff.choice.text,(JoinstyleStuff.data)[i].text);
+ break;
+ }
+ }
+ for (i=0;i<NUM_FILLSTYLES;++i) {
+ if ((FillstyleStuff.data)[i].code == X.gcv.fill_style) {
+ fprintf(recordfile,"%s %s\n",
+ FillstyleStuff.choice.text,(FillstyleStuff.data)[i].text);
+ break;
+ }
+ }
+ for (i=0;i<NUM_FILLRULES;++i) {
+ if ((FillruleStuff.data)[i].code == X.gcv.fill_rule) {
+ fprintf(recordfile,"%s %s\n",
+ FillruleStuff.choice.text,(FillruleStuff.data)[i].text);
+ break;
+ }
+ }
+ for (i=0;i<NUM_ARCMODES;++i) {
+ if ((ArcmodeStuff.data)[i].code == X.gcv.arc_mode) {
+ fprintf(recordfile,"%s %s\n",
+ ArcmodeStuff.choice.text,(ArcmodeStuff.data)[i].text);
+ break;
+ }
+ }
+ fprintf(recordfile,"linewidth %d\n",X.gcv.line_width);
+ fprintf(recordfile,"foreground %ld\n",X.gcv.foreground);
+ fprintf(recordfile,"background %ld\n",X.gcv.background);
+ fprintf(recordfile,"planemask %ld\n",X.gcv.plane_mask);
+ fprintf(recordfile,"dashlist %d\n",X.gcv.dashes);
+ fprintf(recordfile,"font %s\n",X.fontname);
+}
+
+/********************************************/
+
+/* start_playback()
+** ----------------
+** This gets called if the user wants to playback from a file.
+** Get the file name and do the appropriate thing.
+*/
+
+void
+start_playback()
+{
+ get_filename(chose_playback_filename,cancel_playback);
+}
+
+/* cancel_playback()
+** -----------------
+** What to do if the user canceled the playback request.
+*/
+
+static void
+cancel_playback()
+{
+}
+
+/* chose_playback_filename()
+** -------------------------
+** What to do once the user's selected a filename to playback.
+** Play it back.
+*/
+
+static void
+chose_playback_filename()
+{
+ Arg args[1];
+ char *filename;
+
+ XtSetArg(args[0], XtNstring, &filename);
+ XtGetValues(filename_text_widget, args, (Cardinal) 1);
+
+ if ((playbackfile = fopen(filename,"r")) != NULL) {
+ yyin = playbackfile;
+ yyparse();
+ }
+}
+
+/* read_from_keyboard()
+** --------------------
+** Do a playback from the keyboard.
+*/
+
+void
+read_from_keyboard()
+{
+ yyin = stdin;
+ yyparse();
+}
diff --git a/testfrac.c b/testfrac.c
new file mode 100644
index 0000000..56ba951
--- /dev/null
+++ b/testfrac.c
@@ -0,0 +1,205 @@
+/*
+** testfrac.c
+**
+** How to make a widget to choose the fraction of tests to be run.
+**
+*/
+/* $XFree86: xc/programs/xgc/testfrac.c,v 1.3 2000/02/17 14:00:37 dawes Exp $ */
+
+#include <stdio.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/Scrollbar.h>
+#include "xgc.h"
+
+extern void interpret();
+
+extern XtAppContext appcontext;
+
+#define SCROLLBAR_LENGTH 125
+#define SLIDER_LENGTH 0.2 /* proportion of scrollbar taken up
+ by the slider */
+
+static Widget label; /* the label */
+static Widget slider; /* the scrollbar */
+static Widget percent; /* label with chosen percentage */
+
+static float fraction; /* what percent has been chosen */
+static int oldpercent = -1; /* so we only update when the slider has
+ been moved */
+
+/* slider_jump(w,data,position)
+** ----------------------------
+** This function is called if the user moves the scrollbar to a new
+** position (generally, by using the middle button). It updates
+** information about where the scrollbar is.
+*/
+
+/*ARGSUSED*/
+static void
+slider_jump(w, data, position)
+ Widget w;
+ caddr_t data;
+ caddr_t position;
+{
+ static Arg percentargs[] = {
+ {XtNlabel, (XtArgVal) NULL}
+ };
+
+ float oldpercent; /* where the scrollbar is */
+ float newpercent; /* normalized scrollbar */
+ char snewpercent[3]; /* string representation of scrollbar */
+
+ oldpercent = *(float *) position;
+
+ /* We want the scrollbar to be at 100% when the right edge of the slider
+ ** hits the end of the scrollbar, not the left edge. When the right edge
+ ** is at 1.0, the left edge is at 1.0 - SLIDER_LENGTH. Normalize
+ ** accordingly. */
+
+ newpercent = oldpercent / (1.0 - SLIDER_LENGTH);
+
+ /* If the slider's partially out of the scrollbar, move it back in. */
+
+ if (newpercent > 1.0) {
+ newpercent = 1.0;
+ XawScrollbarSetThumb( slider, 1.0 - SLIDER_LENGTH, SLIDER_LENGTH);
+ }
+
+ /* Store the position of the silder where it can be found */
+
+ *(float *)data = newpercent;
+
+ /* Update the label widget */
+
+ sprintf(snewpercent,"%d",(int)(newpercent*100));
+ percentargs[0].value = (XtArgVal) snewpercent;
+ XtSetValues(percent, percentargs, XtNumber(percentargs));
+}
+
+/* slider_scroll(w,data,position)
+** ------------------------------
+** This function is called when the user does incremental scrolling,
+** generally with the left or right button. Right now it just ignores it.
+*/
+
+/*ARGSUSED*/
+static void
+slider_scroll(w, data, position)
+ Widget w;
+ caddr_t data;
+ caddr_t position;
+{}
+
+/*ARGSUSED*/
+static void
+update(w,event,params,num_params)
+ Widget w;
+ XEvent *event;
+ String *params;
+ int *num_params;
+{
+ char buf[80];
+ int newpercent;
+
+ newpercent = (int)(fraction * 100.0);
+ if (newpercent != oldpercent) {
+ sprintf(buf, "percent %d\n", (int)(fraction * 100.0));
+ interpret(buf);
+ oldpercent = newpercent;
+ }
+}
+
+/* create_testfrac_choice(w)
+** -------------------------
+** Inside w (a form widget), creates:
+** 1. A label "Percentage of Test"
+** 2. A scrollbar for the user to choose the percentage (from 0 to 100)
+** 3. A label with the current percentage displayed on it.
+** The percentage starts at 100.
+**
+** When the pointer leaves the scrollbar, a string is sent to interpret()
+** so that it knows the position of the scrollbar.
+*/
+
+void
+create_testfrac_choice(w)
+ Widget w;
+{
+ static XtCallbackRec jumpcallbacks[] = {
+ {(XtCallbackProc) slider_jump, NULL},
+ {NULL, NULL}
+ };
+
+ static XtCallbackRec scrollcallbacks[] = {
+ {(XtCallbackProc) slider_scroll, NULL},
+ {NULL, NULL}
+ };
+
+ static Arg labelargs[] = {
+ {XtNborderWidth, (XtArgVal) 0},
+ {XtNjustify, (XtArgVal) XtJustifyRight},
+ {XtNvertDistance, (XtArgVal) 4}
+ };
+
+ static Arg percentargs[] = {
+ {XtNborderWidth, (XtArgVal) 1},
+ {XtNhorizDistance, (XtArgVal) 10},
+ {XtNfromHoriz, (XtArgVal) NULL}
+ };
+
+ static Arg scrollargs[] = {
+ {XtNorientation, (XtArgVal) XtorientHorizontal},
+ {XtNlength, (XtArgVal) SCROLLBAR_LENGTH},
+ {XtNthickness, (XtArgVal) 10},
+ {XtNshown, (XtArgVal) 10},
+ {XtNhorizDistance, (XtArgVal) 10},
+ {XtNfromHoriz, (XtArgVal) NULL},
+ {XtNjumpProc, (XtArgVal) NULL},
+ {XtNscrollProc, (XtArgVal) NULL}
+ };
+
+ static const char *translationtable = "<Leave>: Update()";
+
+ static XtActionsRec actiontable[] = {
+ {"Update", (XtActionProc) update},
+ {NULL, NULL}
+ };
+
+ /* Let the scrollbar know where to store information where we
+ ** can see it */
+
+ jumpcallbacks[0].closure = (caddr_t) &fraction;
+
+ label = XtCreateManagedWidget("Percentage of Test",labelWidgetClass,w,
+ labelargs,XtNumber(labelargs));
+
+ percentargs[2].value = (XtArgVal) label;
+
+ percent = XtCreateManagedWidget("100",labelWidgetClass,w,
+ percentargs,XtNumber(percentargs));
+
+ scrollargs[5].value = (XtArgVal) percent;
+ scrollargs[6].value = (XtArgVal) jumpcallbacks;
+ scrollargs[7].value = (XtArgVal) scrollcallbacks;
+
+ slider = XtCreateManagedWidget("Slider",scrollbarWidgetClass,w,
+ scrollargs,XtNumber(scrollargs));
+
+ XtAppAddActions(appcontext,actiontable,XtNumber(actiontable));
+ XtOverrideTranslations(slider,XtParseTranslationTable(translationtable));
+
+ /* Start the thumb out at 100% */
+
+ XawScrollbarSetThumb(slider, 1.0 - SLIDER_LENGTH, SLIDER_LENGTH);
+}
+
+void
+update_slider(newpercent)
+ int newpercent;
+{
+ fraction = (float) newpercent / 100.0;
+ XawScrollbarSetThumb(slider, fraction / (1.0-SLIDER_LENGTH), SLIDER_LENGTH);
+}
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 <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/AsciiText.h>
+#include <X11/Xos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "xgc.h"
+#ifdef SVR4
+#define SYSV
+#endif
+#if !defined(SYSV) && !defined(QNX4)
+#include <sys/timeb.h>
+#include <sys/resource.h>
+#endif
+
+#ifndef PI
+#define PI 3.14159265
+#endif
+
+#ifdef SYSV
+#define random lrand48
+#endif
+
+extern XStuff X;
+extern Widget result;
+
+extern void GC_change_font();
+extern void print_if_recording();
+void show_result();
+
+/* timer(flag)
+** -----------
+** When called with StartTimer, starts the stopwatch and returns nothing.
+** When called with EndTimer, stops the stopwatch and returns the time
+** in microseconds since it started.
+**
+** Uses rusage() so we can subtract the time used by the system and user
+** from our timer, and just concentrate on the time used in the X calls.
+*/
+
+static long
+timer(flag)
+ int flag;
+{
+#if !defined(SYSV)
+ static struct timeval starttime; /* starting time for gettimeofday() */
+ struct timeval endtime; /* ending time for gettimeofday() */
+#if !defined(__UNIXOS2__) && !defined(QNX4)
+ static struct rusage startusage; /* starting time for getrusage() */
+ struct rusage endusage; /* ending time for getrusage() */
+#endif
+ struct timezone tz; /* to make gettimeofday() happy */
+
+ long elapsedtime; /* how long since we started the timer */
+
+ switch (flag) {
+ case StartTimer: /* store initial values */
+ gettimeofday(&starttime,&tz);
+#if !defined(__UNIXOS2__) && !defined(QNX4)
+ getrusage(RUSAGE_SELF,&startusage);
+#endif
+ return((long) NULL);
+ case EndTimer:
+ gettimeofday(&endtime,&tz); /* store final values */
+#if !defined(__UNIXOS2__) && !defined(QNX4)
+ getrusage(RUSAGE_SELF,&endusage);
+#endif
+
+ /* all the following line does is use the formula
+ elapsed time = ending time - starting time, but there are three
+ different timers and two different units of time, ack... */
+
+#if !defined(__UNIXOS2__) && !defined(QNX4)
+ elapsedtime = (long) ((long)
+ ((endtime.tv_sec - endusage.ru_utime.tv_sec - endusage.ru_stime.tv_sec
+ - starttime.tv_sec + startusage.ru_utime.tv_sec
+ + startusage.ru_stime.tv_sec)) * 1000000) + (long)
+ ((endtime.tv_usec - endusage.ru_utime.tv_usec - endusage.ru_stime.tv_usec
+ - starttime.tv_usec + startusage.ru_utime.tv_usec
+ + startusage.ru_stime.tv_usec));
+#else
+ elapsedtime = (long)( ((long)endtime.tv_sec-(long)starttime.tv_sec)*1000000
+ +((long)endtime.tv_usec-(long)starttime.tv_usec));
+#endif
+ return(elapsedtime);
+
+ default:
+ fprintf(stderr,"Invalid flag in timer()\n");
+ return((long) NULL);
+ }
+#else
+ static long starttime;
+
+ switch (flag) {
+ case StartTimer:
+ time(&starttime);
+ return((long) NULL);
+ case EndTimer:
+ return( (time(NULL) - starttime) * 1000000);
+ default:
+ fprintf(stderr,"Invalid flag in timer()\n");
+ return((long) NULL);
+ }
+#endif
+}
+
+
+void
+copyarea_test()
+{
+ int num_copies = 200;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ num_copies *= X.percent;
+
+ XSetFillStyle(X.dpy,X.miscgc,FillTiled);
+ XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400);
+
+ XSync(X.dpy,0);
+ timer(StartTimer);
+ for (i=0;i<num_copies;++i)
+ XCopyArea(X.dpy,X.win,X.win,X.gc,i,200-i,
+ 200,200,200-i,i);
+ XSync(X.dpy,0);
+ totaltime = timer(EndTimer);
+
+ sprintf(buf,"%.2f seconds.",(double)totaltime/1000000.);
+ show_result(buf);
+}
+
+void
+copyplane_test()
+{
+ int num_copies = 200;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ if(!X.gcv.plane_mask || (X.gcv.plane_mask & (X.gcv.plane_mask - 1))) {
+ show_result("exactly one bit in plane mask must be set for this test");
+ return;
+ }
+
+
+ num_copies *= X.percent;
+
+ XSetPlaneMask(X.dpy, X.gc, ~0L);
+ XSetFillStyle(X.dpy,X.miscgc,FillTiled);
+ XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400);
+
+ XSync(X.dpy,0);
+ timer(StartTimer);
+ for (i=0;i<num_copies;++i)
+ XCopyPlane(X.dpy,X.win,X.win,X.gc,i,200-i,
+ 200,200,200-i,i,X.gcv.plane_mask);
+ XSync(X.dpy,0);
+ totaltime = timer(EndTimer);
+ XSetPlaneMask(X.dpy, X.gc, X.gcv.plane_mask);
+
+ sprintf(buf,"%.2f seconds.",(double)totaltime/1000000.);
+ show_result(buf);
+}
+
+void
+circle_line_test(num_vertices,radius)
+ int num_vertices,radius;
+{
+ double theta, delta;
+ int length, centerx, centery, i;
+ int relative_angle;
+ long totaltime;
+ char buf[80];
+ XPoint *coord;
+
+ relative_angle = num_vertices*5/12+1;
+ delta = (double) relative_angle / (double) num_vertices * 2 * PI;
+ centerx = centery = 200;
+
+ coord = (XPoint *) malloc (sizeof(XPoint)*(num_vertices+1));
+
+ length = (int) (2 * radius * (float) atan(delta/2.));
+
+ for (i=0;i<=num_vertices;++i) {
+ theta = (double) i * delta;
+ coord[i].x = centerx + (int) (radius * cos(theta));
+ coord[i].y = centery + (int) (radius * sin(theta));
+ }
+
+ XSync(X.dpy,0);
+ timer(StartTimer);
+ XDrawLines(X.dpy,X.win,X.gc,coord,num_vertices+1,CoordModeOrigin);
+ XSync(X.dpy,0);
+ totaltime = timer(EndTimer);
+
+ sprintf(buf,"%d lines of length %d in %.3f seconds.",num_vertices,
+ length,(double)totaltime/1000000.);
+ show_result(buf);
+
+ free(coord);
+}
+
+
+
+void
+polyline_test()
+{
+ circle_line_test((int)(601*X.percent),190);
+}
+
+void
+polysegment_test()
+{
+ XSegment *segments;
+ int num_segments = 600;
+ long totaltime;
+ char buf[80];
+ int i;
+
+ num_segments *= X.percent;
+
+ segments = (XSegment *) malloc(sizeof(XSegment) * num_segments);
+
+ segments[0].x1 = random()%400; segments[0].y1 = random()%400;
+ segments[0].x2 = random()%400; segments[0].y2 = random()%400;
+
+ for(i=1;i<num_segments;++i) {
+ segments[i].x1 = (segments[i-1].x1-segments[i-1].y2+400+i)%400;
+ segments[i].y1 = (segments[i-1].y1+segments[i-1].x2+i)%400;
+ segments[i].x2 = (segments[i-1].x1-segments[i-1].y1+400+i)%400;
+ segments[i].y2 = (segments[i-1].x2+segments[i-1].y2+i)%400;
+ }
+
+ XSync(X.dpy,0);
+ start_timer();
+ XDrawSegments(X.dpy,X.win,X.gc,segments,num_segments);
+ XSync(X.dpy,0);
+ totaltime = end_timer();
+
+ sprintf(buf,"%d segments in %.3f seconds.",num_segments,
+ (double)totaltime/1000000.);
+ show_result(buf);
+
+ free(segments);
+}
+
+void
+polypoint_test()
+{
+ XPoint *points;
+ int num_points = 100000;
+ long totaltime;
+ char buf[80];
+ int i;
+
+ num_points *= X.percent;
+
+ points = (XPoint *) malloc(sizeof(XPoint) * num_points);
+
+ points[0].x = random()%400; points[0].y = random()%400;
+ points[1].x = random()%400; points[1].y = random()%400;
+
+ for (i=2;i<num_points;++i) {
+ points[i].x = (points[i-1].x+points[i-2].y+i*3/200)%400;
+ points[i].y = (points[i-1].y+points[i-2].x+i*5/200)%400;
+ }
+
+ XSync(X.dpy,0);
+ start_timer();
+ XDrawPoints(X.dpy,X.win,X.gc,points,num_points,CoordModeOrigin);
+ XSync(X.dpy,0);
+ totaltime = end_timer();
+
+ sprintf(buf,"%d points in %.3f seconds.",num_points,
+ (double)totaltime/1000000.);
+ show_result(buf);
+
+ free(points);
+}
+
+void
+genericrectangle_test(fill)
+ Boolean fill;
+{
+ XRectangle *rects;
+ int num_rects = 200;
+ int perimeter = 0, area = 0;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ num_rects *= X.percent;
+
+ rects = (XRectangle *) malloc(sizeof(XRectangle) * num_rects);
+
+ for (i=0;i<num_rects;++i) {
+ rects[i].x = rects[i].y = 200 - i;
+ rects[i].width = rects[i].height = 2 * i;
+ perimeter += rects[i].width * 2 + rects[i].height * 2;
+ area += rects[i].width * rects[i].height;
+ }
+
+ XSync(X.dpy,0);
+ start_timer();
+ if (fill) XFillRectangles(X.dpy,X.win,X.gc,rects,num_rects);
+ else XDrawRectangles(X.dpy,X.win,X.gc,rects,num_rects);
+ XSync(X.dpy,0);
+ totaltime = end_timer();
+
+ if (fill)
+ sprintf(buf,"%d pixels in %.2f seconds.",area,(double)totaltime/1000000.);
+ else
+ sprintf(buf,"Total line length %d in %.3f seconds.",perimeter,
+ (double)totaltime/1000000.);
+ show_result(buf);
+
+ free(rects);
+}
+
+void
+polyrectangle_test()
+{
+ genericrectangle_test(FALSE);
+}
+
+void
+polyfillrectangle_test()
+{
+ genericrectangle_test(TRUE);
+}
+
+/*****************************/
+
+void
+fillpolygon_test()
+{
+ int i;
+ int points_per_side = 40;
+ int spacing;
+ XPoint *points;
+ XPoint polypoints[3];
+
+ points = (XPoint *) malloc (sizeof(XPoint) * points_per_side * 4);
+ spacing = 400 / points_per_side;
+
+ for (i = 0; i < points_per_side; ++i) {
+ points[i].x = i * spacing;
+ points[i].y = 0;
+
+ points[i + points_per_side].x = 400;
+ points[i + points_per_side].y = i * spacing;
+
+ points[i + 2 * points_per_side].x = 400 - i * spacing;
+ points[i + 2 * points_per_side].y = 400;
+
+ points[i + 3 * points_per_side].x = 0;
+ points[i + 3 * points_per_side].y = 400 - i * spacing;
+ }
+
+ for (i = 0; i < 2 * points_per_side; i += 2) {
+ polypoints[0].x = points[i].x;
+ polypoints[0].y = points[i].y;
+
+ polypoints[1].x = points[i + 2 * points_per_side].x;
+ polypoints[1].y = points[i + 2 * points_per_side].y;
+
+ polypoints[2].x = points[i + 2 * points_per_side + 1].x;
+ polypoints[2].y = points[i + 2 * points_per_side + 1].y;
+
+ XFillPolygon (X.dpy, X.win, X.gc, polypoints, 3, Convex, CoordModeOrigin);
+ }
+ free(points);
+}
+
+/*****************************/
+
+void
+genericarc_test(fill)
+ Boolean fill;
+{
+ XArc *arcs;
+ int num_arcs = 180;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ num_arcs *= X.percent;
+
+ arcs = (XArc *) malloc(sizeof(XArc) * num_arcs);
+
+ for (i=0;i<num_arcs;++i) {
+ arcs[i].x = i;
+ arcs[i].y = i;
+ arcs[i].width = i;
+ arcs[i].height = i;
+ arcs[i].angle1 = i * 128;
+ arcs[i].angle2 = i * 128;
+ }
+
+ XSync(X.dpy,0);
+ start_timer();
+ if (fill) XFillArcs(X.dpy,X.win,X.gc,arcs,num_arcs);
+ else XDrawArcs(X.dpy,X.win,X.gc,arcs,num_arcs);
+ XSync(X.dpy,0);
+ totaltime = end_timer();
+
+ sprintf(buf,"An uncounted number of pixels in %.3f seconds.",
+ (double)totaltime/1000000.);
+ show_result(buf);
+
+ free(arcs);
+}
+
+void
+polyarc_test()
+{
+ genericarc_test(FALSE);
+}
+
+void
+polyfillarc_test()
+{
+ genericarc_test(TRUE);
+}
+
+static const char string8[] = "pack my box with five dozen liquor jugs";
+
+void
+polytext8_test()
+{
+ int num_strings = 200;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ num_strings *= X.percent;
+
+ XSync(X.dpy,0);
+ start_timer();
+ for (i=0;i<num_strings;++i) {
+ XDrawString(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),i,
+ string8,sizeof(string8)-1);
+ }
+ XSync(X.dpy,0);
+ totaltime = end_timer();
+
+ sprintf(buf,"%d strings in %.2f seconds.",num_strings,
+ (double) totaltime/1000000.);
+ show_result(buf);
+}
+
+void
+imagetext8_test()
+{
+ int num_strings = 200;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ num_strings *= X.percent;
+
+ XSync(X.dpy,0);
+ start_timer();
+ for (i=0;i<num_strings;++i) {
+ XDrawImageString(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),i,
+ string8,sizeof(string8)-1);
+ }
+ XSync(X.dpy,0);
+ totaltime = end_timer();
+
+ sprintf(buf,"%d strings in %.2f seconds.",num_strings,
+ (double) totaltime/1000000.);
+ show_result(buf);
+}
+
+static const char unicode_font[] =
+ "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1";
+
+static const XChar2b string16[] = {
+ { 0x00, 0x20 }, { 0x00, 0x20 }, { 0x22, 0x2E }, { 0x00, 0x20 },
+ { 0x00, 0x45 }, { 0x22, 0xC5 }, { 0x00, 0x64 }, { 0x00, 0x61 },
+ { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x00, 0x51 },
+ { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x00, 0x20 }, { 0x00, 0x6E },
+ { 0x00, 0x20 }, { 0x21, 0x92 }, { 0x00, 0x20 }, { 0x22, 0x1E },
+ { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x22, 0x11 }, { 0x00, 0x20 },
+ { 0x00, 0x66 }, { 0x00, 0x28 }, { 0x00, 0x69 }, { 0x00, 0x29 },
+ { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x22, 0x0F },
+ { 0x00, 0x20 }, { 0x00, 0x67 }, { 0x00, 0x28 }, { 0x00, 0x69 },
+ { 0x00, 0x29 }, { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x22, 0x00 },
+ { 0x00, 0x78 }, { 0x22, 0x08 }, { 0x21, 0x1D }, { 0x00, 0x3A },
+ { 0x00, 0x20 }, { 0x23, 0x08 }, { 0x00, 0x78 }, { 0x23, 0x09 },
+ { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x22, 0x12 },
+ { 0x23, 0x0A }, { 0x22, 0x12 }, { 0x00, 0x78 }, { 0x23, 0x0B },
+ { 0x00, 0x2C }, { 0x00, 0x20 }, { 0x03, 0xB1 }, { 0x00, 0x20 },
+ { 0x22, 0x27 }, { 0x00, 0x20 }, { 0x00, 0xAC }, { 0x03, 0xB2 },
+ { 0x00, 0x20 }, { 0x00, 0x3D }, { 0x00, 0x20 }, { 0x00, 0xAC },
+ { 0x00, 0x28 }, { 0x00, 0xAC }, { 0x03, 0xB1 }, { 0x00, 0x20 },
+ { 0x22, 0x28 }, { 0x00, 0x20 }, { 0x03, 0xB2 }, { 0x00, 0x29 },
+ { 0x00, 0x2C }
+};
+
+void
+polytext16_test()
+{
+ int num_strings = 50;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ num_strings *= X.percent;
+
+ GC_change_font(unicode_font,FALSE);
+
+ XSync(X.dpy,0);
+ start_timer();
+ for (i=0;i<num_strings;++i) {
+ XDrawString16(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),10*i,
+ string16,sizeof(string16)/sizeof(XChar2b));
+ }
+ XSync(X.dpy,0);
+ totaltime = end_timer();
+
+ GC_change_font(X.fontname,FALSE);
+
+ sprintf(buf,"%d strings in %.2f seconds.",num_strings,
+ (double) totaltime/1000000.);
+ show_result(buf);
+}
+
+void
+imagetext16_test()
+{
+ int num_strings = 50;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ num_strings *= X.percent;
+
+ GC_change_font(unicode_font,FALSE);
+
+ XSync(X.dpy,0);
+ start_timer();
+ for (i=0;i<num_strings;++i) {
+ XDrawImageString16(X.dpy,X.win,X.gc,(i%2 ? i : num_strings - i),10*i,
+ string16,sizeof(string16)/sizeof(XChar2b));
+ }
+ XSync(X.dpy,0);
+ totaltime = end_timer();
+
+ GC_change_font(X.fontname,FALSE);
+
+ sprintf(buf,"%d strings in %.2f seconds.",num_strings,
+ (double) totaltime/1000000.);
+ show_result(buf);
+}
+
+void
+putimage_test()
+{
+ int num_copies = 200;
+ int i;
+ long totaltime;
+ char buf[80];
+
+ num_copies *= X.percent;
+
+ XSetFillStyle(X.dpy,X.miscgc,FillTiled);
+ XFillRectangle(X.dpy,X.win,X.miscgc,0,0,400,400);
+
+ X.image = XGetImage(X.dpy,X.win,0,0,200,200,~0,XYPixmap);
+
+ XSync(X.dpy,0);
+ timer(StartTimer);
+ for (i=0;i<num_copies;++i)
+ XPutImage(X.dpy,X.win,X.gc,X.image,0,0,i,i,200,200);
+ XSync(X.dpy,0);
+ totaltime = timer(EndTimer);
+
+ sprintf(buf,"%.2f seconds.",(double)totaltime/1000000.);
+ show_result(buf);
+}
+
+
+/*****************************/
+/*****************************/
+
+void
+run_test()
+{
+ XClearWindow(X.dpy,X.win);
+
+ print_if_recording("run\n");
+
+ switch (X.test) {
+ case CopyArea: copyarea_test(); break;
+ case CopyPlane: copyplane_test(); break;
+ case PolyPoint: polypoint_test(); break;
+ case PolyLine: polyline_test(); break;
+ case PolySegment: polysegment_test(); break;
+ case PolyRectangle: polyrectangle_test(); break;
+ case PolyArc: polyarc_test(); break;
+ case FillPolygon: fillpolygon_test(); break;
+ case PolyFillRect: polyfillrectangle_test(); break;
+ case PolyFillArc: polyfillarc_test(); break;
+ case PolyText8: polytext8_test(); break;
+ case ImageText8: imagetext8_test(); break;
+ case PolyText16: polytext16_test(); break;
+ case ImageText16: imagetext16_test(); break;
+ case PutImage: putimage_test(); break;
+ default: fprintf(stderr,"That test doesn't exist yet.\n");
+ }
+}
+
+/*****************************/
+
+/* set_text(w,string)
+** ------------------
+** Sets the text in a read-only text widget to the specified string.
+*/
+
+void
+set_text(w,string)
+ Widget w;
+ char *string;
+{
+ static Arg args[2];
+
+ XtSetArg(args[0], XtNstring, string);
+ XtSetArg(args[1], XtNlength, strlen(string));
+ XtSetValues(w, args, (Cardinal) 2 );
+}
+
+void
+show_result(string)
+ char *string;
+{
+ char buf[80];
+
+ set_text(result,string);
+
+ strcpy(buf,"# ");
+ strncat(buf,string,sizeof(buf) - 3);
+ buf[sizeof(buf) - 3] = '\0';
+ strcat(buf,"\n");
+ print_if_recording(buf);
+}
diff --git a/text.c b/text.c
new file mode 100644
index 0000000..7a86137
--- /dev/null
+++ b/text.c
@@ -0,0 +1,209 @@
+/*
+** xgc
+**
+** text.c
+**
+** How to make a text widget that returns a string when the cursor
+** leaves its window.
+*/
+/* $XFree86: xc/programs/xgc/text.c,v 1.3 2000/02/17 14:00:37 dawes Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/AsciiText.h>
+#include "xgc.h"
+
+static void WriteText();
+extern void interpret();
+
+extern XStuff X;
+extern XtAppContext appcontext;
+
+/* the strings which are displayed on the screen, edited, and sent
+ to interpret() */
+static char textstrings[NUMTEXTWIDGETS][80];
+
+static char oldtextstrings[NUMTEXTWIDGETS][80];
+
+static const char *defaultstrings[NUMTEXTWIDGETS] = {"0","6x10","0","1"};
+
+/* The labels displayed next to them */
+static const char *labels[NUMTEXTWIDGETS] = {"Line Width","Font","Foreground",
+ "Background"};
+
+/* the first half of what gets sent to interpret() */
+static const char *names[NUMTEXTWIDGETS] = {"linewidth ","font ","foreground ",
+ "background "};
+
+/* create_text_choice(w,type,length,width)
+** ---------------------------------------
+** Inside w (a form), creates an editable text widget of width width. The
+** user can enter a string of up to length characters. type is one of
+** the constants defined in xgc.h; it decides things like the label,
+** what string will be displayed and edited, etc. When the pointer leaves
+** the widget, the widget does the appropriate thing with the text
+** inside it; the user doesn't have to press an "enter" button or anything.
+** Returns the text widget which the user will edit.
+*/
+
+Widget
+create_text_choice(w,type,length,width)
+ Widget w;
+ int type;
+ int length, width;
+{
+ char translationtable[600]; /* for adding the new action (calling
+ WriteText() when the pointer leaves) */
+
+ static XtActionsRec actionTable[] = { /* likewise */
+ {"WriteText", WriteText},
+ {"Nothing", NULL}
+ };
+
+ static Arg labelargs[] = {
+ {XtNborderWidth, (XtArgVal) 0},
+ {XtNjustify, (XtArgVal) XtJustifyRight}
+ };
+
+ static Arg textargs[] = {
+ {XtNeditType, (XtArgVal) XawtextEdit},
+ {XtNstring, (XtArgVal) NULL},
+ {XtNlength, (XtArgVal) NULL},
+ {XtNwidth, (XtArgVal) NULL},
+ {XtNhorizDistance, (XtArgVal) 10},
+ {XtNfromHoriz, (XtArgVal) NULL},
+ {XtNinsertPosition, (XtArgVal) NULL},
+ {XtNuseStringInPlace, (XtArgVal) True}
+ };
+
+ static Widget text; /* the text widget */
+ static Widget label; /* the label widget */
+
+ /* Disable keys which would cause the cursor to go off the single
+ ** line that we want to display. If the pointer leaves the window,
+ ** update the GC accordingly. The integer passed to WriteText is
+ ** so it knows what type of widget was just updated. */
+
+ sprintf(translationtable,
+ "<Leave>: WriteText(%d)\n\
+ Ctrl<Key>J: Nothing()\n\
+ Ctrl<Key>M: Nothing()\n\
+ <Key>Linefeed: Nothing()\n\
+ <Key>Return: Nothing()\n\
+ Ctrl<Key>O: Nothing()\n\
+ Meta<Key>I: Nothing()\n\
+ Ctrl<Key>N: Nothing()\n\
+ Ctrl<Key>P: Nothing()\n\
+ Ctrl<Key>Z: Nothing()\n\
+ Meta<Key>Z: Nothing()\n\
+ Ctrl<Key>V: Nothing()\n\
+ Meta<Key>V: Nothing()",type);
+
+ /* label uses type to find out what its title is */
+ label = XtCreateManagedWidget(labels[type],labelWidgetClass,w,
+ labelargs,XtNumber(labelargs));
+
+ /* text uses type to find out what its string is */
+ switch (type) {
+ case TForeground:
+ sprintf(textstrings[type],"%d",(int) X.gcv.foreground);
+ sprintf(oldtextstrings[type],"%d",(int) X.gcv.foreground);
+ break;
+ case TBackground:
+ sprintf(textstrings[type],"%d",(int) X.gcv.background);
+ sprintf(oldtextstrings[type],"%d",(int) X.gcv.background);
+ break;
+ default:
+ strcpy(textstrings[type],defaultstrings[type]);
+ strcpy(oldtextstrings[type],defaultstrings[type]);
+ }
+ textargs[1].value = (XtArgVal) textstrings[type];
+ textargs[2].value = (XtArgVal) length;
+ textargs[3].value = (XtArgVal) width;
+ textargs[5].value = (XtArgVal) label;
+ textargs[6].value = (XtArgVal) strlen(textstrings[type]);
+
+ text = XtCreateManagedWidget("text", asciiTextWidgetClass,w,
+ textargs,XtNumber(textargs));
+
+ /* Register the actions and translations */
+
+ XtAppAddActions(appcontext,actionTable,XtNumber(actionTable));
+ XtOverrideTranslations(text,XtParseTranslationTable(translationtable));
+
+ return(text);
+}
+
+/* WriteText(w,event,params,num_params)
+** ------------------------------------
+** Makes an appropriate string and sends it off to interpret().
+** It's an ActionProc, thus the funny arguments.
+*/
+
+/*ARGSUSED*/
+static void
+WriteText(w,event,params,num_params)
+ Widget w;
+ XEvent *event;
+ String *params; /* the type is in here */
+ Cardinal *num_params;
+{
+ char mbuf[80];
+ int type; /* which string # to send */
+
+ type = atoi(params[0]);
+ if (strcmp(textstrings[type],oldtextstrings[type])) {
+ strcpy(oldtextstrings[type],textstrings[type]);
+ sprintf(mbuf,names[type]); /* the right first half */
+ strcat(mbuf,textstrings[type]); /* the right second half */
+ strcat(mbuf,"\n"); /* the right newline */
+ interpret(mbuf); /* send it off */
+ }
+}
+
+/* change_text(w,type,newtext)
+** ------------------------
+** Changes the text in the text widget w of type type to newtext.
+*/
+
+void
+change_text(w,newtext)
+ Widget w;
+ String newtext;
+{
+ XawTextBlock text; /* the new text */
+ XawTextPosition first, last; /* boundaries of the old text */
+ String oldtext; /* the old text */
+
+ static Arg textargs[] = {
+ {XtNstring, (XtArgVal) 0}
+ };
+
+ /* Initialize the XawTextBlock. */
+
+ if (!newtext)
+ newtext = "";
+ text.firstPos = 0;
+ text.length = strlen(newtext);
+ text.ptr = newtext;
+ text.format = FMT8BIT;
+
+ /* Find the old text, so we can get its length, so we know how
+ ** much of it to update. */
+
+ textargs[0].value = (XtArgVal) &oldtext;
+ XtGetValues(w,textargs,XtNumber(textargs));
+ first = XawTextTopPosition(w);
+ if (!oldtext)
+ oldtext = "";
+ last = (XawTextPosition) strlen(oldtext)+1;
+
+ /* Replace it with the new text. */
+
+ XawTextReplace(w, first, last, &text);
+}
+
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