diff --git a/collects/scribble/html-render.ss b/collects/scribble/html-render.ss
index f9783ba465..0aad6228ad 100644
--- a/collects/scribble/html-render.ss
+++ b/collects/scribble/html-render.ss
@@ -314,6 +314,16 @@
[else (error 'html-render "unrecognized style symbol: ~e" style)])]
[(string? style)
`((span ([class ,style]) ,@(super render-element e part ht)))]
+ [(and (pair? style)
+ (eq? (car style) 'show-color))
+ `((font ((style ,(format "background-color: ~a"
+ (apply string-append "#"
+ (map (lambda (v) (let ([s (format "0~x" v)])
+ (substring s (- (string-length s) 2))))
+ (cdr style))))))
+ (tt nbsp nbsp nbsp nbsp nbsp))
+ nbsp
+ ,@(super render-element e part ht))]
[(target-url? style)
(if (current-no-links)
(super render-element e part ht)
diff --git a/collects/scribble/manual.ss b/collects/scribble/manual.ss
index 076bb0e382..7a543152e3 100644
--- a/collects/scribble/manual.ss
+++ b/collects/scribble/manual.ss
@@ -480,6 +480,20 @@
(define max-proto-width 65)
+ (define (name-this-object type-sym)
+ (to-element
+ (string->symbol
+ (regexp-replace
+ #rx"(%|<%>|-mixin)$"
+ (format "_a~a-~s"
+ (if (member
+ (string-ref (symbol->string type-sym) 0)
+ '(#\a #\e #\i #\o #\u))
+ "n"
+ "")
+ type-sym)
+ ""))))
+
(define (*defproc mode within-id
stx-ids prototypes arg-contractss result-contracts content-thunk)
(let ([spacer (hspace 1)]
@@ -564,17 +578,7 @@
(make-element #f
(list (scheme send)
(hspace 1)
- (to-element (string->symbol
- (regexp-replace
- #rx"(%|<%>|-mixin)$"
- (format "a~a-~s"
- (if (member
- (string-ref (symbol->string (syntax-e within-id)) 0)
- '(#\a #\e #\i #\o #\u))
- "n"
- "")
- (syntax-e within-id))
- "")))
+ (name-this-object (syntax-e within-id))
(hspace 1)
(if first?
(let* ([mname (car prototype)]
@@ -1225,6 +1229,7 @@
defmethod*
methspec
methimpl
+ this-obj
include-class)
(define-syntax-parameter current-class #f)
@@ -1417,5 +1422,14 @@
(syntax-rules ()
[(_ body ...) (make-spec (lambda () (list (italic "Specification:") body ...)))]))
+ (define (*this-obj cname)
+ (name-this-object cname))
+
+ (define-syntax (this-obj stx)
+ (syntax-case stx ()
+ [(_)
+ (with-syntax ([cname (syntax-parameter-value #'current-class)])
+ #'(*this-obj 'cname))]))
+
;; ----------------------------------------
)
diff --git a/collects/scribblings/gui/add-color-intf.scrbl b/collects/scribblings/gui/add-color-intf.scrbl
new file mode 100644
index 0000000000..8640c47f17
--- /dev/null
+++ b/collects/scribblings/gui/add-color-intf.scrbl
@@ -0,0 +1,78 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@definterface[add-color<%> ()]{
+
+An @scheme[add-color<%>] object is used to additively change the RGB
+ values of a @scheme[color%] object. An @scheme[add-color<%>] object
+ only exists within a @scheme[style-delta%] object.
+
+See also @method[style-delta% get-foreground-add] and
+ @method[style-delta% get-background-add].
+
+
+
+@defmethod[(get [r (box/c (integer-in -1000 1000))]
+ [g (box/c (integer-in -1000 1000))]
+ [b (box/c (integer-in -1000 1000))])
+ void?]{
+
+Gets all of the additive values.
+
+@boxisfill[(scheme r) @elem{the additive value for the red component of the color}]
+@boxisfill[(scheme g) @elem{the additive value for the green component of the color}]
+@boxisfill[(scheme b) @elem{the additive value for the blue component of the color}]
+
+}
+
+@defmethod[(get-b)
+ (integer-in -1000 1000)]{
+
+Gets the additive value for the blue component of the color.
+
+}
+
+@defmethod[(get-g)
+ (integer-in -1000 1000)]{
+
+Gets the additive value for the green component of the color.
+
+}
+
+@defmethod[(get-r)
+ (integer-in -1000 1000)]{
+
+Gets the additive value for the red component of the color.
+
+}
+
+@defmethod[(set [r (integer-in -1000 1000)]
+ [g (integer-in -1000 1000)]
+ [b (integer-in -1000 1000)])
+ void?]{
+
+Sets all of the additive values.
+
+}
+
+@defmethod[(set-b [v (integer-in -1000 1000)])
+ void?]{
+
+Sets the additive value for the blue component of the color.
+
+}
+
+@defmethod[(set-g [v (integer-in -1000 1000)])
+ void?]{
+
+Sets the additive value for the green component of the color.
+
+}
+
+@defmethod[(set-r [v (integer-in -1000 1000)])
+ void?]{
+
+Sets the additive value for the red component of the color.
+
+}}
+
diff --git a/collects/scribblings/gui/bitmap-class.scrbl b/collects/scribblings/gui/bitmap-class.scrbl
new file mode 100644
index 0000000000..6a4a347089
--- /dev/null
+++ b/collects/scribblings/gui/bitmap-class.scrbl
@@ -0,0 +1,250 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[bitmap% object% ()]{
+
+A @scheme[bitmap%] object is a pixel-based image, either
+ monochrome or color.
+
+Sometimes, a bitmap object creation fails in a low-level manner. In
+ that case, the @method[bitmap% ok?] method returns @scheme[#f], and
+ the bitmap cannot be supplied to methods that consume or operate on
+ bitmaps (otherwise, @|MismatchExn|).
+
+
+@defconstructor*/make[(([width (integer-in 1 10000)]
+ [height (integer-in 1 10000)]
+ [monochrome? any/c #f])
+ ([filename path-string?]
+ [kind (one-of/c 'unknown 'unknown/mask
+ 'gif 'gif/mask 'jpeg 'png 'png/mask
+ 'xbm 'xpm 'bmp 'pict)
+ 'unknown]
+ [bg-color (or/c (is-a?/c color%) false/c) #f])
+ ([bits bytes?]
+ [width (integer-in 1 10000)]
+ [height (integer-in 1 10000)]))]{
+
+When @scheme[with] and @scheme[height] are provided: Creates a new
+ bitmap. If @scheme[monochrome?] is @scheme[#f], the bitmap matches
+ the display depth of the screen. The initial content of the bitmap is
+ undefined.
+
+When @scheme[filename] is provided: Creates a bitmap from a file,
+ where @scheme[kind] specifies the kind of image file. See
+ @method[bitmap% load-file] for details.
+
+
+When a @scheme[bits] byte string is provided: Creates a monochrome
+ bitmap from an array of bit values, where each byte in @scheme[bits]
+ specifies eight bits, and padding bits are added so that each bitmap
+ line starts on a character boundary. A @scheme[1] bit value indicates
+ black, and @scheme[0] indicates white. If @scheme[width] times
+ @scheme[height] is larger than 8 times the length of @scheme[bits],
+ @|MismatchExn|.
+
+
+}
+
+@defmethod[(get-argb-pixels [x real?]
+ [y real?]
+ [width (integer-in 1 10000)]
+ [height (integer-in 1 10000)]
+ [pixels (and/c byte-string? mutable?)]
+ [alpha? any/c @scheme[#f]])
+ void?]{
+
+Produces the same result as @xmethod[bitmap-dc% get-pixel] with the
+bitmap selected into the DC, but the bitmap does not have to be
+selected anywhere (and this method works even if the bitmap is
+selected into another DC, attached as a button label, etc.).
+
+}
+
+@defmethod[(get-depth)
+ nonnegative-exact-integer?]{
+
+Gets the color depth of the bitmap. See also @method[bitmap%
+is-color?].
+
+}
+
+@defmethod[(get-gl-config [config (is-a?/c gl-config%)])
+ void?]{
+
+Returns a copy of this bitmap's requested OpenGL configuration. See
+ also @method[bitmap% set-gl-config].
+
+}
+
+@defmethod[(get-height)
+ (integer-in 1 10000)]{
+
+Gets the height of the bitmap in pixels.
+
+}
+
+@defmethod[(get-loaded-mask)
+ (or/c (is-a?/c bitmap%) false/c)]{
+
+Returns a mask bitmap that is stored with this bitmap.
+
+When a GIF file is loaded with @scheme['gif/mask] or
+ @scheme['unknown/mask] and the file contains a transparent ``color,''
+ a mask bitmap is generated to identify the transparent pixels. The
+ mask bitmap is monochrome, with white pixels where the loaded bitmap
+ is transparent and black pixels everywhere else.
+
+When a PNG file is loaded with @scheme['png/mask] or
+ @scheme['unknown/mask] and the file contains a mask or alpha channel,
+ a mask bitmap is generated to identify the mask or alpha channel. If
+ the file contains a mask or an alpha channel with only extreme
+ values, the mask bitmap is monochrome, otherwise it is grayscale
+ (representing the alpha channel inverted).
+
+The mast bitmap is @italic{not} used automatically by drawing
+ routines. The mask bitmap can be extracted and supplied explicitly as
+ a mask (e.g., as the sixth argument to @method[dc<%>
+ draw-bitmap]). The mask bitmap is used by @method[bitmap% save-file]
+ when saving a bitmap as @scheme['png] if the mask has the same
+ dimensions as the saved bitmap. The mask bitmap is also used
+ automatically when the bitmap is a control label.
+
+}
+
+@defmethod[(get-width)
+ (integer-in 1 10000)]{
+
+Gets the width of the bitmap in pixels.
+
+}
+
+@defmethod[(is-color?)
+ boolean?]{
+
+Returns @scheme[#f] if the bitmap is monochrome, @scheme[#t] otherwise.
+
+}
+
+@defmethod[(load-file [name pat-string?]
+ [kind (one-of/c 'unknown 'unknown/mask
+ 'gif 'gif/mask 'jpeg 'png 'png/mask
+ 'xbm 'xpm 'bmp 'pict)
+ 'unknown]
+ [bg-color (or/c (is-a?/c color%) false/c) #f])
+ boolean?]{
+
+Loads a bitmap from a file. If the bitmap is in use by a
+ @scheme[bitmap-dc%] object or a control, the bitmap file is not
+ loaded. The bitmap changes its size and depth to match that of
+ the loaded image.
+
+The @scheme[kind] argument specifies the file's format:
+
+@itemize{
+@item{@scheme['unknown] --- examine the file to determine its format}
+@item{@scheme['unknown/mask] --- like @scheme['unknown], but see @method[bitmap% get-loaded-mask]}
+@item{@scheme['gif] --- load a GIF bitmap file (X, Windows, Mac OS X)}
+@item{@scheme['gif/mask] --- like @scheme['gif], but see @method[bitmap% get-loaded-mask] (X, Windows, Mac OS X)}
+@item{@scheme['jpeg] --- load a JPEG bitmap file (X, Windows, Mac OS X)}
+@item{@scheme['png] --- load a PNG bitmap file (X, Windows, Mac OS X)}
+@item{@scheme['png/mask] --- like @scheme['png], but see @method[bitmap% get-loaded-mask] (X, Windows, Mac OS X)}
+@item{@scheme['xbm] --- load an X bitmap file (X, Windows, Mac OS X); creates a monochrome bitmap}
+@item{@scheme['xpm] --- load an XPM bitmap file (X, Windows, Mac OS X)}
+@item{@scheme['bmp] --- load a Windows bitmap file (X, Windows, Mac OS X)}
+@item{@scheme['pict] --- load a PICT bitmap file (Mac OS X)}
+}
+
+An XBM image is always loaded as a monochrome bitmap. A 1-bit
+ grayscale PNG without a mask or alpha channel is also loaded as a
+ monochrome bitmap. An image in any other format is always loaded as a
+ bitmap that matches the depth of the screen.
+
+For PNG loading, if @scheme[bg-color] is not @scheme[#f], then it is
+ combined with the file's alpha channel or mask (if any) while loading
+ the image; in this case, no separate mask bitmap is generated, even
+ if @scheme['unknown/mask] or @scheme['png/mask] is specified for the
+ format. If the format is specified as @scheme['unknown] or
+ @scheme['png] and @scheme[bg-color] is not specified, the PNG file is
+ consulted for a background color to use for loading, and white is
+ used if no background color is indicated in the file.
+
+@index["gamma correction"]{In} all PNG-loading modes, gamma correction
+ is applied when the file provides a gamma value, otherwise gamma
+ correction is not applied. The current display's gamma factor is
+ determined by the @ResourceFirst{gamma} (see @|mrprefsdiscuss|) if it
+ is set, or else by the @indexed-envvar{SCREEN_GAMMA} environment
+ variable if it is defined. If the preference and environment variable
+ are both undefined, a platform-specific default is used.
+
+}
+
+@defmethod[(ok?)
+ boolean?]{
+
+Returns @scheme[#t] if the bitmap is usable (created or changed
+ successfully). If @scheme[#f] is returned, the bitmap cannot be
+ supplied to methods that consume or operate on bitmaps (otherwise,
+ @|MismatchExn|).
+
+}
+
+@defmethod[(save-file [name pat-string?]
+ [kind (one-of/c 'png 'jpeg 'xbm 'xpm 'bmp)]
+ [quality (integer-in 0 100) 75])
+ boolean?]{
+
+Saves a bitmap in the named file.
+
+The @scheme[kind] argument determined the type of file that is created,
+ one of:
+
+@itemize{
+
+ @item{@scheme['png] --- save a PNG file (X, Windows, Mac OS X)}
+
+ @item{@scheme['jpeg] --- save a JPEG file (X, Windows, Mac OS X)}
+
+ @item{@scheme['xbm] --- save an X bitmap file (X, Windows, Mac OS X)}
+
+ @item{@scheme['xpm] --- save an XPM bitmap file (X, Windows, Mac OS X)}
+
+ @item{@scheme['bmp] --- save a Windows bitmap file (Windows)}
+
+}
+
+The @scheme[quality] argument is used only for saving as @scheme['jpeg], in
+ which case it specifies the trade-off between image precision (high
+ quality matches the content of the @scheme[bitmap%] object more
+ precisely) and size (low quality is smaller).
+
+When saving as @scheme['png], if @method[bitmap% get-loaded-mask]
+returns a bitmap of the same size as this one, a grayscale version is
+included in the PNG file as the alpha channel.
+
+A monochrome bitmap saved as @scheme['png] without a mask bitmap
+ produces a 1-bit grayscale PNG file (which , when read with
+ @method[bitmap% load-file], creates a monochrome @scheme[bitmap%]
+ object.)
+
+}
+
+@defmethod[(set-gl-config [config (is-a?/c gl-config%)])
+ void?]{
+
+Sets the requested OpenGL configuration for this bitmap. The
+ configuration is used when the bitmap selected into a drawing
+ context, and then a GL context is created for the drawing context.
+
+The given @scheme[gl-config%] object is copied, so that changes to
+ the object do not affect the bitmap's configuration.
+
+}
+
+@defmethod[(set-loaded-mask [mask (or/c (is-a?/c bitmap%) false/c)])
+ void?]{
+
+See @method[bitmap% get-loaded-mask].
+
+}}
+
diff --git a/collects/scribblings/gui/bitmap-dc-class.scrbl b/collects/scribblings/gui/bitmap-dc-class.scrbl
new file mode 100644
index 0000000000..9fbd64b578
--- /dev/null
+++ b/collects/scribblings/gui/bitmap-dc-class.scrbl
@@ -0,0 +1,170 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[bitmap-dc% object% (dc<%>)]{
+
+A @scheme[bitmap-dc%] object allows drawing directly into a bitmap. A
+ @scheme[bitmap%] object must be supplied at initialization or
+ installed into a bitmap DC using @method[bitmap-dc% set-bitmap]
+ before any other method of the DC is called, except @method[dc<%>
+ get-text-extent], @method[dc<%> get-char-height], or @method[dc<%>
+ get-char-width]. If any other @scheme[bitmap-dc%] method is called
+ before a bitmap is selected, the method call is ignored.
+
+Drawing to a @scheme[bitmap-dc%] with a color bitmap is guaranteed to
+ produce the same result as drawing into a @scheme[canvas%] instance
+ (with appropriate clipping and offsets). Thus, a @scheme[bitmap-dc%]
+ can be used for offscreen staging of canvas content.
+
+
+@defconstructor[([bitmap (or/c (is-a?/c bitmap%) false/c)])]{
+
+Creates a new memory DC. If @scheme[bitmap] is not @scheme[#f], it is
+ installed into the DC so that drawing commands on the DC draw to
+ @scheme[bitmap]. Otherwise, no bitmap is installed into the DC and
+ @method[bitmap-dc% set-bitmap] must be called before any other method
+ of the DC is called.
+
+}
+
+@defmethod[(draw-bitmap-section-smooth [source (is-a?/c bitmap%)]
+ [dest-x real?]
+ [dest-y real?]
+ [dest-width (and/c real? (not/c negative?))]
+ [dest-height (and/c real? (not/c negative?))]
+ [src-x real?]
+ [src-y real?]
+ [src-width (and/c real? (not/c negative?))]
+ [src-height (and/c real? (not/c negative?))]
+ [mask (or/c (is-a?/c bitmap%) false/c)])
+ boolean?]{
+
+Display part of a bitmap with smooth scaling. For most platforms, this
+ method produces better results than adjusting the scale of a drawing
+ context before using @method[dc<%> draw-bitmap] and @method[dc<%>
+ draw-bitmap-section], but this method is much slower.
+
+}
+
+@defmethod[(get-argb-pixels [x real?]
+ [y real?]
+ [width (integer-in 1 10000)]
+ [height (integer-in 1 10000)]
+ [pixels (and/c bytes? (not/c immutable?))]
+ [alpha? any/c @scheme[#f]])
+ void?]{
+
+Gets a rectangle of pixels in the bitmap, subject to the same rules
+ and performance characteristics of @method[bitmap-dc% get-pixel],
+ except that the block get is likely to be faster than the sequence of
+ individual gets. Also, the @scheme[bitmap%] class also provides the
+ same method directly, so it is not necessary to select a bitmap into
+ a DC to extracts its pixel values.
+
+The pixel RGB values are copied into @scheme[pixels]. The first byte
+ represents an alpha value of the pixel at (@scheme[x], @scheme[y]),
+ the second byte represents a red value of the pixel at (@scheme[x],
+ @scheme[y]), the third byte is the blue value, etc. In this way, the
+ first @math{@scheme[width] * @scheme[height] *4} bytes of
+ @scheme[pixels] are set to reflect the current pixel values in the
+ DC. The pixels are in row-major order, left to right then top to
+ bottom.
+
+If @scheme[alpha?] is false, then the alpha value for each pixel is
+ set to 255. If @scheme[alpha?] is true, then @italic{only} the alpha
+ value is set for each pixel, based on each pixel's value. Thus, the
+ same @scheme[pixels] byte string is in general filled from two bitmaps:
+ one (the main image) for the pixel values and one (the mask) for the
+ alpha values.
+
+}
+
+@defmethod[(get-bitmap)
+ (or/c (is-a?/c bitmap%) false/c)]{
+
+Gets the bitmap currently installed in the DC, or @scheme[#f] if no
+ bitmap is installed. See @method[bitmap-dc% set-bitmap] for more
+ information.
+
+}
+
+@defmethod[(get-pixel [x real?]
+ [y real?]
+ [color (is-a?/c color%)])
+ boolean?]{
+
+Fills @scheme[color] with the color of the current pixel at position
+(@scheme[x], @scheme[y]) in the drawing context. If the color is
+successfully obtained, the return value is @scheme[#t], otherwise the
+result is @scheme[#f].
+
+Under X, interleaving drawing commands with @method[bitmap-dc%
+get-pixel] calls (for the same @scheme[bitmap-dc%] object) incurs a
+substantial performance penalty, except for interleaved calls to
+@method[bitmap-dc% set-pixel], @method[bitmap-dc% set-argb-pixels],
+and @method[bitmap-dc% get-argb-pixels].
+
+}
+
+@defmethod[(set-argb-pixels [x real?]
+ [y real?]
+ [width (integer-in 1 10000)]
+ [height (integer-in 1 10000)]
+ [pixels bytes?]
+ [alpha? any/c @scheme[#f]])
+ void?]{
+
+
+Sets a rectangle of pixels in the bitmap, subject to the same
+ rules and performance characteristics of
+@method[bitmap-dc% set-pixel], except that the block set is likely to be faster than the
+ sequence of individual sets.
+
+The pixel RGB values are taken from @scheme[pixels]. The first byte
+ represents an alpha value, the second byte represents a red value to
+ used for the pixel at (@scheme[x], @scheme[y]), the third byte is a blue
+ value, etc. In this way, the first
+ @math{@scheme[width] * @scheme[height] * 4} bytes of @scheme[pixels]
+ determine the new pixel values in the DC. The pixels are in row-major
+ order, left to right then top to bottom.
+
+If @scheme[alpha?] is false, then the alpha value for each pixel is
+ ignored. If @scheme[alpha?] is true, then @italic{only} the each
+ pixel is set based @italic{only} on the alpha value. Thus, the same
+ @scheme[pixels] byte string is in general used with two bitmaps, one
+ (the main image) for the pixel values and one (the mask) for the
+ alpha values.
+
+}
+
+@defmethod[(set-bitmap [bitmap (or/c (is-a?/c bitmap%) false/c)])
+ void?]{
+
+Installs a bitmap into the DC, so that drawing operations on the bitmap
+ DC draw to the bitmap. A bitmap is removed from a DC by setting the
+ bitmap to @scheme[#f].
+
+A bitmap can be selected into at most one bitmap DC, and only when it
+ is not used by a control (as a label) or in a @scheme[pen%] or
+ @scheme[brush%] (as a stipple). If the argument to @method[bitmap-dc%
+ set-bitmap] is already in use by another DC, a control, a
+ @scheme[pen%], or a @scheme[brush%], @|MismatchExn|.
+
+}
+
+@defmethod[(set-pixel [x real?]
+ [y real?]
+ [color (is-a?/c color%)])
+ void?]{
+
+Sets a pixel in the bitmap.
+
+The current clipping region might not affect the pixel change. Under
+ X, interleaving drawing commands with @method[bitmap-dc% set-pixel]
+ calls (for the same @scheme[bitmap-dc%] object) incurs a substantial
+ performance penalty, except for interleaved calls to
+ @method[bitmap-dc% get-pixel], @method[bitmap-dc% get-argb-pixels],
+ and @method[bitmap-dc% set-argb-pixels].
+
+}}
+
diff --git a/collects/scribblings/gui/blurbs.ss b/collects/scribblings/gui/blurbs.ss
index 4c1fc526b0..db486c9624 100644
--- a/collects/scribblings/gui/blurbs.ss
+++ b/collects/scribblings/gui/blurbs.ss
@@ -52,12 +52,6 @@
@elem{The bitmap label is installed only
if the control was originally created with a bitmap label.})
- (define (NotDCRelated)
- @elem{A path is not connected to any particular @scheme[dc<%>] object, so
- setting a @scheme[dc<%>] origin or scale does not affect path
- operations. Instead, a @scheme[dc<%>]'s origin and scale apply at the
- time that the path is drawn or used to set a region.})
-
(define (popupmenuinfo what other more)
(make-splice
(list*
@@ -250,7 +244,7 @@ information@|details|, even if the editor currently has delayed refreshing (see
@elem{snip @techlink{position}}))
(define (colorName name name2 r g b)
- name)
+ (make-element `(show-color ,r ,g ,b) (list (to-element (bytes->string/latin-1 name)))))
(define (Resource s)
@elem{@to-element[`(quote ,(string->symbol (string-append "MrEd:" s)))]
@@ -271,5 +265,10 @@ information@|details|, even if the editor currently has delayed refreshing (see
"smaller"
@elem{the editor is @|b|-aligned in the snip}))
+ (define (boxisfill which what)
+ @elem{The @|which| box is filled with @|what|.})
+ (define (boxisfillnull which what)
+ @elem{The @|which| box is filled with @|what|, unless @|which| is @scheme[#f].})
+
)
diff --git a/collects/scribblings/gui/brush-class.scrbl b/collects/scribblings/gui/brush-class.scrbl
new file mode 100644
index 0000000000..2741c22878
--- /dev/null
+++ b/collects/scribblings/gui/brush-class.scrbl
@@ -0,0 +1,213 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[brush% object% ()]{
+
+A brush is a drawing tool with a color and a style that is used for
+ filling in areas, such as the interior of a rectangle or ellipse. On
+ a monochrome display, all non-white brushes are drawn as black.
+
+In addition to its color and style, a brush can have a stipple bitmap.
+ This stipple is used only in unsmoothed mode (see @method[dc<%>
+ set-smoothing]) or in a PostScript drawing context. Painting with a
+ stipple brush is similar to calling @method[dc<%> draw-bitmap] with
+ the stipple bitmap in the filled region, except that the bitmap may
+ not be scaled in the same way (depending on the platform and device).
+
+A brush's style is one of the following:
+
+@itemize{
+
+ @item{@indexed-scheme['transparent] --- Draws with no effect (on the
+ interior of the drawn shape).}
+
+ @item{@indexed-scheme['solid] --- Draws using the brush's color. If a
+ monochrome stipple is installed into the brush, black pixels
+ from the stipple are transferred to the destination using the
+ brush's color, and white pixels from the stipple are not
+ transferred.}
+
+ @item{@indexed-scheme['opaque] --- Same as @scheme['solid], except when a
+ monochrome stipple is installed for unsmoothed or PostScript
+ drawing; in that case, white pixels from the stipple are
+ transferred to the destination using the destination's
+ background color.}
+
+ @item{@indexed-scheme['xor] --- In a smoothing mode or if a color
+ stipple is installed, @scheme['xor] is treated as
+ @scheme['solid]. Otherwise, the brush's color or colored
+ (monochrome) stipple is xor-ed with existing destination pixel
+ values. The @scheme['xor] mapping is unspecified for arbitrary
+ color combinations, but the mapping provides two guarantees:
+
+ @itemize{
+
+ @item{Black-and-white drawing to a color or monochrome
+ destination always works as expected: black xor white = black,
+ white xor black = black, black xor black = white, and white xor
+ white = white.}
+
+ @item{Performing the same drawing operation twice in a row with
+ @scheme['xor] is equivalent to a no-op.}
+
+ }}
+
+ @item{@indexed-scheme['hilite] --- In unsmoothed mode, existing
+ destination pixels are ``highlighted'' in a platform-specific
+ way when the brush color is black. Under Windows and X for a
+ color drawing context, the inverted RGB components of
+ destination pixel are combined with the RGB components of the
+ system-wide highlight color using a bitwise ``or'', and the
+ combination is used. (Under X, the color is specified by the
+ @ResourceFirst{hiliteColor} preference; see @|mrprefsdiscuss|.)
+ Under Mac OS X for a color drawing context, the inverted RGB
+ components of the system-wide highlight color are subtracted
+ from the RGB components of each destination pixel, and the
+ difference (or 0 for a negative result) is used. For any
+ monochrome drawing context, @scheme['hilite] is the same as
+ @scheme['xor]. For PostScript output, @scheme['hilite] uses a
+ stipple that is an array of small dots (essentially a
+ halftone), otherwise @scheme['hilite] is treated like
+ @scheme['solid] in a smoothing mode.}
+
+ @item{@indexed-scheme['panel] --- In unsmoothed mode, draws with the
+ same color and pattern as a top-level panel background, if the
+ brush's color is the same as the color returned by
+ @scheme[get-panel-background] and if the brush has no
+ stipple. To create a @scheme[canvas%] object that is drawn like
+ a control, use the @scheme['transparent] canvas style instead,
+ because certain kinds of nested panels have different
+ background colors (e.g., a @scheme[tab-panel%] under Mac OS
+ X). In a smoothing mode, @scheme['panel] is treated as
+ @scheme['solid].}
+
+ @item{The following modes correspond to built-in stipples drawn in
+ @scheme['solid] mode:
+
+ @itemize{
+ @item{@indexed-scheme['bdiagonal-hatch] --- diagonal lines, top-left to bottom-right}
+ @item{@indexed-scheme['crossdiag-hatch] --- crossed diagonal lines}
+ @item{@indexed-scheme['fdiagonal-hatch] --- diagonal lines, top-right to bottom-left}
+ @item{@indexed-scheme['cross-hatch] --- crossed horizontal and vertical lines}
+ @item{@indexed-scheme['horizontal-hatch] --- horizontal lines}
+ @item{@indexed-scheme['vertical-hatch] --- vertical lines}
+ }
+
+ However, when a specific stipple is installed into the brush
+ for when drawing with a smoothing mode into a non-PostScript
+ context, the above modes are ignored and @scheme['solid] is
+ used, instead.}
+
+}
+
+@index['("drawing" "outlines")]{To} draw outline shapes (such as
+ unfilled boxes and ellipses), use the @scheme['transparent] brush
+ style. See @method[brush% set-style] for more information about
+ styles.
+
+To avoid creating multiple brushes with the same characteristics, use
+ the global @scheme[brush-list%] object
+ @indexed-scheme[the-brush-list], or provide a color and style to
+ @xmethod[dc<%> set-brush].
+
+
+@defconstructor*/make[(()
+ ([color (is-a?/c color%)]
+ [style (one-of/c 'transparent 'solid 'opaque
+ 'xor 'hilite 'panel
+ 'bdiagonal-hatch 'crossdiag-hatch
+ 'fdiagonal-hatch 'cross-hatch
+ 'horizontal-hatch 'vertical-hatch)])
+ ([color-name string?]
+ [style (one-of/c 'transparent 'solid 'opaque
+ 'xor 'hilite 'panel
+ 'bdiagonal-hatch 'crossdiag-hatch
+ 'fdiagonal-hatch 'cross-hatch
+ 'horizontal-hatch 'vertical-hatch)]))]{
+
+When no argument are provided, the result is a solid black brush.
+ Otherwise, the result is a brush with the given color and style. For
+ the case that the color is specified using a name, see
+ @scheme[color-database<%>] for information about color names; if the
+ name is not known, the brush's color is black.
+
+}
+
+@defmethod[(get-color)
+ (is-a?/c color%)]{
+
+Returns the brush's color.
+
+}
+
+@defmethod[(get-stipple)
+ (or/c (is-a?/c bitmap%) false/c)]{
+
+Gets the stipple bitmap, or @scheme[#f] if the brush has no stipple.
+
+}
+
+@defmethod[(get-style)
+ (one-of/c 'transparent 'solid 'opaque
+ 'xor 'hilite 'panel
+ 'bdiagonal-hatch 'crossdiag-hatch
+ 'fdiagonal-hatch 'cross-hatch
+ 'horizontal-hatch 'vertical-hatch)]{
+
+Returns the brush's style. See @scheme[brush%] for information about
+brush styles.
+
+}
+
+@defmethod*[([(set-color [color (is-a?/c color%)])
+ void?]
+ [(set-color [color-name string?])
+ void?]
+ [(set-color [red (integer-in 0 255)]
+ [green (integer-in 0 255)]
+ [blue (integer-in 0 255)])
+ void?])]{
+
+Sets the brush's color. A brush cannot be modified if it was obtained
+ from a @scheme[brush-list%] or while it is selected into a drawing
+ context.
+
+For the case that the color is specified using a string, see
+ @scheme[color-database<%>] for information about color names.
+
+}
+
+@defmethod[(set-stipple [bitmap (or/c (is-a?/c bitmap%) false/c)])
+ void?]{
+
+Sets or removes the stipple bitmap, where @scheme[#f] removes the
+ stipple. See @scheme[brush%] for information about drawing with
+ stipples.
+
+A bitmap cannot be used as a stipple if it is selected into a
+ @scheme[bitmap-dc%] object; if the given bitmap is selected into a
+ @scheme[bitmap-dc%] object, @|MismatchExn|. A brush cannot be
+ modified if it was obtained from a @scheme[brush-list%] or while it
+ is selected into a drawing context.
+
+A pen's stipple is not used in a smoothing mode, except for a
+ @scheme[post-script-dc%] (which is always in a smoothing mode).
+
+}
+
+@defmethod[(set-style [style (one-of/c 'transparent 'solid 'opaque
+ 'xor 'hilite 'panel
+ 'bdiagonal-hatch 'crossdiag-hatch
+ 'fdiagonal-hatch 'cross-hatch
+ 'horizontal-hatch 'vertical-hatch)])
+ void?]{
+
+Sets the brush's style. See
+@scheme[brush%] for information about the possible styles.
+
+A brush cannot be modified if it was obtained from a
+ @scheme[brush-list%] or while it is selected into a drawing
+ context.
+
+}}
+
diff --git a/collects/scribblings/gui/brush-list-class.scrbl b/collects/scribblings/gui/brush-list-class.scrbl
new file mode 100644
index 0000000000..e4d4159dc0
--- /dev/null
+++ b/collects/scribblings/gui/brush-list-class.scrbl
@@ -0,0 +1,40 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[brush-list% object% ()]{
+
+A @scheme[brush-list%] object maintains a list of @scheme[brush%]
+ objects to avoid creating brushes repeatedly. A @scheme[brush%]
+ object in a brush list cannot be mutated.
+
+A global brush list, @scheme[the-brush-list], is created
+ automatically.
+
+
+@defconstructor/make[()]{
+
+Creates an empty brush list.
+
+}
+
+@defmethod*[([(find-or-create-brush [color (is-a?/c color%)]
+ [style (one-of/c 'transparent 'solid 'opaque
+ 'xor 'hilite 'panel
+ 'bdiagonal-hatch 'crossdiag-hatch
+ 'fdiagonal-hatch 'cross-hatch
+ 'horizontal-hatch 'vertical-hatch)])
+ (is-a?/c brush%)]
+ [(find-or-create-brush [color-name string?]
+ [style (one-of/c 'transparent 'solid 'opaque
+ 'xor 'hilite 'panel
+ 'bdiagonal-hatch 'crossdiag-hatch
+ 'fdiagonal-hatch 'cross-hatch
+ 'horizontal-hatch 'vertical-hatch)])
+ (or/c (is-a?/c brush%) false/c)])]{
+
+Finds a brush of the given specification, or creates one and adds it
+ to the list. See @scheme[brush%] for a further explanation of the
+ arguments, which are the same as @scheme[brush%]'s initialization
+ arguments.
+
+}}
diff --git a/collects/scribblings/gui/color-class.scrbl b/collects/scribblings/gui/color-class.scrbl
new file mode 100644
index 0000000000..abfd9b4b0e
--- /dev/null
+++ b/collects/scribblings/gui/color-class.scrbl
@@ -0,0 +1,70 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[color% object% ()]{
+
+A color is an object representing a red-green-blue (RGB) combination
+ of primary colors, and is used to determine drawing colors. Each red,
+ green, or blue component of the color is in the range 0 to 255,
+ inclusive. For example, (0, 0, 0) is black, (255, 255, 255) is
+ white, and (255, 0, 0) is red.
+
+See @scheme[color-database<%>] for information about obtaining a color
+object using a color name.
+
+
+@defconstructor*/make[(([red (integer-in 0 255)]
+ [green (integer-in 0 255)]
+ [blue (integer-in 0 255)])
+ ([color-name string?]))]{
+
+Creates a new color with the given RGB values, or matching the given
+ color name (using ``black'' if the name is not recognized). See
+ @scheme[color-database<%>] for more information on color names.
+
+}
+
+@defmethod[(blue)
+ (integer-in 0 255)]{
+
+Returns the blue component of the color.
+
+}
+
+@defmethod[(copy-from [src (is-a?/c color%)])
+ (is-a?/c color%)]{
+
+Copies the RGB values of another color object to this one, returning
+ this object as the result.
+
+}
+
+@defmethod[(green)
+ (integer-in 0 255)]{
+
+Returns the green component of the color.
+
+}
+
+@defmethod[(ok?)
+ boolean?]{
+
+Returns @scheme[#t] if the color object is valid.
+
+}
+
+@defmethod[(red)
+ (integer-in 0 255)]{
+
+Returns the red component of the color.
+
+}
+
+@defmethod[(set [red (integer-in 0 255)]
+ [green (integer-in 0 255)]
+ [blue (integer-in 0 255)])
+ void?]{
+
+Sets the three (red, green, and blue) component values of the color.
+}}
+
diff --git a/collects/scribblings/gui/color-database-intf.scrbl b/collects/scribblings/gui/color-database-intf.scrbl
new file mode 100644
index 0000000000..287ec732e4
--- /dev/null
+++ b/collects/scribblings/gui/color-database-intf.scrbl
@@ -0,0 +1,211 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@definterface[color-database<%> ()]{
+
+The global @indexed-scheme[the-color-database] object is an instance of
+ @scheme[color-database<%>]. It maintains a database of standard RGB
+ colors for a predefined set of named colors (such as ``black'' and
+ ``light grey'').
+
+The following colors are in the database:
+
+@schemeblock[
+#, @colorName[#"Orange Red" #"OrangeRed" 255 69 0]
+#, @colorName[#"OrangeRed" #"OrangeRed" 255 69 0]
+#, @colorName[#"Tomato" #"Tomato" 255 99 71]
+#, @colorName[#"DarkRed" #"DarkRed" 139 0 0]
+#, @colorName[#"Red" #"Red" 255 0 0]
+#, @colorName[#"Firebrick" #"Firebrick" 178 34 34]
+#, @colorName[#"Crimson" #"Crimson" 220 20 60]
+#, @colorName[#"DeepPink" #"DeepPink" 255 20 147]
+#, @colorName[#"Maroon" #"Maroon" 176 48 96]
+#, @colorName[#"Indian Red" #"IndianRed" 205 92 92]
+#, @colorName[#"IndianRed" #"IndianRed" 205 92 92]
+#, @colorName[#"Medium Violet Red" #"MediumVioletRed" 199 21 133]
+#, @colorName[#"MediumVioletRed" #"MediumVioletRed" 199 21 133]
+#, @colorName[#"Violet Red" #"VioletRed" 208 32 144]
+#, @colorName[#"VioletRed" #"VioletRed" 208 32 144]
+#, @colorName[#"LightCoral" #"LightCoral" 240 128 128]
+#, @colorName[#"HotPink" #"HotPink" 255 105 180]
+#, @colorName[#"PaleVioletRed" #"PaleVioletRed" 219 112 147]
+#, @colorName[#"LightPink" #"LightPink" 255 182 193]
+#, @colorName[#"RosyBrown" #"RosyBrown" 188 143 143]
+#, @colorName[#"Pink" #"Pink" 255 192 203]
+#, @colorName[#"Orchid" #"Orchid" 218 112 214]
+#, @colorName[#"LavenderBlush" #"LavenderBlush" 255 240 245]
+#, @colorName[#"Snow" #"Snow" 255 250 250]
+#, @colorName[#"Chocolate" #"Chocolate" 210 105 30]
+#, @colorName[#"SaddleBrown" #"SaddleBrown" 139 69 19]
+#, @colorName[#"Brown" #"Brown" 132 60 36]
+#, @colorName[#"DarkOrange" #"DarkOrange" 255 140 0]
+#, @colorName[#"Coral" #"Coral" 255 127 80]
+#, @colorName[#"Sienna" #"Sienna" 160 82 45]
+#, @colorName[#"Orange" #"Orange" 255 165 0]
+#, @colorName[#"Salmon" #"Salmon" 250 128 114]
+#, @colorName[#"Peru" #"Peru" 205 133 63]
+#, @colorName[#"DarkGoldenrod" #"DarkGoldenrod" 184 134 11]
+#, @colorName[#"Goldenrod" #"Goldenrod" 218 165 32]
+#, @colorName[#"SandyBrown" #"SandyBrown" 244 164 96]
+#, @colorName[#"LightSalmon" #"LightSalmon" 255 160 122]
+#, @colorName[#"DarkSalmon" #"DarkSalmon" 233 150 122]
+#, @colorName[#"Gold" #"Gold" 255 215 0]
+#, @colorName[#"Yellow" #"Yellow" 255 255 0]
+#, @colorName[#"Olive" #"Olive" 128 128 0]
+#, @colorName[#"Burlywood" #"Burlywood" 222 184 135]
+#, @colorName[#"Tan" #"Tan" 210 180 140]
+#, @colorName[#"NavajoWhite" #"NavajoWhite" 255 222 173]
+#, @colorName[#"PeachPuff" #"PeachPuff" 255 218 185]
+#, @colorName[#"Khaki" #"Khaki" 240 230 140]
+#, @colorName[#"DarkKhaki" #"DarkKhaki" 189 183 107]
+#, @colorName[#"Moccasin" #"Moccasin" 255 228 181]
+#, @colorName[#"Wheat" #"Wheat" 245 222 179]
+#, @colorName[#"Bisque" #"Bisque" 255 228 196]
+#, @colorName[#"PaleGoldenrod" #"PaleGoldenrod" 238 232 170]
+#, @colorName[#"BlanchedAlmond" #"BlanchedAlmond" 255 235 205]
+#, @colorName[#"Medium Goldenrod" #"MediumGoldenrod" 234 234 173]
+#, @colorName[#"MediumGoldenrod" #"MediumGoldenrod" 234 234 173]
+#, @colorName[#"PapayaWhip" #"PapayaWhip" 255 239 213]
+#, @colorName[#"MistyRose" #"MistyRose" 255 228 225]
+#, @colorName[#"LemonChiffon" #"LemonChiffon" 255 250 205]
+#, @colorName[#"AntiqueWhite" #"AntiqueWhite" 250 235 215]
+#, @colorName[#"Cornsilk" #"Cornsilk" 255 248 220]
+#, @colorName[#"LightGoldenrodYellow" #"LightGoldenrodYellow" 250 250 210]
+#, @colorName[#"OldLace" #"OldLace" 253 245 230]
+#, @colorName[#"Linen" #"Linen" 250 240 230]
+#, @colorName[#"LightYellow" #"LightYellow" 255 255 224]
+#, @colorName[#"SeaShell" #"SeaShell" 255 245 238]
+#, @colorName[#"Beige" #"Beige" 245 245 220]
+#, @colorName[#"FloralWhite" #"FloralWhite" 255 250 240]
+#, @colorName[#"Ivory" #"Ivory" 255 255 240]
+#, @colorName[#"Green" #"Green" 0 255 0]
+#, @colorName[#"LawnGreen" #"LawnGreen" 124 252 0]
+#, @colorName[#"Chartreuse" #"Chartreuse" 127 255 0]
+#, @colorName[#"Green Yellow" #"GreenYellow" 173 255 47]
+#, @colorName[#"GreenYellow" #"GreenYellow" 173 255 47]
+#, @colorName[#"Yellow Green" #"YellowGreen" 154 205 50]
+#, @colorName[#"YellowGreen" #"YellowGreen" 154 205 50]
+#, @colorName[#"Medium Forest Green" #"MediumForestGreen" 107 142 35]
+#, @colorName[#"OliveDrab" #"OliveDrab" 107 142 35]
+#, @colorName[#"MediumForestGreen" #"MediumForestGreen" 107 142 35]
+#, @colorName[#"Dark Olive Green" #"DarkOliveGreen" 85 107 47]
+#, @colorName[#"DarkOliveGreen" #"DarkOliveGreen" 85 107 47]
+#, @colorName[#"DarkSeaGreen" #"DarkSeaGreen" 143 188 139]
+#, @colorName[#"Lime" #"Lime" 0 255 0]
+#, @colorName[#"Dark Green" #"DarkGreen" 0 100 0]
+#, @colorName[#"DarkGreen" #"DarkGreen" 0 100 0]
+#, @colorName[#"Lime Green" #"LimeGreen" 50 205 50]
+#, @colorName[#"LimeGreen" #"LimeGreen" 50 205 50]
+#, @colorName[#"Forest Green" #"ForestGreen" 34 139 34]
+#, @colorName[#"ForestGreen" #"ForestGreen" 34 139 34]
+#, @colorName[#"Spring Green" #"SpringGreen" 0 255 127]
+#, @colorName[#"SpringGreen" #"SpringGreen" 0 255 127]
+#, @colorName[#"Medium Spring Green" #"MediumSpringGreen" 0 250 154]
+#, @colorName[#"MediumSpringGreen" #"MediumSpringGreen" 0 250 154]
+#, @colorName[#"Sea Green" #"SeaGreen" 46 139 87]
+#, @colorName[#"SeaGreen" #"SeaGreen" 46 139 87]
+#, @colorName[#"Medium Sea Green" #"MediumSeaGreen" 60 179 113]
+#, @colorName[#"MediumSeaGreen" #"MediumSeaGreen" 60 179 113]
+#, @colorName[#"Aquamarine" #"Aquamarine" 112 216 144]
+#, @colorName[#"LightGreen" #"LightGreen" 144 238 144]
+#, @colorName[#"Pale Green" #"PaleGreen" 152 251 152]
+#, @colorName[#"PaleGreen" #"PaleGreen" 152 251 152]
+#, @colorName[#"Medium Aquamarine" #"MediumAquamarine" 102 205 170]
+#, @colorName[#"MediumAquamarine" #"MediumAquamarine" 102 205 170]
+#, @colorName[#"Turquoise" #"Turquoise" 64 224 208]
+#, @colorName[#"LightSeaGreen" #"LightSeaGreen" 32 178 170]
+#, @colorName[#"Medium Turquoise" #"MediumTurquoise" 72 209 204]
+#, @colorName[#"MediumTurquoise" #"MediumTurquoise" 72 209 204]
+#, @colorName[#"Honeydew" #"Honeydew" 240 255 240]
+#, @colorName[#"MintCream" #"MintCream" 245 255 250]
+#, @colorName[#"RoyalBlue" #"RoyalBlue" 65 105 225]
+#, @colorName[#"DodgerBlue" #"DodgerBlue" 30 144 255]
+#, @colorName[#"DeepSkyBlue" #"DeepSkyBlue" 0 191 255]
+#, @colorName[#"CornflowerBlue" #"CornflowerBlue" 100 149 237]
+#, @colorName[#"Steel Blue" #"SteelBlue" 70 130 180]
+#, @colorName[#"SteelBlue" #"SteelBlue" 70 130 180]
+#, @colorName[#"LightSkyBlue" #"LightSkyBlue" 135 206 250]
+#, @colorName[#"Dark Turquoise" #"DarkTurquoise" 0 206 209]
+#, @colorName[#"DarkTurquoise" #"DarkTurquoise" 0 206 209]
+#, @colorName[#"Cyan" #"Cyan" 0 255 255]
+#, @colorName[#"Aqua" #"Aqua" 0 255 255]
+#, @colorName[#"DarkCyan" #"DarkCyan" 0 139 139]
+#, @colorName[#"Teal" #"Teal" 0 128 128]
+#, @colorName[#"Sky Blue" #"SkyBlue" 135 206 235]
+#, @colorName[#"SkyBlue" #"SkyBlue" 135 206 235]
+#, @colorName[#"Cadet Blue" #"CadetBlue" 96 160 160]
+#, @colorName[#"CadetBlue" #"CadetBlue" 95 158 160]
+#, @colorName[#"Dark Slate Gray" #"DarkSlateGray" 47 79 79]
+#, @colorName[#"DarkSlateGray" #"DarkSlateGray" 47 79 79]
+#, @colorName[#"LightSlateGray" #"LightSlateGray" 119 136 153]
+#, @colorName[#"SlateGray" #"SlateGray" 112 128 144]
+#, @colorName[#"Light Steel Blue" #"LightSteelBlue" 176 196 222]
+#, @colorName[#"LightSteelBlue" #"LightSteelBlue" 176 196 222]
+#, @colorName[#"Light Blue" #"LightBlue" 173 216 230]
+#, @colorName[#"LightBlue" #"LightBlue" 173 216 230]
+#, @colorName[#"PowderBlue" #"PowderBlue" 176 224 230]
+#, @colorName[#"PaleTurquoise" #"PaleTurquoise" 175 238 238]
+#, @colorName[#"LightCyan" #"LightCyan" 224 255 255]
+#, @colorName[#"AliceBlue" #"AliceBlue" 240 248 255]
+#, @colorName[#"Azure" #"Azure" 240 255 255]
+#, @colorName[#"Medium Blue" #"MediumBlue" 0 0 205]
+#, @colorName[#"MediumBlue" #"MediumBlue" 0 0 205]
+#, @colorName[#"DarkBlue" #"DarkBlue" 0 0 139]
+#, @colorName[#"Midnight Blue" #"MidnightBlue" 25 25 112]
+#, @colorName[#"MidnightBlue" #"MidnightBlue" 25 25 112]
+#, @colorName[#"Navy" #"Navy" 36 36 140]
+#, @colorName[#"Blue" #"Blue" 0 0 255]
+#, @colorName[#"Indigo" #"Indigo" 75 0 130]
+#, @colorName[#"Blue Violet" #"BlueViolet" 138 43 226]
+#, @colorName[#"BlueViolet" #"BlueViolet" 138 43 226]
+#, @colorName[#"Medium Slate Blue" #"MediumSlateBlue" 123 104 238]
+#, @colorName[#"MediumSlateBlue" #"MediumSlateBlue" 123 104 238]
+#, @colorName[#"Slate Blue" #"SlateBlue" 106 90 205]
+#, @colorName[#"SlateBlue" #"SlateBlue" 106 90 205]
+#, @colorName[#"Purple" #"Purple" 160 32 240]
+#, @colorName[#"Dark Slate Blue" #"DarkSlateBlue" 72 61 139]
+#, @colorName[#"DarkSlateBlue" #"DarkSlateBlue" 72 61 139]
+#, @colorName[#"DarkViolet" #"DarkViolet" 148 0 211]
+#, @colorName[#"Dark Orchid" #"DarkOrchid" 153 50 204]
+#, @colorName[#"DarkOrchid" #"DarkOrchid" 153 50 204]
+#, @colorName[#"MediumPurple" #"MediumPurple" 147 112 219]
+#, @colorName[#"Cornflower Blue" #"CornflowerBlue" 68 64 108]
+#, @colorName[#"Medium Orchid" #"MediumOrchid" 186 85 211]
+#, @colorName[#"MediumOrchid" #"MediumOrchid" 186 85 211]
+#, @colorName[#"Magenta" #"Magenta" 255 0 255]
+#, @colorName[#"Fuchsia" #"Fuchsia" 255 0 255]
+#, @colorName[#"DarkMagenta" #"DarkMagenta" 139 0 139]
+#, @colorName[#"Violet" #"Violet" 238 130 238]
+#, @colorName[#"Plum" #"Plum" 221 160 221]
+#, @colorName[#"Lavender" #"Lavender" 230 230 250]
+#, @colorName[#"Thistle" #"Thistle" 216 191 216]
+#, @colorName[#"GhostWhite" #"GhostWhite" 248 248 255]
+#, @colorName[#"White" #"White" 255 255 255]
+#, @colorName[#"WhiteSmoke" #"WhiteSmoke" 245 245 245]
+#, @colorName[#"Gainsboro" #"Gainsboro" 220 220 220]
+#, @colorName[#"Light Gray" #"LightGray" 211 211 211]
+#, @colorName[#"LightGray" #"LightGray" 211 211 211]
+#, @colorName[#"Silver" #"Silver" 192 192 192]
+#, @colorName[#"Gray" #"Gray" 190 190 190]
+#, @colorName[#"Dark Gray" #"DarkGray" 169 169 169]
+#, @colorName[#"DarkGray" #"DarkGray" 169 169 169]
+#, @colorName[#"Dim Gray" #"DimGray" 105 105 105]
+#, @colorName[#"DimGray" #"DimGray" 105 105 105]
+#, @colorName[#"Black" #"Black" 0 0 0]
+]
+
+The names are not case-sensitive.
+
+See also @scheme[color%].
+
+
+
+
+@defmethod[(find-color [color-name string?])
+ (or/c (is-a?/c color%) false/c)]{
+
+Finds a color by name (character case is ignored). If no color is
+ found for the name, @scheme[#f] is returned.
+
+}}
+
diff --git a/collects/scribblings/gui/dc-intf.scrbl b/collects/scribblings/gui/dc-intf.scrbl
new file mode 100644
index 0000000000..7e313303fe
--- /dev/null
+++ b/collects/scribblings/gui/dc-intf.scrbl
@@ -0,0 +1,909 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@definterface[dc<%> ()]{
+
+A @scheme[dc<%>] object is a drawing context for drawing graphics and
+ text. It represents output devices in a generic way; e.g., a canvas
+ has a drawing context, as does a printer.
+
+The drawing methods, such as @method[dc<%> draw-rectangle], accept
+real number values as arguments, but the results are only well-defined
+when the drawing coordinates are in the range @scheme[-16383] to
+@scheme[16383]. This restriction applies to the coordinates both
+before and after offsets and scaling factors are applied.
+
+@defmethod[(clear)
+ void?]{
+
+Clears the drawing region (fills it with the current background color,
+as determined by @method[dc<%> get-background]).
+
+}
+
+@defmethod[(draw-arc [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))]
+ [start-radians real?]
+ [end-radians real?])
+ void?]{
+
+Draws a counter-clockwise circular arc, a part of the ellipse
+ inscribed in the rectangle specified by @scheme[x] (left), @scheme[y]
+ (top), @scheme[width], and @scheme[height]. The arc starts at the angle
+ specified by @scheme[start-radians] (@scheme[0] is three o'clock and
+ half-pi is twelve o'clock) and continues counter-clockwise to
+ @scheme[end-radians]. If @scheme[start-radians] and @scheme[end-radians] are
+ the same, a full ellipse is drawn.
+
+The current pen is used for the arc. If the current brush is not
+ transparent, it is used to fill the wedge bounded by the arc plus
+ lines (not drawn) extending to the center of the inscribed ellipse.
+
+If both the pen and brush are non-transparent, the wedge is filled
+ with the brush before the arc is drawn with the pen. The wedge and
+ arc meet so that no space is left between them, but the precise
+ overlap between the wedge and arc is platform- and size-specific.
+ Typically, the regions drawn by the brush and pen overlap. More
+ generally, the pen is centered over the outline of the arc, rounding
+ toward the center in unsmoothed mode.
+
+@|DrawSizeNote|
+
+}
+
+
+@defmethod[(draw-bitmap [source (is-a?/c bitmap%)]
+ [dest-x real?]
+ [dest-y real?]
+ [style (one-of/c 'solid 'opaque 'xor) 'solid]
+ [color (is-a?/c color%) (send the-color-database find-color "black")]
+ [mask (or/c (is-a?/c bitmap%) false/c) #f])
+ boolean?]{
+
+Displays a bitmap. The @scheme[dest-x] and @scheme[dest-y] arguments
+ are in DC coordinates.
+
+For color bitmaps, the drawing style and color arguments are
+ ignored. For monochrome bitmaps, @method[dc<%> draw-bitmap] uses the
+ style and color arguments in the same way that a brush uses its style
+ and color settings to draw a monochrome stipple (see @scheme[brush%]
+ for more information).
+
+If a mask bitmap is supplied, it must have the same width and height
+ as the bitmap to display, and its @method[bitmap% ok?] must return
+ true, otherwise @|MismatchExn|. The bitmap to draw and the mask
+ bitmap can be the same object, but if the drawing context is a
+ @scheme[bitmap-dc%] object, both bitmaps must be distinct from the
+ destination bitmap, otherwise @|MismatchExn|.
+
+If the mask bitmap is monochrome, drawing occurs in the target
+ @scheme[dc<%>] only where the mask bitmap contains black pixels.
+
+If the mask bitmap is grayscale and the bitmap to draw is not
+ monochrome, then the blackness of each mask pixel controls the
+ opacity of the drawn pixel (i.e., the mask acts as an inverted alpha
+ channel), at least on most platforms. (Non-monochrome masks
+ are collapsed to monochrome under X when the RENDER extension is not
+ available, and under Windows 95 and NT when @file{msing32.dll} is not
+ available.) Other combinations involving a non-monochrome mask (i.e.,
+ a non-grayscale mask or a monochrome bitmap to draw) produce
+ platform-specific results.
+
+The current brush, current pen, and current text settings for the DC
+ have no effect on how the bitmap is drawn, but the bitmap is scaled
+ if the DC has a scale.
+
+For @scheme[post-script-dc%] output, the mask bitmap is currently
+ ignored, and the @scheme['solid] style is treated the same as
+ @scheme['opaque]. (However, mask bitmaps and @scheme['solid] drawing
+ may become supported for @scheme[post-script-dc%] in the future.)
+
+The result is @scheme[#t] if the bitmap is successfully drawn,
+ @scheme[#f] otherwise (possibly because the bitmap's @method[bitmap%
+ ok?] method returns @scheme[#f]).
+
+See also @method[dc<%> draw-bitmap-section].
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(draw-bitmap-section [source (is-a?/c bitmap%)]
+ [dest-x real?]
+ [dest-y real?]
+ [src-x real?]
+ [src-y real?]
+ [src-width (and/c real? (not/c negative?))]
+ [src-height (and/c real? (not/c negative?))]
+ [style (one-of/c 'solid 'opaque 'xor) 'solid]
+ [color (is-a?/c color%) (send the-color-database find-color "black")]
+ [mask (or/c (is-a?/c bitmap%) false/c) #f])
+ boolean?]{
+
+Displays part of a bitmap.
+
+The @scheme[src-x], @scheme[src-y], @scheme[src-width], and
+ @scheme[src-height] arguments specify a rectangle in the source
+ bitmap to copy into this drawing context.
+
+See @method[dc<%> draw-bitmap] for information about @scheme[dest-x],
+ @scheme[dest-y], @scheme[style], @scheme[color], and @scheme[mask].
+
+}
+
+@defmethod[(draw-ellipse [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))])
+ void?]{
+
+Draws an ellipse contained in a rectangle with the given top-left
+ corner and size. The current pen is used for the outline, and the
+ current brush is used for filling the shape.
+
+If both the pen and brush are non-transparent, the ellipse is filled
+ with the brush before the outline is drawn with the pen. The filling
+ and outline meet so that no space is left between them, but the
+ precise overlap between the filling and outline is platform- and
+ size-specific. Typically, the regions drawn by the brush and pen
+ overlap. More generally, the pen is centered over the outline of the
+ ellipse, rounding toward the center in unsmoothed mode.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(draw-line [x1 real?]
+ [y1 real?]
+ [x2 real?]
+ [y2 real?])
+ void?]{
+
+Draws a line from one point to another. The current pen is used for
+ drawing the line.
+
+In unsmoothed mode, the points correspond to pixels, and the line
+ covers both the start and end points. For a pen whose scaled width is
+ larger than @scheme[1], the line is drawn centered over the start and
+ end points.
+
+See also @method[dc<%> set-smoothing] for information on the
+@scheme['aligned] smoothing mode.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(draw-lines [points (listof (is-a?/c point%))]
+ [xoffset real? 0]
+ [yoffset real? 0])
+ void?]{
+
+Draws lines using a list of @scheme[points], adding @scheme[xoffset]
+ and @scheme[yoffset] to each point. The current pen is used for
+ drawing the lines.
+
+See also @method[dc<%> set-smoothing] for information on the
+ @scheme['aligned] smoothing mode.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(draw-path [path (is-a?/c dc-path%)]
+ [xoffset real? 0]
+ [yoffset real? 0]
+ [fill-style (one-of/c 'odd-even 'winding) 'odd-even])
+ void?]{
+
+Draws the sub-paths of the given @scheme[dc-path%] object, adding
+ @scheme[xoffset] and @scheme[yoffset] to each point. The current pen
+ is used for drawing the path as a line, and the current brush is used
+ for filling the area bounded by the path.
+
+If both the pen and brush are non-transparent, the path is filled with
+ the brush before the outline is drawn with the pen. The filling and
+ outline meet so that no space is left between them, but the precise
+ overlap between the filling and outline is platform- and
+ size-specific. Thus, the regions drawn by the brush and pen may
+ overlap. More generally, the pen is centered over the path, rounding
+ left and down in unsmoothed mode.
+
+The @scheme[fill-style] argument specifies the fill rule:
+ @scheme['odd-even] or @scheme['winding]. In @scheme['odd-even] mode, a
+ point is considered enclosed within the path if it is enclosed by an
+ odd number of sub-path loops. In @scheme['winding] mode, a point is
+ considered enclosed within the path if it is enclosed by more or less
+ clockwise sub-path loops than counter-clockwise sub-path loops. In
+ unsmoothed mode, the @scheme['winding] fill rule is not supported
+ under Mac OS X and it is not supported when @scheme[path] contains
+ multiple sub-paths; the @scheme['winding] fill rules is always
+ supported when smoothing is enabled (see
+@method[dc<%> set-smoothing]).
+
+See also @method[dc<%> set-smoothing] for information on the
+ @scheme['aligned] smoothing mode.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(draw-point [x real?]
+ [y real?])
+ void?]{
+
+Plots a single point using the current pen.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(draw-polygon [points (listof (is-a?/c point%))]
+ [xoffset real? 0]
+ [yoffset real? 0]
+ [fill-style (one-of/c 'odd-even 'winding) 'odd-even])
+ void?]{
+
+Draw a filled polygon using a list of @scheme[points], adding
+ @scheme[xoffset] and @scheme[yoffset] to each point. The polygon is
+ automatically closed, so the first and last point can be
+ different. The current pen is used for drawing the outline, and the
+ current brush for filling the shape.
+
+If both the pen and brush are non-transparent, the polygon is filled
+ with the brush before the outline is drawn with the pen. The filling
+ and outline meet so that no space is left between them, but the
+ precise overlap between the filling and outline is platform- and
+ shape-specific. Thus, the regions drawn by the brush and pen may
+ overlap. More generally, the pen is centered over the polygon lines,
+ rounding left and down in unsmoothed mode.
+
+The @scheme[fill-style] argument specifies the fill rule:
+ @scheme['odd-even] or @scheme['winding]. In @scheme['odd-even] mode, a
+ point is considered enclosed within the polygon if it is enclosed by
+ an odd number of loops. In @scheme['winding] mode, a point is
+ considered enclosed within the polygon if it is enclosed by more or
+ less clockwise loops than counter-clockwise loops. The
+ @scheme['winding] fill rule is not supported under Mac OS X,
+ except when smoothing is enabled (see
+@method[dc<%> set-smoothing]).
+
+See also @method[dc<%> set-smoothing] for information on the
+ @scheme['aligned] smoothing mode.
+
+@|DrawSizeNote|
+
+}
+
+
+@defmethod[(draw-rectangle [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))])
+ void?]{
+
+Draws a rectangle with the given top-left corner and size. The
+ current pen is used for the outline and the current brush for filling
+ the shape.
+
+If both the pen and brush are non-transparent, the rectangle is filled
+ with the brush before the outline is drawn with the pen. In
+ unsmoothed mode, when the pen is size 0 or 1, the filling precisely
+ overlaps the entire outline. As a result, if a rectangle is drawn
+ with a size-0 or size-1 @scheme['xor] @scheme[pen%] and an
+ @scheme['xor] @scheme[brush%], the outline is xored twice (first by
+ the brush, then by the pen), leaving it unchanged. More generally,
+ the pen is centered over the outline of the rectangle, rounding
+ toward the center in unsmoothed mode.
+
+See also @method[dc<%> set-smoothing] for information on the
+@scheme['aligned] smoothing mode.
+
+@|DrawSizeNote|
+
+}
+
+
+@defmethod[(draw-rounded-rectangle [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))]
+ [radius real? -0.25])
+ void?]{
+
+Draws a rectangle with the given top-left corner, and with the given
+ size. The corners are quarter-circles using the given radius. The
+ current pen is used for the outline and the current brush for filling
+ the shape.
+
+If @scheme[radius] is positive, the value is used as the radius of the
+ rounded corner. If @scheme[radius] is negative, the absolute value is
+ used as the @italic{proportion} of the smallest dimension of the
+ rectangle.
+
+If @scheme[radius] is less than @scheme[-0.5] or more than half of
+ @scheme[width] or @scheme[height], @|MismatchExn|.
+
+If both the pen and brush are non-transparent, the rectangle is filled
+ with the brush before the outline is drawn with the pen. The filling
+ and outline meet so that no space is left between them, but the
+ precise overlap between the filling and outline is platform- and
+ size-specific. Thus, the regions drawn by the brush and pen may
+ partially overlap. More generally, the pen is centered over the
+ outline of the rounded rectangle, rounding toward the center in
+ unsmoothed mode.
+
+See also @method[dc<%> set-smoothing] for information on the
+@scheme['aligned] smoothing mode.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(draw-spline [x1 real?]
+ [y1 real?]
+ [x2 real?]
+ [y2 real?]
+ [x3 real?]
+ [y3 real?])
+ void?]{
+
+Draws a spline from (@scheme[x1], @scheme[y1]) to (@scheme[x3], @scheme[y3])
+ using (@scheme[x2], @scheme[y2]) as the control point.
+
+See also @method[dc<%> set-smoothing] for information on the
+@scheme['aligned] smoothing mode.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(draw-text [text string?]
+ [x real?]
+ [y real?]
+ [combine? any/c #f]
+ [offset nonnegative-exact-integer? 0]
+ [angle real? 0])
+ void?]{
+
+Draws a text string at a specified point, using the current text font,
+ and the current text foreground and background colors. For unrotated
+ text, the specified point is used as the starting top-left point for
+ drawing characters (e.g, if ``W'' is drawn, the point is roughly the
+ location of the top-left pixel in the ``W''). Rotated text is rotated
+ around this point.
+
+The @scheme[text] string is drawn starting from the @scheme[offset]
+ character, and continuing until the end of @scheme[text] or the first
+ null character.
+
+If @scheme[combine?] is @scheme[#t], then @scheme[text] may be
+ measured with adjacent characters combined to ligature glyphs, with
+ Unicode combining characters as a single glyph, with kerning, with
+ right-to-left rendering of characters, etc. If @scheme[combine?] is
+ @scheme[#f], then the result is the same as if each character is
+ measured separately, and Unicode control characters are ignored.
+
+The string is rotated by @scheme[angle] radians counter-clockwise. If
+ @scheme[angle] is not zero, then the text is always drawn in
+ transparent mode (see @method[dc<%> set-text-mode]).
+
+The current brush and current pen settings for the DC have no effect
+ on how the text is drawn.
+
+See @method[dc<%> get-text-extent] for information on the size of the
+ drawn text.
+
+See also @method[dc<%> set-text-foreground], @method[dc<%>
+ set-text-background], and @method[dc<%> set-text-mode].
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(end-doc)
+ void?]{
+
+Ends a document, relevant only when drawing to a printer or PostScript
+ device (including to a PostScript file).
+
+For printer or PostScript output, an exception is raised if
+@scheme[end-doc] is called when the document is not started with
+@method[dc<%> start-doc], when a page is currently started by
+@method[dc<%> start-page] and not ended with @method[dc<%> end-page],
+or when the document has been ended already.
+
+}
+
+@defmethod[(end-page)
+ void?]{
+
+Ends a single page, relevant only when drawing to a printer or
+ PostScript device (including to a PostScript file).
+
+For printer or PostScript output, an exception is raised if
+@scheme[end-page] is called when a page is not currently started by
+@method[dc<%> start-page].
+
+}
+
+@defmethod[(get-background)
+ (is-a?/c color%)]{
+
+Gets the color used for painting the background. See also
+@method[dc<%> set-background].
+
+}
+
+@defmethod[(get-brush)
+ (is-a?/c brush%)]{
+
+Gets the current brush. See also @method[dc<%> set-brush].
+
+}
+
+@defmethod[(get-char-height)
+ (and/c real? (not/c negative?))]{
+
+Gets the height of a character using the current font.
+
+Unlike most methods, this method can be called for a
+ @scheme[bitmap-dc%] object without a bitmap installed.
+
+}
+
+@defmethod[(get-char-width)
+ (and/c real? (not/c negative?))]{
+
+Gets the average width of a character using the current font.
+
+Unlike most methods, this method can be called for a
+ @scheme[bitmap-dc%] object without a bitmap installed.
+
+}
+
+@defmethod[(get-clipping-region)
+ (or/c (is-a?/c region%) false/c)]{
+
+Gets the current clipping region, returning @scheme[#f] if the drawing
+ context is not clipped (i.e., the clipping region is the entire
+ drawing region).
+
+}
+
+@defmethod[(get-font)
+ (is-a?/c font%)]{
+
+Gets the current font. See also @method[dc<%> set-font].
+
+}
+
+@defmethod[(get-gl-context)
+ (or/c (is-a?/c gl-context<%>) false/c)]{
+
+Returns a @scheme[gl-context<%>] object for this drawing context
+ if it supports OpenGL, @scheme[#f] otherwise.
+
+See @scheme[gl-context<%>] for more information.
+
+}
+
+@defmethod[(get-origin)
+ (values real? real?)]{
+
+Returns the device origin, i.e., the location in device coordinates of
+ @math{(0,0)} in logical coordinates.
+
+See also @method[dc<%> set-origin].
+
+}
+
+
+@defmethod[(get-pen)
+ (is-a?/c pen%)]{
+
+Gets the current pen. See also @method[dc<%> set-pen].
+
+}
+
+@defmethod[(get-scale)
+ (values real? real?)]{
+
+Returns the scaling factor that maps logical coordinates to device
+coordinates.
+
+See also @method[dc<%> set-scale].
+
+}
+
+@defmethod[(get-size)
+ (values nonnegative-real? nonnegative-real?)]{
+
+Gets the size of the destination drawing area. For a @scheme[dc<%>]
+ object obtained from a @scheme[canvas<%>], this is the (virtual
+ client) size of the destination window; for a @scheme[bitmap-dc%]
+ object, this is the size of the selected bitmap (or 0 if no bitmap is
+ selected); for a @scheme[post-script-dc%] or @scheme[printer-dc%]
+ drawing context, this gets the horizontal and vertical size of the
+ drawing area.
+
+}
+
+@defmethod[(get-smoothing)
+ (one-of/c 'unsmoothed 'smoothed 'aligned)]{
+
+Returns the current smoothing mode. See @method[dc<%> set-smoothing].
+
+}
+
+@defmethod[(get-text-background)
+ (is-a?/c color%)]{
+
+Gets the current text background color. See also @method[dc<%>
+set-text-background].
+
+}
+
+@defmethod[(get-text-extent [string string?]
+ [font (or/c (is-a?/c font%) false/c) #f]
+ [combine? any/c #f]
+ [offset nonnegative-exact-integer? 0])
+ (values nonnegative-real?
+ nonnegative-real?
+ nonnegative-real?
+ nonnegative-real?)]{
+
+
+Returns the size of @scheme[str] at it would be drawn in the drawing
+ context, starting from the @scheme[offset] character of @scheme[str],
+ and continuing until the end of @scheme[str] or the first null
+ character. The @scheme[font] argument specifies the font to use in
+ measuring the text; if it is @scheme[#f], the current font of the
+ drawing area is used. (See also @method[dc<%> set-font].)
+
+The result is four real numbers:
+
+@itemize{
+
+ @item{the total width of the text (depends on both the font and the
+ text);}
+
+ @item{the total height of the font (depends only on the font);}
+
+ @item{the distance from the baseline of the font to the bottom of the
+ descender (included in the height, depends only on the font); and}
+
+ @item{extra vertical space added to the font by the font designer
+ (included in the height, and often zero; depends only on the font).}
+
+}
+
+The returned width and height define a rectangle is that guaranteed to
+ contain the text string when it is drawn, but the fit is not
+ necessarily tight. Some undefined number of pixels on the left,
+ right, top, and bottom of the drawn string may be ``whitespace,''
+ depending on the whims of the font designer and the platform-specific
+ font-scaling mechanism.
+
+If @scheme[combine?] is @scheme[#t], then @scheme[text] may be drawn
+ with adjacent characters combined to ligature glyphs, with Unicode
+ combining characters as a single glyph, with kerning, with
+ right-to-left ordering of characters, etc. If @scheme[combine?] is
+ @scheme[#f], then the result is the same as if each character is
+ drawn separately, and Unicode control characters are ignored.
+
+Unlike most methods, this method can be called for a
+ @scheme[bitmap-dc%] object without a bitmap installed.
+
+}
+
+
+@defmethod[(get-text-foreground)
+ (is-a?/c color%)]{
+
+Gets the current text foreground color. See also @method[dc<%>
+set-text-foreground].
+
+}
+
+@defmethod[(get-text-mode)
+ (one-of/c 'solid 'transparent)]{
+Reports how text is drawn; see
+@method[dc<%> set-text-mode] .
+
+}
+
+@defmethod[(glyph-exists? [c char]
+ [font (or/c (is-a?/c font%) false/c) #f])
+ boolean?]{
+
+Returns @scheme[#t] if the given character has a corresponding glyph
+ for this drawing context, @scheme[#f] otherwise.
+
+Due to automatic font substitution when drawing or measuring text, the
+ result of this method does not depend on the given font, which merely
+ provides a hint for the glyph search. If the font is @scheme[#f], the
+ drawing context's current font is used. The result depends on the
+ type of the drawing context, but the result for @scheme[canvas%]
+ @scheme[dc<%>] instances and @scheme[bitmap-dc%] instances is always
+ the same for a given platform and a given set of installed fonts.
+
+See also @method[font% screen-glyph-exists?] .
+
+}
+
+@defmethod[(ok?)
+ boolean?]{
+
+Returns @scheme[#t] if the drawing context is usable.
+
+}
+
+@defmethod[(set-background [color (is-a?/c color%)])
+ void?]{
+
+Sets the background color for drawing in this object (e.g., using
+@method[dc<%> clear] or using a stippled @scheme[brush%] with the mode
+@scheme['opaque]). For monochrome drawing, all non-black colors are
+treated as white.
+
+}
+
+@defmethod*[([(set-brush [brush (is-a?/c brush%)])
+ void?]
+ [(set-brush [color (is-a?/c color%)]
+ [style (one-of/c 'transparent 'solid 'opaque
+ 'xor 'hilite 'panel
+ 'bdiagonal-hatch 'crossdiag-hatch
+ 'fdiagonal-hatch 'cross-hatch
+ 'horizontal-hatch 'vertical-hatch)])
+ void?]
+ [(set-brush [color-name string?]
+ [style (one-of/c 'transparent 'solid 'opaque
+ 'xor 'hilite 'panel
+ 'bdiagonal-hatch 'crossdiag-hatch
+ 'fdiagonal-hatch 'cross-hatch
+ 'horizontal-hatch 'vertical-hatch)])
+ void?])]{
+
+Sets the current brush for drawing in this object. While a brush is
+ selected into a drawing context, it cannot be modified. When a color
+ and style are given, the arguments are as for @xmethod[brush-list%
+ find-or-create-brush].
+
+}
+
+
+@defmethod[(set-clipping-rect [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))])
+ void?]{
+
+Sets the clipping region to a rectangular region.
+
+See also @method[dc<%> set-clipping-region] and @method[dc<%>
+get-clipping-region].
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(set-clipping-region [rgn (or/c (is-a?/c region%) false/c)])
+ void?]{
+
+Sets the clipping region for the drawing area, turning off all
+ clipping within the drawing region if @scheme[#f] is provided.
+
+The clipping region must be reset after changing a @scheme[dc<%>]
+ object's origin or scale (unless it is @scheme[#f]); see
+ @scheme[region%] for more information.
+
+See also @method[dc<%> set-clipping-rect] and @method[dc<%>
+ get-clipping-region].
+
+}
+
+@defmethod[(set-font [font (is-a?/c font%)])
+ void?]{
+
+Sets the current font for drawing text in this object.
+
+}
+
+@defmethod[(set-origin [x real?]
+ [y real?])
+ void?]{
+
+Sets the device origin, i.e., the location in device coordinates of
+ @math{(0,0)} in logical coordinates.
+
+Changing a @scheme[dc<%>] object's origin or scale does not affect
+ @scheme[region%] objects that were previously created. See
+@scheme[region%] for more information.
+
+
+@|DrawSizeNote|
+
+}
+
+@defmethod*[([(set-pen [pen (is-a?/c pen%)])
+ void?]
+ [(set-pen [color (is-a?/c color%)]
+ [width (real-in 0 255)]
+ [style (one-of/c 'transparent 'solid 'xor 'hilite
+ 'dot 'long-dash 'short-dash 'dot-dash
+ 'xor-dot 'xor-long-dash 'xor-short-dash
+ 'xor-dot-dash)])
+ void?]
+ [(set-pen [color-name string?]
+ [width (real-in 0 255)]
+ [style (one-of/c 'transparent 'solid 'xor 'hilite
+ 'dot 'long-dash 'short-dash 'dot-dash
+ 'xor-dot 'xor-long-dash 'xor-short-dash
+ 'xor-dot-dash)])
+ void?])]{
+
+Sets the current pen for this object. When a color, width, and style
+ are given, the arguments are as for @xmethod[pen-list%
+ find-or-create-pen].
+
+The current pen does not affect text drawing; see also @method[dc<%>
+ set-text-foreground].
+
+While a pen is selected into a drawing context, it cannot be modified.
+
+}
+
+@defmethod[(set-scale [x-scale (and/c real? (not/c negative?))]
+ [y-scale (and/c real? (not/c negative?))])
+ void?]{
+
+Sets a scaling factor that maps logical coordinates to device coordinates.
+
+Changing a @scheme[dc<%>] object's origin or scale does not affect
+ @scheme[region%] objects that were previously created. See
+ @scheme[region%] for more information.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(set-smoothing [mode (one-of/c 'unsmoothed 'smoothed 'aligned)])
+ void?]{
+
+Enables or disables anti-aliased smoothing of lines, curves,
+ rectangles, rounded rectangles, ellipses, polygons, paths, and clear
+ operations. (Text smoothing is not affected by this method, and is
+ instead controlled through the @scheme[font%] object.)
+
+Smoothing is supported under Windows only when Microsoft's
+ @file{gdiplus.dll} is installed (which is always the case for Windows
+ XP). Smoothing is supported under Mac OS X always. Smoothing is
+ supported under X only when Cairo is installed when MrEd is compiled.
+ Smoothing is never supported for black-and-white contexts. Smoothing
+ is always supported (and cannot be disabled) for PostScript output.
+
+The smoothing mode is either @scheme['unsmoothed], @scheme['smoothed],
+ or @scheme['aligned]. Both @scheme['aligned] and @scheme['smoothed]
+ are smoothing modes.
+
+In @scheme['smoothed] mode for a canvas or bitmap drawing context,
+ integer drawing coordinates correspond to the boundary between
+ pixels, and pen-based drawing is centered over a given line or
+ curve. Thus, drawing with pen width @scheme[1] from @math{(0, 10)} to
+ @math{(10, 10)} draws a 2-pixel wide line with @math{50%} opacity.
+
+The @scheme['aligned] smoothing mode is like @scheme['smoothed], but
+ it paints pixels more like @scheme['unsmoothed] mode. Since it aligns
+ shapes to pixel boundaries, @scheme['aligned] mode often produces
+ better results than @scheme['smoothed], but the results depend on the
+ application. The @scheme['aligned] mode is defined in terms of
+ @scheme['smoothed] mode, except that drawing coordinates are rounded
+ down (via @scheme[floor], after scaling and origin translation). For
+ line drawing, coordinates are then shifted right and down by the
+ @scheme[floor] of half a pen width. In addition, for pen drawing
+ through @method[dc<%> draw-rectangle], @method[dc<%> draw-ellipse],
+ @method[dc<%> draw-rounded-rectangle], and @method[dc<%> draw-arc],
+ the given width and height are each decreased by @math{1.0}.
+
+In either smoothing mode, brush and pen stipples are ignored (except
+ for PostScript drawing), and @scheme['hilite] and @scheme['xor]
+ drawing modes are treated as @scheme['solid]. If smoothing is not
+ supported, then attempting to set the smoothing mode to
+ @scheme['smoothed] or @scheme['aligned] will have no effect, and
+ @method[dc<%> get-smoothing] will always return
+ @scheme['unsmoothed]. Similarly, @method[dc<%> get-smoothing] for a
+ @scheme[post-script-dc%] always returns @scheme['smoothed].
+
+}
+
+@defmethod[(set-text-background [color (is-a?/c color%)])
+ void?]{
+
+Sets the current text background color for this object. The text
+ background color is painted behind text that is drawn with
+ @method[dc<%> draw-text], but only for the @scheme['solid] text mode
+ (see @method[dc<%> set-text-mode]).
+
+For monochrome drawing, all non-white colors are treated as black.
+
+}
+
+@defmethod[(set-text-foreground [color (is-a?/c color%)])
+ void?]{
+
+Sets the current text foreground color for this object, used for
+ drawing text with
+@method[dc<%> draw-text].
+
+For monochrome drawing, all non-black colors are treated as
+ white.
+
+}
+
+@defmethod[(set-text-mode [mode (one-of/c 'solid 'transparent)])
+ void?]{
+
+Determines how text is drawn:
+
+@itemize{
+
+ @item{@scheme['solid] --- Before text is drawn, the destination area
+ is filled with the text background color (see @method[dc<%>
+ set-text-background]).}
+
+ @item{@scheme['transparent] --- Text is drawn directly over any
+ existing image in the destination, as if overlaying text
+ written on transparent film.}
+
+}
+
+}
+
+@defmethod[(start-doc [message string?])
+ boolean?]{
+
+Starts a document, relevant only when drawing to a printer or
+ PostScript device (including to a PostScript file). For some
+ platforms, the @scheme[message] string is displayed in a dialog until
+ @method[dc<%> end-doc] is called.
+
+For printer or PostScript output, an exception is raised if
+ @scheme[start-doc] has been called already (even if @method[dc<%>
+ end-doc] has been called as well). Furthermore, drawing methods raise
+ an exception if not called while a page is active as determined by
+ @method[dc<%> start-doc] and @method[dc<%> start-page].
+
+}
+
+@defmethod[(start-page)
+ void?]{
+
+Starts a page, relevant only when drawing to a printer or PostScript
+ device (including to a PostScript file).
+
+For printer or PostScript output, an exception is raised if
+ @scheme[start-doc] is called when a page is already started, or when
+ @method[dc<%> start-doc] has not been called, or when @method[dc<%>
+ end-doc] has been called already. In addition, in the case of
+ PostScript output, Encapsulated PostScript (EPS) cannot contain
+ multiple pages, so calling @scheme[start-page] a second time for a
+ @scheme[post-script-dc%] instance raises an exception; to create
+ PostScript output with multiple pages, supply @scheme[#f] as the
+ @scheme[as-eps] initialization argument for @scheme[post-script-dc%].
+
+}
+
+@defmethod[(try-color [try (is-a?/c color%)]
+ [result (is-a?/c color%)])
+ void?]{
+
+Determines the actual color used for drawing requests with the given
+ color. The @scheme[result] color is set to the RGB values that are
+ actually produced for this drawing context to draw the color
+ @scheme[try].
+
+}}
diff --git a/collects/scribblings/gui/dc-path-class.scrbl b/collects/scribblings/gui/dc-path-class.scrbl
new file mode 100644
index 0000000000..0d63b745d9
--- /dev/null
+++ b/collects/scribblings/gui/dc-path-class.scrbl
@@ -0,0 +1,261 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[dc-path% object% ()]{
+
+A path is a set of figures defined by curves. A path can be used with
+the @method[dc<%> draw-path] method of a @scheme[dc<%>] object to draw
+the path's curves as lines, fill the region bounded by the path's
+curves, or both. A path can also be used with the @method[region%
+set-path] method of a @scheme[region%] object to generate a region
+bounded by the path's curves.
+
+A path consists of zero or more @deftech{closed sub-paths}, and
+ possibly one @deftech{open sub-path}. Some @scheme[dc-path%] methods
+ extend the open sub-path, some @scheme[dc-path%] methods close the
+ open sub-path, and some @scheme[dc-path%] methods add closed
+ sub-paths.
+
+When a path is drawn as a line, a closed sub-path is drawn as a closed
+ figure, analogous to a polygon. An open sub-path is drawn with
+ disjoint start and end points, analogous lines drawn with
+ @xmethod[dc<%> draw-lines].
+
+When a path is filled or used as a region, the open sub-path (if any)
+ is treated as if it were closed. The content of a path is determined
+ either through the @scheme['even-odd] rule or the @scheme['winding]
+ rule, as selected at the time when the path is filled or used to
+ generate a region.
+
+A path is not connected to any particular @scheme[dc<%>] object, so
+ setting a @scheme[dc<%>] origin or scale does not affect path
+ operations. Instead, a @scheme[dc<%>]'s origin and scale apply at the
+ time that the path is drawn or used to set a region.
+
+@defconstructor/make[()]{
+
+Creates a new path that contains no sub-paths (and no @tech{open
+sub-path}).
+
+}
+
+
+@defmethod[(append [path (is-a?/c dc-path%)])
+ void?]{
+
+Adds the sub-paths of @scheme[path] to @this-obj[]. @tech{Closed
+ sub-paths} of @scheme[path] are added as @tech{closed sub-paths} to
+ @this-obj[]. If both paths have an @tech{open sub-path}, then this
+ path's sub-path is extended by the given path's @tech{open sub-path},
+ adding a line from this path's current ending point to the given
+ path's starting point. If only one of the paths has an @tech{open
+ sub-path}, then it becomes (or remains) this path's @tech{open
+ sub-path}.
+
+}
+
+@defmethod[(arc [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))]
+ [start-radians real?]
+ [end-radians real?]
+ [counter-clockwise? any/c #t])
+ void?]{
+
+Extends or starts the path's @tech{open sub-path} with a curve that
+ corresponds to a section of an ellipse. The ellipse is the one
+ bounded by a rectangle whose top-left corner is @math{(@scheme[x],
+ @scheme[y])} and whose dimensions are @scheme[width] by
+ @scheme[height]. The ellipse section starts a the angle
+ @scheme[start-radians] (@scheme[0] is three o'clock and half-pi is
+ twelve o'clock) and continues to the angle @scheme[end-radians]; if
+ @scheme[counter-clockwise?] is true, then the arc runs
+ counter-clockwise from @scheme[start-radians] to
+ @scheme[end-radians], otherwise it runs clockwise.
+
+If the path has no @tech{open sub-path}, a new one is started with the
+ arc's starting point. Otherwise, the arc extends the existing
+ sub-path, and the existing path is connected with a line to the arc's
+ starting point.
+
+}
+
+@defmethod[(close)
+ void?]{
+
+Closes the path's @tech{open sub-path}. If the path has no @tech{open
+ sub-path}, @|MismatchExn|.
+
+}
+
+@defmethod[(curve-to [x1 real?]
+ [y1 real?]
+ [x2 real?]
+ [y2 real?]
+ [x3 real?]
+ [y3 real?])
+ void?]{
+
+Extends the path's @tech{open sub-path} with a Bezier curve to the
+ given point @math{(@scheme[x3],@scheme[y3])}, using the points
+ @math{(@scheme[x1], @scheme[y1])}$ and @math{(@scheme[x2],
+ @scheme[y2])}$ as control points. If the path has no @tech{open
+ sub-path}, @|MismatchExn|.
+
+}
+
+@defmethod[(ellipse [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))])
+ void?]{
+
+Closes the @tech{open sub-path}, if any, and adds a @tech{closed
+ sub-path} that represents an ellipse bounded by a rectangle whose
+ top-left corner is @math{(@scheme[x], @scheme[y])} and whose
+ dimensions are @scheme[width] by @scheme[height]. (This convenience
+ method is implemented in terms of @method[dc-path% close] and
+ @method[dc-path% arc].)
+
+}
+
+@defmethod[(get-bounding-box)
+ (values real? real? real? real?)]{
+
+Returns a rectangle that encloses the path's points. The return
+ values are the left, top, width, and height of the rectangle.
+
+For curves within the path, the bounding box enclosed the two control
+ points as well as the start and end points. Thus, the bounding box
+ does not always tightly bound the path.
+
+}
+
+@defmethod[(line-to [x real?]
+ [y real?])
+ void?]{
+
+Extends the path's @tech{open sub-path} with a line to the given
+ point. If the path has no @tech{open sub-path}, @|MismatchExn|.
+
+}
+
+@defmethod[(lines [points (listof (is-a?/c point%))]
+ [xoffset real? 0]
+ [yoffset real? 0])
+ void?]{
+
+Extends the path's @tech{open sub-path} with a sequences of lines to
+ the given points. If the path has no @tech{open sub-path},
+ @|MismatchExn|. (This convenience method is implemented in terms of
+ @method[dc-path% line-to].)
+
+}
+
+@defmethod[(move-to [x real?]
+ [y real?])
+ void?]{
+
+After closing the @tech{open sub-path}, if any, starts a new
+ @tech{open sub-path} with the given initial point.
+
+}
+
+@defmethod[(open?)
+ boolean?]{
+
+Returns @scheme[#t] if the path has an @tech{open sub-path},
+@scheme[#f] otherwise.
+
+}
+
+@defmethod[(rectangle [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))])
+ void?]{
+
+Closes the @tech{open sub-path}, if any, and adds a closed path that
+ represents a rectangle whose top-left corner is @math{(@scheme[x],
+ @scheme[y])} and whose dimensions are @scheme[width] by
+ @scheme[height]. (This convenience method is implemented in terms of
+ @method[dc-path% close], @method[dc-path% move-to], and
+ @method[dc-path% line-to].)
+
+}
+
+@defmethod[(reset)
+ void?]{
+
+Removes all sub-paths of the path.
+
+}
+
+@defmethod[(reverse)
+ void?]{
+
+Reverses the order of all points in all sub-paths. If the path has an
+ @tech{open sub-path}, the starting point becomes the ending point,
+ and extensions to the @tech{open sub-path} build on this new ending
+ point. Reversing a @tech{closed sub-path} affects how it combines
+ with other sub-paths when determining the content of a path in
+ @scheme['winding] mode.
+
+}
+
+@defmethod[(rotate [radians real?])
+ void?]{
+
+Adjusts all points within the path (including all sub-paths), rotating
+ them @scheme[radians] counter-clockwise around @math{(0, 0)}. Future
+ additions to the path are not rotated by this call.
+
+}
+
+@defmethod[(rounded-rectangle [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))]
+ [radius real? -0.25])
+ void?]{
+
+Closes the @tech{open sub-path}, if any, and adds a @tech{closed
+ sub-path} that represents a round-cornered rectangle whose top-left
+ corner is @math{(@scheme[x] @scheme[y])} and whose dimensions are
+ @scheme[width] by @scheme[height]. (This convenience method is
+ implemented in terms of @method[dc-path% close], @method[dc-path%
+ move-to], @method[dc-path% arc], and @method[dc-path% line-to].)
+
+If @scheme[radius] is positive, the value is used as the radius of the
+ rounded corner. If @scheme[radius] is negative, the absolute value is
+ used as the @italic{proportion} of the smallest dimension of the
+ rectangle.
+
+If @scheme[radius] is less than @scheme[-0.5] or more than half of
+ @scheme[width] or @scheme[height], @|MismatchExn|.
+
+}
+
+@defmethod[(scale [x real?]
+ [y real?])
+ void?]{
+
+@index['("paths" "flipping")]{Adjusts} all points within the path
+ (including all sub-paths), multiplying each x-coordinate by
+ @scheme[x] and each y-coordinate by @scheme[y]. Scaling by a negative
+ number flips the path over the corresponding axis. Future additions
+ to the path are not scaled by this call.
+
+}
+
+@defmethod[(translate [x real?]
+ [y real?])
+ void?]{
+
+Adjusts all points within the path (including all sub-paths), shifting
+ then @scheme[x] to the right and @scheme[y] down. Future additions
+ to the path are not translated by this call.
+
+}}
+
diff --git a/collects/scribblings/gui/draw-classes.scrbl b/collects/scribblings/gui/draw-classes.scrbl
new file mode 100644
index 0000000000..4f3ec40f8e
--- /dev/null
+++ b/collects/scribblings/gui/draw-classes.scrbl
@@ -0,0 +1,49 @@
+#reader(lib "docreader.ss" "scribble")
+@require["common.ss"]
+@require["diagrams.ss"]
+
+@title[#:style '(toc quiet)]{Drawing Class Reference}
+
+@local-table-of-contents[]
+
+@require["bitmap-class.scrbl"]
+@require["bitmap-dc-class.scrbl"]
+@require["brush-class.scrbl"]
+@require["brush-list-class.scrbl"]
+@require["color-class.scrbl"]
+@require["color-database-intf.scrbl"]
+@require["dc-intf.scrbl"]
+@require["dc-path-class.scrbl"]
+@require["font-class.scrbl"]
+@require["font-list-class.scrbl"]
+@require["font-name-directory-intf.scrbl"]
+@require["gl-config-class.scrbl"]
+@require["gl-context-intf.scrbl"]
+@require["pen-class.scrbl"]
+@require["pen-list-class.scrbl"]
+@require["point-class.scrbl"]
+@require["post-script-dc-class.scrbl"]
+@require["printer-dc-class.scrbl"]
+@require["ps-setup-class.scrbl"]
+@require["region-class.scrbl"]
+
+@include-class[bitmap%]
+@include-class[bitmap-dc%]
+@include-class[brush%]
+@include-class[brush-list%]
+@include-class[color%]
+@include-class[color-database<%>]
+@include-class[dc<%>]
+@include-class[dc-path%]
+@include-class[font%]
+@include-class[font-list%]
+@include-class[font-name-directory<%>]
+@include-class[gl-config%]
+@include-class[gl-context<%>]
+@include-class[pen%]
+@include-class[pen-list%]
+@include-class[point%]
+@include-class[post-script-dc%]
+@include-class[printer-dc%]
+@include-class[ps-setup%]
+@include-class[region%]
diff --git a/collects/scribblings/gui/draw-funcs.scrbl b/collects/scribblings/gui/draw-funcs.scrbl
new file mode 100644
index 0000000000..d61bfe9555
--- /dev/null
+++ b/collects/scribblings/gui/draw-funcs.scrbl
@@ -0,0 +1,11 @@
+#reader(lib "docreader.ss" "scribble")
+@require["common.ss"]
+
+@title{Drawing Function Reference}
+
+@local-table-of-contents[]
+
+@include-section["global-draw-funcs.scrbl"]
+@include-section["post-script-funcs.scrbl"]
+@include-section["draw-list-funcs.scrbl"]
+@include-section["font-funcs.scrbl"]
diff --git a/collects/scribblings/gui/draw-list-funcs.scrbl b/collects/scribblings/gui/draw-list-funcs.scrbl
new file mode 100644
index 0000000000..848ab10c2a
--- /dev/null
+++ b/collects/scribblings/gui/draw-list-funcs.scrbl
@@ -0,0 +1,36 @@
+#reader(lib "docreader.ss" "scribble")
+@require["common.ss"]
+
+@title{Drawing Object Lists}
+
+
+@defthing[the-brush-list (is-a?/c brush-list%)]{
+
+See @scheme[brush-list%].
+
+}
+
+@defthing[the-color-database (is-a?/c color-database<%>)]{
+
+See @scheme[color-database<%>].
+
+}
+
+@defthing[the-font-list (is-a?/c font-list%)]{
+
+See @scheme[font-list%].
+
+}
+
+@defthing[the-font-name-directory (is-a?/c font-name-directory<%>)]{
+
+See @scheme[font-name-directory<%>].
+
+
+}
+
+@defthing[the-pen-list (is-a?/c pen-list%)]{
+
+See @scheme[pen-list%].
+
+}
diff --git a/collects/scribblings/gui/draw-overview.scrbl b/collects/scribblings/gui/draw-overview.scrbl
index b01daf4972..1ff96d6237 100644
--- a/collects/scribblings/gui/draw-overview.scrbl
+++ b/collects/scribblings/gui/draw-overview.scrbl
@@ -3,7 +3,7 @@
@require["common.ss"]
@require["diagrams.ss"]
-@title[#:tag "mred:drawing-toolbox"]{Drawing Toolbox Overview}
+@title[#:tag "mr:drawing-overview"]{Drawing Guide}
Drawing in MrEd requires a @deftech{device context} (@deftech{DC}),
which is an instance of the @scheme[dc<%>] interface. For example,
diff --git a/collects/scribblings/gui/drawing.scrbl b/collects/scribblings/gui/drawing.scrbl
deleted file mode 100644
index 67cf845ffe..0000000000
--- a/collects/scribblings/gui/drawing.scrbl
+++ /dev/null
@@ -1,9 +0,0 @@
-#reader(lib "docreader.ss" "scribble")
-@require["common.ss"]
-@require["diagrams.ss"]
-
-@title[#:tag "mr:drawing" #:style 'toc]{Drawing Toolbox}
-
-@local-table-of-contents[]
-
-@include-section["draw-overview.scrbl"]
diff --git a/collects/scribblings/gui/editor-classes.scrbl b/collects/scribblings/gui/editor-classes.scrbl
new file mode 100644
index 0000000000..df7386fb16
--- /dev/null
+++ b/collects/scribblings/gui/editor-classes.scrbl
@@ -0,0 +1,44 @@
+#reader(lib "docreader.ss" "scribble")
+@require["common.ss"]
+@require["diagrams.ss"]
+
+@title[#:style '(toc quiet)]{Editor Class Reference}
+
+@local-table-of-contents[]
+
+@require["add-color-intf.scrbl"]
+@require["editor-intf.scrbl"]
+@;{
+@require["editor-admin-class.scrbl"]
+@require["editor-canvas-class.scrbl"]
+@require["editor-data-class.scrbl"]
+@require["editor-data-class-class.scrbl"]
+@require["editor-data-class-list-intf.scrbl"]
+@require["editor-snip-editor-admin-intf.scrbl"]
+@require["editor-snip-class.scrbl"]
+@require["editor-stream-in-class.scrbl"]
+@require["editor-stream-in-base-class.scrbl"]
+@require["editor-stream-in-bytes-base-class.scrbl"]
+@require["editor-stream-out-class.scrbl"]
+@require["editor-stream-out-base-class.scrbl"]
+@require["editor-stream-out-bytes-base-class.scrbl"]
+@require["editor-wordbreak-map-class.scrbl"]
+@require["image-snip-class.scrbl"]
+@require["keymap-class.scrbl"]
+@require["mult-color-intf.scrbl"]
+@require["pasteboard-class.scrbl"]
+@require["readable-snip-intf.scrbl"]
+@require["snip-class.scrbl"]
+@require["snip-admin-class.scrbl"]
+@require["snip-class-class.scrbl"]
+@require["snip-class-list-intf.scrbl"]
+@require["string-snip-class.scrbl"]
+@require["style-intf.scrbl"]
+@require["style-delta-class.scrbl"]
+@require["style-list-class.scrbl"]
+@require["tab-snip-class.scrbl"]
+@require["text-class.scrbl"]
+}
+
+@include-class[add-color<%>]
+@include-class[editor<%>]
diff --git a/collects/scribblings/gui/editor-intf.scrbl b/collects/scribblings/gui/editor-intf.scrbl
new file mode 100644
index 0000000000..b765b3b4f2
--- /dev/null
+++ b/collects/scribblings/gui/editor-intf.scrbl
@@ -0,0 +1,2361 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@definterface[editor<%> ()]{
+
+The @scheme[editor<%>] interface is implemented by @scheme[text%] and
+ @scheme[pasteboard%].
+
+@defmethod[(add-canvas [canvas (is-a?/c editor-canvas%)])
+ void?]{
+
+Adds a canvas to this editor's list of displaying canvases. (See
+@method[editor<%> get-canvases].)
+
+Normally, this method is called only by @xmethod[editor-canvas%
+ set-editor].
+
+}
+
+@defmethod[(add-undo [undoer (-> any)])
+ void?]{
+
+Adds an undoer procedure to the editor's undo stack. If an undo is
+ currently being performed, the undoer is added to the editor's redo
+ stack. The undoer is called by the system when it is undoing (or
+ redoing) changes to an editor, and when this undoer is the first item
+ on the undo (or redo) stack.
+
+The system automatically installs undo records to undo built-in editor
+ operations, such as inserts, deletes, and font changes. Install an
+ undoer only when it is necessary to maintain state or handle
+ operations that are not built-in. For example, in a program where the
+ user can assign labels to snips in a pasteboard, the program should
+ install an undoer to revert a label change. Thus, when a user changes
+ a snip's label and then selects @onscreen{Undo} (from a standard menu
+ bar), the snip's label will revert as expected. In contrast, there is
+ no need to install an undoer when the user moves a snip by dragging
+ it, because the system installs an appropriate undoer automatically.
+
+After an undoer returns, the undoer is popped off the editor's undo
+ (or redo) stack; if the return value is true, then the next undoer is
+ also executed as part of the same undo (or redo) step. The undoer
+ should return true if the action being undone was originally
+ performed as part of a @method[editor<%> begin-edit-sequence] and
+ @method[editor<%> end-edit-sequence] sequence. The return value
+ should also be true if the undone action was implicitly part of a
+ sequence. To extend the previous example, if a label change is paired
+ with a move to realign the snip, then the label-change undoer should
+ be added to the editor @italic{after} the call to @method[pasteboard%
+ move], and it should return @scheme[#t] when it is called. As a
+ result, the move will be undone immediately after the label change is
+ undone. (If the opposite order is needed, use @method[editor<%>
+ begin-edit-sequence] and @method[editor<%> end-edit-sequence] to
+ create an explicit sequence.)
+
+The system adds undoers to an editor (in response to other method
+ calls) without calling this method.
+
+}
+
+@defmethod[(adjust-cursor [event (is-a?/c mouse-event%)])
+ (or/c (is-a?/c cursor%) false/c)]{
+
+@methspec{
+
+Gets a cursor to be used in the editor's @techlink{display}. If the
+ return value is @scheme[#f], a default cursor is used.
+
+See also @method[editor<%> set-cursor].
+
+}
+@methimpl{
+
+If an overriding cursor has been installed with
+@method[editor<%> set-cursor], then the installed cursor is returned.
+
+Otherwise, if the event is a dragging event, a snip in the editor has
+the focus, and the snip's
+@method[snip% adjust-cursor] method returns a cursor, that cursor is returned.
+
+Otherwise, if the cursor is over a snip and the snip's
+@method[snip% adjust-cursor] method returns a cursor, that cursor is returned.
+
+Otherwise, if a cursor has been installed with
+@method[editor<%> set-cursor], then the installed cursor is returned.
+
+Otherwise, if the cursor is over a clickback region in an editor, an
+arrow cursor is returned.
+
+Finally, if none of the above cases apply, a default cursor is
+returned. For a text editor, the default cursor is an I-beam. For a
+pasteboard editor, the default cursor is an arrow.
+
+}}
+
+@defmethod[#:mode 'pubment
+ (after-edit-sequence)
+ void?]{
+
+@methspec{
+
+Called after a top-level edit sequence completes (involving unnested
+@method[editor<%> begin-edit-sequence] and @method[editor<%>
+end-edit-sequence]).
+
+See also @method[editor<%> on-edit-sequence].
+
+}
+
+@methimpl{
+
+Does nothing.
+
+}
+
+}
+
+@defmethod[#:mode 'pubment
+ (after-load-file [success? any/c])
+ void?]{
+
+@methspec{
+
+Called just after the editor is loaded from a file.
+
+The argument to the method originally specified whether the save was
+successful, but failures now trigger exceptions such that the method is
+not even called. Consequently, the argument is always @scheme[#t].
+
+See also
+@method[editor<%> can-load-file?] and
+@method[editor<%> on-load-file].
+
+}
+
+@methimpl{
+
+Does nothing.
+
+}
+}
+
+@defmethod[#:mode 'pubment
+ (after-save-file [success? any/c])
+ void?]{
+
+@methspec{
+
+Called just after the editor is saved to a file.
+
+The argument to the method originally specified whether the save was
+successful, but failures now trigger exceptions such that the method is
+not even called. Consequently, the argument is always @scheme[#t].
+
+See also
+@method[editor<%> can-save-file?] and
+@method[editor<%> on-save-file].
+
+}
+@methimpl{
+
+Does nothing.
+
+}
+}
+
+@defmethod*[([(auto-wrap)
+ boolean?]
+ [(auto-wrap [auto-wrap? any/c])
+ void?])]{
+
+Enables or disables automatically calling @method[editor<%>
+set-max-width] in response to @method[editor<%> on-display-size], or
+gets the state of auto-wrapping. For text editors, this has the effect
+of wrapping the editor's contents to fit in a canvas displaying the
+editor (the widest one if multiple canvases display the editor). For
+pasteboard editors, ``auto-wrapping'' merely truncates the area of the
+pasteboard to match its canvas @techlink{display}.
+
+When the wrapping mode is changed, the @method[editor<%>
+on-display-size] method is called immediately to update the editor's
+maximum width.
+
+Auto-wrapping is initially disabled.
+
+}
+
+@defmethod[(begin-edit-sequence [undoable? any/c #t]
+ [interrupt-streak? any/c #t])
+ void?]{
+
+@methspec{
+
+The @method[editor<%> begin-edit-sequence] and @method[editor<%>
+ end-edit-sequence] methods are used to bracket a set of editor
+ modifications so that the results are all displayed at once. The
+ commands may be nested arbitrarily deep. Using these functions can
+ greatly speed up displaying the changes.
+
+When an editor contains other editors, using @method[editor<%>
+ begin-edit-sequence] and @method[editor<%> end-edit-sequence] on the
+ main editor brackets some changes to the sub-editors as well, but it
+ is not as effective when a sub-editor changes as calling
+ @method[editor<%> begin-edit-sequence] and @method[editor<%>
+ end-edit-sequence] for the sub-editor.
+
+See also @method[editor<%> refresh-delayed?] and @method[editor<%>
+ in-edit-sequence?], and see @secref["mr:editorthreads"] for
+ information about edit sequences and refresh requests.
+
+If the @scheme[undoable?] flag is @scheme[#f], then the changes made
+ in the sequence cannot be reversed through the @method[editor<%>
+ undo] method. This flag is only effective for the outermost
+ @method[editor<%> begin-edit-sequence] when nested sequences are
+ used. Note that, for a @scheme[text%] object, the character-inserting
+ version of @method[text% insert] interferes with sequence-based undo
+ groupings.
+
+If the @scheme[interrupt-streak?] flag is @scheme[#f] and the sequence is
+ outermost, then special actions before and after the sequence count
+ as consecutive actions. For example, kills just before and after the
+ sequence are appended in the copy buffer.
+
+}
+@methimpl{
+
+Starts a sequence.
+
+}}
+
+@defmethod[(begin-write-header-footer-to-file [f (is-a?/c editor-stream-out%)]
+ [name string?]
+ [buffer (box/c (and/c exact? integer?))])
+ void?]{
+
+This method must be called before writing any special header data to a
+stream. See @|filediscuss| and @method[editor<%>
+write-headers-to-file] for more information.
+
+The @scheme[name] string must be a unique name that can be used by a
+ header reader to recognize the data. This method will store a value
+ in @scheme[buffer] that should be passed on to @method[editor<%>
+ end-write-header-footer-to-file].
+
+}
+
+@defmethod[(blink-caret)
+ void?]{
+
+@methspec{
+
+Tells the editor to blink the selection caret. This method is
+called periodically when the editor's @techlink{display} has the keyboard
+focus.
+
+}
+@methimpl{
+
+Propagates the request to any snip with the editor-local focus.
+
+}}
+
+@defmethod[(can-do-edit-operation? [op (one-of/c 'undo 'redo 'clear 'cut 'copy 'paste
+ 'kill 'select-all 'insert-text-box
+ 'insert-pasteboard-box 'insert-image)]
+ [recursive? any/c #t])
+ boolean?]{
+@methspec{
+
+Checks whether a generic edit command would succeed for the editor.
+ This check is especially useful for enabling and disabling menus on
+ demand. See @method[editor<%> do-edit-operation] for information
+ about the @scheme[op] and @scheme[recursive?] arguments.
+
+}
+@methimpl{
+
+Allows the operation depending on the selection, whether the editor is
+locked, etc.
+
+}}
+
+@defmethod[#:mode 'pubment
+ (can-load-file? [filename path?]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy)])
+ boolean?]{
+@methspec{
+
+Called just before the editor is loaded from a file. If the return
+value is @scheme[#f], the file is not loaded. See also
+@method[editor<%> on-load-file] and @method[editor<%>
+after-load-file].
+
+The @scheme[filename] argument is the name the file will be loaded
+ from. See @method[editor<%> load-file] for information about
+ @scheme[format].
+
+Note that the @scheme[filename] argument cannot be a string; it must
+be a path value.
+
+}
+@methimpl{
+
+Returns @scheme[#t].
+
+}}
+
+@defmethod[#:mode 'pubment
+ (can-save-file? [filename path?]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy)])
+ boolean?]{
+@methspec{
+
+Called just before the editor is saved to a file. If the return value
+is @scheme[#f], the file is not saved. See also @method[editor<%>
+on-save-file] and @method[editor<%> after-save-file].
+
+The @scheme[filename] argument is the name the file will be saved
+ to. See @method[editor<%> load-file] for information about
+ @scheme[format].
+
+Note that the @scheme[filename] argument cannot be a string; it must
+ be a path value.
+
+}
+
+@methimpl{
+
+Returns @scheme[#t].
+
+}}
+
+@defmethod*[([(change-style [delta (or/c (is-a?/c style-delta%) false/c)])
+ void?]
+ [(change-style [style (or/c (is-a?/c style<%>) false/c)])
+ void?])]{
+
+Changes the style for @techlink{items} in the editor, either by
+applying a style delta or using a specific style.
+
+To change a large collection of snips from one style to another style,
+ consider providing a @scheme[style<%>] instance rather than a
+ @scheme[style-delta%] instance. Otherwise, @method[editor<%>
+ change-style] must convert the @scheme[style-delta%] instance to the
+ @scheme[style<%>] instance for every snip; this conversion consumes
+ both time and (temporary) memory.
+
+@MonitorMethod[@elem{The style within an editor} @elem{the
+ system (in response to other method calls)} @elem{@xmethod[text% on-change-style]} @elem{style}]
+
+}
+
+@defmethod[(clear)
+ void?]{
+
+Deletes the currently selected @techlink{item}s.
+
+@|OnDeleteNote|
+
+}
+
+@defmethod[(clear-undos)
+ void?]{
+
+Destroys the undo history of the editor.
+
+}
+
+@defmethod[(copy [extend? any/c #f]
+ [time (and/c exact? integer?) 0])
+ void?]{
+
+Copies @techlink{item}s into the clipboard. If @scheme[extend?] is not
+ @scheme[#f], the old clipboard contents are appended.
+
+The system may execute a copy (in response to other method calls)
+ without calling this method. To extend or re-implement copying,
+ override the @xmethod[text% do-copy] or @xmethod[pasteboard% do-copy]
+ method of an editor.
+
+See @|timediscuss| for a discussion of the @scheme[time] argument. If
+ @scheme[time] is outside the platform-specific range of times,
+ @|MismatchExn|.
+
+
+}
+
+@defmethod[(copy-self)
+ (or/c (is-a?/c text%) (is-a?/c pasteboard%))]{
+
+Creates a new editor with the same properties as this one. After an
+ editor is created (either a @scheme[text%] or @scheme[pasteboard%]
+ instance, as appropriate), the new editor is passed to
+ @method[editor<%> copy-self-to].
+
+}
+
+
+@defmethod[(copy-self-to [dest (or/c (is-a?/c text%) (is-a?/c pasteboard%))])
+ void?]{
+
+Copies the properties of @this-obj[] to @scheme[dest].
+
+Each snip in @this-obj[] is copied and inserted into @scheme[dest].
+In addition, @this-obj[]'s filename, maximum undo history setting,
+keymap, interactive caret threshold, and overwrite-styles-on-load
+settings are installed into @scheme[dest]. Finally, @this-obj[]'s
+style list is copied and the copy is installed as the style list for
+@scheme[dest].
+
+}
+
+@defmethod[(cut [extend? any/c #f]
+ [time (and/c exact? integer?) 0])
+ void?]{
+
+Copies and then deletes the currently selected @techlink{item}s. If
+ @scheme[extend?] is not @scheme[#f], the old clipboard contents are
+ appended.
+
+The system may execute a cut (in response to other method calls)
+ without calling this method. To extend or re-implement the copying
+ portion of the cut, override the @xmethod[text% do-copy] or
+ @xmethod[pasteboard% do-copy] method of an editor. To monitor
+ deletions in an editor, override @xmethod[text% on-delete] or
+ @xmethod[pasteboard% on-delete].
+
+See @|timediscuss| for a discussion of the @scheme[time] argument. If
+ @scheme[time] is outside the platform-specific range of times,
+ @|MismatchExn|.
+
+}
+
+@defmethod[(dc-location-to-editor-location [x real?]
+ [y real?])
+ (values real? real?)]{
+
+Converts the given coordinates from top-level @techlink{display}
+ coordinates (usually canvas coordinates) to editor
+ @techlink{location} coordinates. The same calculation is performed
+ by @method[editor<%> global-to-local].
+
+@|OVD|
+
+See also @method[editor<%> editor-location-to-dc-location].
+
+}
+
+@defmethod[(default-style-name)
+ string?]{
+
+Returns the name of a style to be used for newly inserted text,
+ etc. The default is @scheme["Standard"].
+
+}
+
+@defmethod[(do-edit-operation [op (one-of/c 'undo 'redo 'clear 'cut 'copy 'paste
+ 'kill 'select-all 'insert-text-box
+ 'insert-pasteboard-box 'insert-image)]
+ [recursive? any/c #t]
+ [time (and/c exact? integer?) 0])
+ void?]{
+
+Performs a generic edit command. The @scheme[op] argument must be a
+valid edit command, one of:
+
+@itemize{
+@item{@scheme['undo] --- undoes the last operation}
+@item{@scheme['redo] --- undoes the last undo}
+@item{@scheme['clear] --- deletes the current selection}
+@item{@scheme['cut] --- cuts}
+@item{@scheme['copy] --- copies}
+@item{@scheme['paste] --- pastes}
+@item{@scheme['kill] --- cuts to the end of the current line, or cuts a newline if there is only whitespace between the selection and end of line}
+@item{@scheme['select-all] --- selects everything in the editor}
+@item{@scheme['insert-text-box] --- inserts a text editor as an @techlink{item} in this editor; see also
+@method[editor<%> on-new-box] .}
+@item{@scheme['insert-pasteboard-box] --- inserts a pasteboard editor as an @techlink{item} in this editor; see also
+@method[editor<%> on-new-box] .}
+@item{@scheme['insert-image] --- gets a filename from the user and inserts the image as an @techlink{item} in this editor; see also
+@method[editor<%> on-new-image-snip] .}
+}
+
+If @scheme[recursive?] is not @scheme[#f], then the command is passed on to
+ any active snips of this editor (i.e., snips which own the caret).
+
+See @|timediscuss| for a discussion of the @scheme[time] argument. If
+ @scheme[time] is outside the platform-specific range of times,
+ @|MismatchExn|.
+
+}
+
+@defmethod[(editor-location-to-dc-location [x real?]
+ [y real?])
+ (values real? real?)]{
+
+Converts the given coordinates from editor @techlink{location}
+ coordinates to top-level @techlink{display} coordinates (usually
+ canvas coordinates). The same calculation is performed by
+ @method[editor<%> local-to-global].
+
+@|OVD|
+
+See also @method[editor<%> dc-location-to-editor-location].
+
+}
+
+@defmethod[(end-edit-sequence)
+ void?]{
+
+See @method[editor<%> begin-edit-sequence].
+
+}
+
+@defmethod[(end-write-header-footer-to-file [f (is-a?/c editor-stream-out%)]
+ [buffer-value (and/c exact? integer?)])
+ void?]{
+
+This method must be called after writing any special header data to a
+stream. The @scheme[buffer-value] argument must be the value put in
+the @scheme[buffer] argument box by @method[editor<%>
+begin-write-header-footer-to-file].
+
+See @|filediscuss| and @method[editor<%> write-headers-to-file] for
+more information.
+
+}
+
+
+@defmethod[(find-first-snip)
+ (or/c (is-a?/c snip%) false/c)]{
+
+Returns the first snip in the editor, or @scheme[#f] if the editor is
+ empty. To get all of the snips in the editor, use the @xmethod[snip%
+ next] on the resulting snip.
+
+The first snip in a text editor is the one at @techlink{position}
+ 0. The first snip in a pasteboard is the frontmost
+ snip. (@|seesniporderdiscuss|)
+
+}
+
+@defmethod[(find-scroll-line [location real?])
+ nonnegative-exact-integer?]{
+
+Maps a vertical @techlink{location} within the editor to a vertical
+ scroll position.
+
+For @scheme[text%] objects: @|FCA| @|OVD|
+
+}
+
+@defmethod[(get-active-canvas)
+ (or/c (is-a?/c editor-canvas%) false/c)]{
+
+If the editor is displayed in a canvas, this method returns the canvas
+ that most recently had the keyboard focus (while the editor was
+ displayed). If no such canvas exists, @scheme[#f] is returned.
+
+}
+
+@defmethod[(get-admin)
+ (or/c (is-a?/c editor-admin%) false/c)]{
+
+Returns the @scheme[editor-admin%] object currently managing this
+ editor or @scheme[#f] if the editor is not displayed.
+
+}
+
+@defmethod[(get-canvas)
+ (or/c (is-a?/c editor-canvas%) false/c)]{
+
+If @method[editor<%> get-active-canvas] returns a canvas, that canvas
+ is also returned by this method. Otherwise, if @method[editor<%>
+ get-canvases] returns a non-empty list, the first canvas in the list
+ is returned, otherwise @scheme[#f] is returned.
+
+}
+
+@defmethod[(get-canvases)
+ (listof (is-a?/c editor-canvas%))]{
+
+Returns a list of canvases displaying the editor. An editor may be
+ displayed in multiple canvases and no other kind of @techlink{display}, or one
+ instance of another kind of @techlink{display} and no canvases. If the editor is
+ not displayed or the editor's current @techlink{display} is not a canvas,
+ @scheme[null] is returned.
+
+}
+
+@defmethod[(get-dc)
+ (or/c (is-a?/c dc<%>) false/c)]{
+
+Typically used (indirectly) by snip objects belonging to the
+ editor. Returns a destination drawing context which is suitable for
+ determining display sizing information, or @scheme[#f] if the editor
+ is not displayed.
+
+}
+
+@defmethod[(get-descent)
+ (and/c real? (not/c negative?))]{
+
+Returns the font descent for the editor. This method is primarily used
+ when an editor is an @techlink{item} within another editor.
+
+@|OVD| @FCAME[]
+
+}
+
+@defmethod[(get-extent [w (or/c (box/c (and/c real? (not/c negative?))) false/c)]
+ [h (or/c (box/c (and/c real? (not/c negative?))) false/c)])
+ void?]{
+
+Gets the current extent of the editor's graphical representation.
+@boxisfillnull[(scheme w) @elem{the editor's width}]
+@boxisfillnull[(scheme h) @elem{the editor's height}]
+
+@|OVD| @FCAME[]
+
+}
+
+@defmethod[(get-file [directory (or/c path? false/c)])
+ (or/c path-string? false/c)]{
+@methspec{
+
+Called when the user must be queried for a filename to load an
+ editor. A starting-directory path is passed in, but is may be
+ @scheme[#f] to indicate that any directory is fine.
+
+Note that the @scheme[directory] argument cannot be a string; it must
+ be a path value or @scheme[#f].
+
+}
+@methimpl{
+
+Calls the global @scheme[get-file] procedure.
+
+If the editor is displayed in a single canvas, then the canvas's
+ top-level frame is used as the parent for the file dialog. Otherwise,
+ the file dialog will have no parent.
+
+}}
+
+@defmethod[(get-filename [temp (box/c (or/c any/c false/c)) #f])
+ (or/c path-string? false/c)]{
+
+Returns the path name of the last file saved from or loaded into this
+ editor, @scheme[#f] if the editor has no filename.
+
+@boxisfill[(scheme temp) @elem{@scheme[#t] if the filename is temporary or @scheme[#f]
+otherwise}]
+
+}
+
+@defmethod[(get-flattened-text)
+ string?]{
+
+Returns the contents of the editor in text form. See @|textdiscuss| for
+a discussion of flattened vs. non-flattened text.
+
+}
+
+
+@defmethod[(get-focus-snip)
+ (or/c (is-a?/c snip%) false/c)]{
+
+@index['("keyboard focus" "snips")]{Returns} the snip within the
+ editor that gets the keyboard focus when the editor has the focus, or
+ @scheme[#f] if the editor does not delegate the focus.
+
+The returned snip might be an @scheme[editor-snip%] object. In that
+ case, the embedded editor might delegate the focus to one of its own
+ snips. However, the @method[editor<%> get-focus-snip] method returns
+ only the @scheme[editor-snip%] object, because it is the focus-owning
+ snip within the immediate editor.
+
+See also @method[editor<%> set-caret-owner].
+
+}
+
+
+@defmethod[(get-inactive-caret-threshold)
+ (one-of/c 'no-caret 'show-inactive-caret 'show-caret)]{
+
+Returns the threshold for painting an inactive selection. This
+ threshold is compared with the @scheme[draw-caret] argument to
+ @method[editor<%> refresh] and if the argument is as least as large
+ as the threshold (but larger than @indexed-scheme['show-caret]), the
+ selection is drawn as inactive.
+
+See also @method[editor<%> set-inactive-caret-threshold] and
+ @|drawcaretdiscuss|.
+
+}
+
+
+@defmethod[(get-keymap)
+ (or/c (is-a?/c keymap%) false/c)]{
+
+Returns the main keymap currently used by the editor.
+
+}
+
+
+@defmethod[(get-load-overwrites-styles)
+ boolean?]{
+
+Reports whether named styles in the current style list are replaced by
+ @method[editor<%> load-file] when the loaded file contains style
+ specifications.
+
+See also @method[editor<%> set-load-overwrites-styles].
+
+}
+
+@defmethod[(get-max-height)
+ (or/c (and/c real? (not/c negative?)) (one/of 'none))]{
+
+Gets the maximum display height for the contents of the editor; zero or
+ @scheme['none] indicates that there is no maximum.
+
+}
+
+@defmethod[(get-max-undo-history)
+ (integer-in 0 100000)]{
+
+Returns the maximum number of undoables that will be remembered by the
+ editor. Note that undoables are counted by insertion, deletion,
+ etc. events, not by the number of times that @method[editor<%> undo]
+ can be called; a single @method[editor<%> undo] call often reverses
+ multiple events at a time (such as when the user types a stream of
+ characters at once).
+
+}
+
+@defmethod[(get-max-view-size)
+ (values real? real?)]{
+
+Returns the maximum visible area into which the editor is currently
+ being displayed, according to the editor's administrators. If the
+ editor has only one @techlink{display}, the result is the same as for
+ @method[editor<%> get-view-size]. Otherwise, the maximum width and
+ height of all the editor's displaying canvases is returned.
+
+@|OVD|
+
+If the @techlink{display} is an editor canvas, see also
+ @method[area-container<%> reflow-container].
+
+}
+
+@defmethod[(get-max-width)
+ (or/c (and/c real? (not/c negative?)) (one/of 'none))]{
+
+Gets the maximum display width for the contents of the editor; zero or
+ @scheme['none] indicates that there is no maximum. In a text editor,
+ zero of @scheme['none] disables automatic line breaking.
+
+}
+
+@defmethod[(get-min-height)
+ (or/c (and/c real? (not/c negative?)) (one/of 'none))]{
+
+Gets the minimum display height for the contents of the editor; zero
+ or @scheme['none] indicates that there is no minimum.
+
+}
+
+
+@defmethod[(get-min-width)
+ (or/c (and/c real? (not/c negative?)) (one/of 'none))]{
+
+Gets the minimum display width for the contents of the editor; zero or
+ @scheme['none] indicates that there is no minimum.
+
+}
+
+@defmethod[(get-paste-text-only)
+ boolean?]{
+
+If the result is @scheme[#t], then the editor accepts only plain-text
+ data from the clipboard. If the result is @scheme[#f], the editor
+ accepts both text and snip data from the clipboard.
+
+}
+
+@defmethod[(get-snip-data [thesnip (is-a?/c snip%)])
+ (or/c (is-a?/c editor-data%) false/c)]{
+
+@methspec{
+
+Gets extra data associated with a snip (e.g., @techlink{location}
+ information in a pasteboard) or returns @scheme[#f] is there is no
+ information. See @|editordatadiscuss| for more information.
+
+}
+@methimpl{
+
+Returns @scheme[#f].
+
+}}
+
+
+@defmethod[(get-snip-location [thesnip (is-a?/c snip%)]
+ [x (or/c (box/c real?) false/c) #f]
+ [y (or/c (box/c real?) false/c) #f]
+ [bottom-right? any/c #f])
+ boolean?]{
+
+Gets the @techlink{location} of the given snip. If the snip is found in
+ the editor, @scheme[#t] is returned; otherwise, @scheme[#f] is returned.
+
+@boxisfillnull[(scheme x) @elem{the x-coordinate of the snip's @techlink{location}}]
+@boxisfillnull[(scheme y) @elem{the y-coordinate of the snip's @techlink{location}}]
+
+If @scheme[bottom-right?] is not @scheme[#f], the values in the
+ @scheme[x] and @scheme[y] boxes are for the snip's bottom right
+ corner instead of its top-left corner.
+
+Obtaining the @techlink{location} if the bottom-right corner may
+ trigger delayed size calculations (including snips other than
+ the one whose @techlink{location} was requested).
+
+@|OVD| As a special case, however, a @scheme[pasteboard%] object
+ always reports valid answers when @scheme[bottom-right?] is @scheme[#f].
+ @FCAME[]
+
+}
+
+
+@defmethod[(get-space)
+ (and/c real? (not/c negative?))]{
+
+Returns the maximum font space for the editor. This method is
+ primarily used when an editor is an @techlink{item} within another
+ editor.
+
+@|OVD| @FCAME[]
+
+}
+
+@defmethod[(get-style-list)
+ (is-a?/c style-list%)]{
+
+Returns the style list currently in use by the editor.
+
+}
+
+
+@defmethod[(get-view-size [w (or/c (box/c (and/c real? (not/c negative?))) false/c)]
+ [h (or/c (box/c (and/c real? (not/c negative?))) false/c)])
+ void?]{
+
+Returns the visible area into which the editor is currently being
+ displayed (according to the editor's administrator). See also
+ @method[editor-admin% get-view] .
+
+@boxisfillnull[(scheme w) @elem{the visible area width}]
+@boxisfillnull[(scheme h) @elem{the visible area height}]
+
+@|OVD|
+
+If the @techlink{display} is an editor canvas, see also
+@method[area-container<%> reflow-container].
+
+}
+
+@defmethod[(global-to-local [x (or/c (box/c real?) false/c)]
+ [y (or/c (box/c real?) false/c)])
+ void?]{
+
+Converts the given coordinates from top-level @techlink{display} coordinates
+ (usually canvas coordinates) to editor @techlink{location} coordinates. The
+ same calculation is performed by
+@method[editor<%> dc-location-to-editor-location].
+
+@boxisfillnull[(scheme x) @elem{the translated x-coordinate of the value initially
+in @scheme[x]}]
+@boxisfillnull[(scheme y) @elem{the translated x-coordinate of the value initially
+in @scheme[y]}]
+
+@|OVD|
+
+See also @method[editor<%> local-to-global].
+
+}
+
+@defmethod[(in-edit-sequence?)
+ boolean?]{
+
+Returns @scheme[#t] if updating on this editor is currently delayed
+ because @method[editor<%> begin-edit-sequence] has been called for
+ this editor.
+
+See also @method[editor<%> refresh-delayed?].
+
+}
+
+
+@defmethod[(insert [snip (is-a?/c snip%)])
+ void?]{
+
+Inserts data into the editor. A snip cannot be inserted into multiple
+ editors or multiple times within a single editor.
+
+@|OnInsertNote|
+
+}
+
+
+@defmethod[(insert-box [type (one-of/c 'text 'pasteboard) 'text])
+ void?]{
+
+Inserts a box (a sub-editor) into the editor by calling
+@method[editor<%> on-new-box], then passing along @scheme[type] and
+inserts the resulting snip into the editor.
+
+@|OnInsertNote|
+
+}
+
+
+@defmethod*[([(insert-file [filename path-string?]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'guess]
+ [show-errors? any/c #t])
+ boolean?]
+ [(insert-file [port input-port]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'guess]
+ [show-errors? any/c #t])
+ boolean?])]{
+
+Inserts the content of a file or port into the editor (at the current
+ selection @techlink{position} in @scheme[text%] editors). The result
+ is @scheme[#t]; if an error occurs, an exception is raised.
+
+If @scheme[port] is supplied, it must support position setting with
+@scheme[file-position].
+
+For information on @scheme[format], see @method[editor<%> load-file].
+The @scheme[show-errors?] argument is no longer used.
+
+@|OnInsertNote|
+
+}
+
+
+@defmethod[(insert-image [filename (or/c path-string? false/c) #f]
+ [type (one-of/c 'unknown 'gif 'jpeg 'xbm 'xpm 'bmp 'pict) 'unknown]
+ [relative-path? any/c #f]
+ [inline? any/c #t])
+ void?]{
+
+Inserts an image into the editor.
+
+If @scheme[filename] is @scheme[#f], then the
+user is queried for a filename. The @scheme[kind] must one of
+the symbols that can be passed to
+@method[bitmap% load-file].
+
+After the filename has been determined, an image is created by
+calling
+@method[editor<%> on-new-image-snip]. See also
+@scheme[image-snip%].
+
+@|OnInsertNote|
+
+}
+
+@defmethod[(insert-port [port input-port]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'guess]
+ [show-errors? any/c #t])
+ (one-of/c 'standard 'text 'text-force-cr)]{
+
+Use @method[editor<%> insert-file], instead.
+
+Inserts the content of a port into the editor (at the current
+ selection @techlink{position} in @scheme[text%] editors) without wrapping
+ the insert operations as an edit sequence. The result is the actual
+ format of the loaded content (which is different from the given
+ format type if the given format is @scheme['guess], @scheme['same], or
+ @scheme['copy]).
+
+The @scheme[port] must support position setting with @scheme[file-position].
+
+For information on @scheme[format], see
+@method[editor<%> load-file].
+
+The @scheme[show-errors?] argument is no longer used.
+
+}
+
+@defmethod[(invalidate-bitmap-cache [x real? 0.0]
+ [y real? 0.0]
+ [width (or/c (and/c real? (not/c negative?)) (one/of 'end)) 'end]
+ [height (or/c (and/c real? (not/c negative?)) (one/of 'end)) 'end])
+ void?]{
+
+When @method[editor<%> on-paint] is overridden, call this method when
+ the state of @method[editor<%> on-paint]'s drawing changes.
+
+The @scheme[x], @scheme[y], @scheme[width], and @scheme[height]
+ arguments specify the area that needs repainting in editor
+ coordinates. If @scheme[width]/@scheme[height] is @scheme['end], then
+ the total height/width of the editor (as reported by
+ @method[editor<%> get-extent]) is used. Note that the editor's size
+ can be smaller than the visible region of its @techlink{display}.
+
+The default implementation triggers a redraw of the editor, either
+ immediately or at the end of the current edit sequence (if any)
+ started by @method[editor<%> begin-edit-sequence].
+
+}
+
+
+@defmethod[(is-locked?)
+ boolean?]{
+
+Returns @scheme[#t] if the editor is currently locked, @scheme[#f]
+ otherwise. See @method[editor<%> lock] for more information.
+
+}
+
+
+@defmethod[(is-modified?)
+ boolean?]{
+
+Returns @scheme[#t] is the editor has been modified since the last
+ save or load (or the last call to @method[editor<%> set-modified]
+ with @scheme[#f]), @scheme[#f] otherwise.
+
+}
+
+
+@defmethod[(kill [time (and/c exact? integer?) 0])
+ void?]{
+
+In a text editor, cuts to the end of the current line, or cuts a
+ newline if there is only whitespace between the selection and end of
+ line. Multiple consecutive kills are appended. In a pasteboard
+ editor, cuts the current selection.
+
+See @|timediscuss| for a discussion of the @scheme[time] argument. If
+ @scheme[time] is outside the platform-specific range of times,
+ @|MismatchExn|.
+
+See also @method[editor<%> cut].
+
+@|OnDeleteNote|
+
+}
+
+
+@defmethod[(load-file [filename (or/c path-string? false/c) #f]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'guess]
+ [show-errors? any/c #t])
+ boolean?]{
+
+
+Loads a file into the editor and returns @scheme[#t]. If an error
+ occurs, an exception is raised.
+
+If @scheme[filename] is @scheme[#f], then the
+internally stored filename will be used; if @scheme[filename] is @scheme[""] or
+if the internal name is unset or temporary, then the user will be
+prompted for a name.
+
+The possible values for @scheme[format] are listed below. A single set of
+@scheme[format] values are used for loading and saving files:
+@itemize{
+
+@item{@scheme['guess] --- guess the format based on
+extension and/or contents; when saving a file, this is the same as
+@scheme['standard]}
+
+@item{@scheme['standard] --- read/write a standard file (binary format)}
+
+@item{@scheme['text] --- read/write a text file (@scheme[text%] only)}
+
+@item{@scheme['text-force-cr] --- read/write a text
+file (@scheme[text%] only); when writing, change automatic
+newlines (from word-wrapping) into real carriage returns}
+
+@item{@scheme['same] --- read in whatever format was last loaded or saved}
+
+@item{@scheme['copy] --- write using whatever
+format was last loaded or saved, but do not change the modification
+flag or remember @scheme[filename] (saving only)}
+
+}
+
+In a @scheme[text%] instance, the format returned from
+@method[text% get-file-format] is always one of @scheme['standard],
+@scheme['text], or
+@scheme['text-force-cr].
+
+The @scheme[show-errors?] argument is no longer used.
+
+The filename used to load the file can be retrieved with
+ @method[editor<%> get-filename]. For a @scheme[text%] instance, the
+ format can be retrieved with @method[text% get-file-format]. However,
+ if an error occurs while loading the file, the filename is set to
+ @scheme[#f].
+
+See also @method[editor<%> on-load-file], @method[editor<%>
+ after-load-file], @method[editor<%> can-load-file?], and
+ @method[editor<%> set-load-overwrites-styles].
+
+}
+
+@defmethod[(local-to-global [x (box/c real?)]
+ [y (box/c real?)])
+ void?]{
+
+Converts the given coordinates from editor @techlink{location}
+ coordinates to top-level @techlink{display} coordinates (usually
+ canvas coordinates). The same calculation is performed by
+ @method[editor<%> editor-location-to-dc-location].
+
+@boxisfillnull[(scheme x) @elem{the translated x-coordinate of the value initially
+in @scheme[x]}]
+@boxisfillnull[(scheme y) @elem{the translated x-coordinate of the value initially
+in @scheme[y]}]
+
+@|OVD|
+
+See also @method[editor<%> global-to-local].
+
+}
+
+
+@defmethod[(locations-computed?)
+ boolean?]{
+
+Returns @scheme[#t] if all @techlink{location} information has been
+ computed after recent changes to the editor's content or to its
+ snips, @scheme[#f] otherwise.
+
+Location information is often computed on demand, and
+ @method[editor<%> begin-edit-sequence] tends to delay the
+ computation.
+
+When the editor is locked for reflowing, location information cannot
+ be recomputed. See also @|lockdiscuss|.
+
+}
+
+
+@defmethod[(lock [lock? any/c])
+ void?]{
+
+Locks or unlocks the editor for modifications. If an editor is locked,
+ @italic{all} modifications are blocked, not just user modifications.
+
+See also @method[editor<%> is-locked?].
+
+This method does not affect internal locks, as discussed in
+ @|lockdiscuss|.
+
+}
+
+@defmethod[(locked-for-flow?)
+ boolean?]{
+
+Reports whether the editor is internally locked for flowing. See
+ @|lockdiscuss| for more information.
+
+}
+
+
+@defmethod[(locked-for-read?)
+ boolean?]{
+
+Reports whether the editor is internally locked for reading. See
+ @|lockdiscuss| for more information.
+
+}
+
+
+@defmethod[(locked-for-write?)
+ boolean?]{
+
+Reports whether the editor is internally locked for writing. See
+ @|lockdiscuss| for more information.
+
+}
+
+
+@defmethod[(needs-update [snip (is-a?/c snip%)]
+ [localx real?]
+ [localy real?]
+ [w (and/c real? (not/c negative?))]
+ [h (and/c real? (not/c negative?))])
+ void?]{
+
+Typically called (indirectly) by a snip within the editor to force the
+editor to be redrawn.
+
+The @scheme[localx], @scheme[localy], @scheme[width], and @scheme[height]
+ arguments specify the area that needs repainting in the coordinate
+ system of @scheme[snip].
+
+@FCAME[]
+
+}
+
+
+@defmethod[(num-scroll-lines)
+ nonnegative-exact-integer?]{
+
+Reports the number of scroll positions available within the editor.
+
+For @scheme[text%] objects: @|FCA| @|EVD|
+
+}
+
+
+@defmethod[#:mode 'pubment
+ (on-change)
+ void?]{
+
+@methspec{
+
+Called whenever any change is made to the editor that affects the way
+ the editor is drawn or the values reported for the
+ @techlink{location}/size of some snip in the editor. The
+ @method[editor<%> on-change] method is called just before the editor
+ calls its administrator's @method[editor-admin% needs-update] method
+ to refresh the editor's @techlink{display}, and it is also called
+ just before and after printing an editor.
+
+The editor is locked for writing and reflowing during the call to
+@method[editor<%> on-change].
+
+}
+@methimpl{
+
+Does nothing.
+
+}}
+
+
+@defmethod[(on-char [event (is-a?/c key-event%)])
+ void?]{
+@methspec{
+
+Handles keyboard input to the editor.
+
+Consider overriding @method[editor<%> on-local-char] or
+@method[editor<%> on-default-char] instead of this method.
+
+}
+@methimpl{
+
+Either passes this event on to a caret-owning snip or calls
+ @method[editor<%> on-local-char]. In the latter case, @scheme[text%]
+ first calls @scheme[hide-cursor-until-moved].
+
+}}
+
+@defmethod[(on-default-char [event (is-a?/c key-event%)])
+ void?]{
+@methspec{
+
+Called by @method[editor<%> on-local-char] when the event is
+ @italic{not} handled by a caret-owning snip or by the keymap.
+
+}
+@methimpl{
+
+Does nothing.
+
+}}
+
+@defmethod[(on-default-event [event (is-a?/c mouse-event%)])
+ void?]{
+
+@methspec{
+
+Called by @method[editor<%> on-local-event] when the event is
+ @italic{not} handled by a caret-owning snip or by the keymap.
+
+}
+@methimpl{
+
+Does nothing. See also @xmethod[text% on-default-event] and
+ @xmethod[pasteboard% on-default-event].
+
+}}
+
+
+@defmethod[#:mode 'pubment
+ (on-display-size)
+ void?]{
+
+@methspec{
+
+This method is called by the editor's @techlink{display} whenever the
+ display's size (as reported by @method[editor<%> get-view-size])
+ changes, but it is called indirectly through @method[editor<%>
+ on-display-size-when-ready].
+
+}
+@methimpl{
+
+If automatic wrapping is enabled (see @method[editor<%> auto-wrap] )
+ then @method[editor<%> set-max-width] is called with the maximum
+ width of all of the editor's canvases (according to the
+ administrators; @xmethod[editor-canvas% call-as-primary-owner] is
+ used with each canvas to set the administrator and get the view
+ size). If the editor is displayed but not in a canvas, the unique
+ width is obtained from the editor's administrator (there is only
+ one). If the editor is not displayed, the editor's maximum width is
+ not changed.
+
+}}
+
+
+@defmethod[(on-display-size-when-ready)
+ void?]{
+
+Calls @method[editor<%> on-display-size] unless the editor is
+ currently in an edit sequence or currently being refreshed. In the
+ latter cases, the call to @method[editor<%> on-display-size] is
+ delegated to another thread; see @secref["mr:editorthreads"] for more
+ information.
+
+}
+
+
+@defmethod[#:mode 'pubment
+ (on-edit-sequence)
+ void?]{
+
+@methspec{
+
+Called just after a top-level (i.e., unnested) edit sequence starts.
+
+During an edit sequence, all callbacks methods are invoked normally,
+ but it may be appropriate for these callbacks to delay computation
+ during an edit sequence. The callbacks must manage this delay
+ manually. Thus, when overriding other callback methods, such as
+ @xmethod[text% on-insert], @xmethod[pasteboard% on-insert],
+ @xmethod[text% after-insert], or @xmethod[pasteboard% after-insert],
+ consider overriding @method[editor<%> on-edit-sequence] and
+ @method[editor<%> after-edit-sequence] as well.
+
+``Top-level edit sequence'' refers to an outermost pair of
+ @method[editor<%> begin-edit-sequence] and @method[editor<%>
+ end-edit-sequence] calls. The embedding of an editor within another
+ editor does not affect the timing of calls to @method[editor<%>
+ on-edit-sequence], even if the embedding editor is in an edit
+ sequence.
+
+Pairings of @method[editor<%> on-edit-sequence] and @method[editor<%>
+ after-edit-sequence] can be nested if an @method[editor<%>
+ after-edit-sequence] starts a new edit sequence, since
+ @method[editor<%> after-edit-sequence] is called after an edit
+ sequence ends. However, @method[editor<%> on-edit-sequence] can never
+ start a new top-level edit sequence (except through an unpaired
+ @method[editor<%> end-edit-sequence]), because it is called after a
+ top-level edit sequence starts.
+
+}
+@methimpl{
+
+Does nothing.
+
+}}
+
+
+@defmethod[(on-event [event (is-a?/c mouse-event%)])
+ void?]{
+
+@methspec{
+
+Handles mouse input to the editor. The event's x and y coordinates
+ are in the @techlink{display}'s co-ordinate system; use the
+ administrator's @method[editor-admin% get-dc] method to obtain
+ translation arguments (or use @method[editor<%>
+ dc-location-to-editor-location]).
+
+Consider overriding @method[editor<%> on-local-event] or
+ @method[editor<%> on-default-event] instead of this method.
+
+}
+@methimpl{
+
+Either passes this event on to a caret-owning snip, selects a new
+ caret-owning snip (@scheme[text%] only) and passes the event on to
+ the selected snip, or calls @method[editor<%> on-local-event]. A new
+ caret-owning snip is selected in a @scheme[text%] object when the
+ click is on an event-handling snip, and not too close to the space
+ between snips (see @method[text% get-between-threshold] ).
+
+}}
+
+
+@defmethod[(on-focus [on? any/c])
+ void?]{
+
+@index['("keyboard focus" "notification")]{Called} when the keyboard
+ focus changes into or out of this editor (and not to/from a snip
+ within the editor) with @scheme[#t] if the focus is being turned on,
+ @scheme[#f] otherwise.
+
+}
+
+
+@defmethod[#:mode 'pubment
+ (on-load-file [filename path?]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy)])
+ void?]{
+@methspec{
+
+Called just before the editor is loaded from a file, after calling
+ @method[editor<%> can-load-file?] to verify that the load is
+ allowed. See also @method[editor<%> after-load-file].
+
+The @scheme[filename] argument is the name the file will be loaded
+ from. See @method[editor<%> load-file] for information about
+ @scheme[format].
+
+Note that the @scheme[filename] argument cannot be a string; it must
+ be a path value.
+
+}
+@methimpl{
+
+Does nothing.
+
+}}
+
+@defmethod[(on-local-char [event (is-a?/c key-event%)])
+ void?]{
+@methspec{
+
+Called by @method[editor<%> on-char] when the event is @italic{not}
+ handled by a caret-owning snip.
+
+Consider overriding @method[editor<%> on-default-char] instead of this
+ method.
+
+}
+@methimpl{
+
+Either lets the keymap handle the event or calls @method[editor<%>
+ on-default-char].
+
+}}
+
+
+@defmethod[(on-local-event [event (is-a?/c mouse-event%)])
+ void?]{
+@methspec{
+
+Called by @method[editor<%> on-event] when the event is @italic{not}
+ handled by a caret-owning snip.
+
+Consider overriding @method[editor<%> on-default-event] instead of
+ this method.
+
+}
+@methimpl{
+
+Either lets the keymap handle the event or calls
+ @method[editor<%> on-default-event].
+
+}}
+
+
+@defmethod[(on-new-box [type (one-of/c 'text 'pasteboard)])
+ (is-a?/c snip%)]{
+@methspec{
+
+Creates and returns a new snip for an embedded editor. This method is
+ called by @method[editor<%> insert-box].
+
+}
+@methimpl{
+
+Creates a @scheme[editor-snip%] with either a sub-editor from
+ @scheme[text%] or sub-pasteboard from @scheme[pasteboard%], depending
+ on whether @scheme[type] is @scheme['text] or
+ @scheme['pasteboard]. The keymap (see @scheme[keymap%]) and style
+ list (see @scheme[style-list%]) for of the new sub-editor are set to
+ the keymap and style list of this editor.
+
+}}
+
+
+@defmethod[(on-new-image-snip [filename (or/c path? false/c)]
+ [kind (one-of/c 'unknown 'gif 'jpeg 'xbm 'xpm 'bmp 'pict)]
+ [relative-path? any/c]
+ [inline? any/c])
+ (is-a?/c image-snip%)]{
+@methspec{
+
+Creates and returns a new instance of @scheme[image-snip%] for
+ @method[editor<%> insert-image].
+
+Note that the @scheme[filename] argument cannot be a string; it must be a
+ path value.
+
+}
+@methimpl{
+
+Returns @scheme[(make-object image-snip% filename kind relative-path? inline?)].
+
+}}
+
+
+@defmethod[(on-paint [before? any/c]
+ [dc (is-a?/c dc<%>)]
+ [left real?]
+ [top real?]
+ [right real?]
+ [bottom real?]
+ [dx real?]
+ [dy real?]
+ [draw-caret (one-of/c 'no-caret 'show-inactive-caret 'show-caret)])
+ void?]{
+@methspec{
+
+Provides a way to add arbitrary graphics to an editor's @techlink{display}. This
+ method is called just before and just after every painting of the
+ editor.
+
+The @scheme[before?] argument is @scheme[#t] when the method is called just
+ before a painting the contents of the editor or @scheme[#f] when it is
+ called after painting. The @scheme[left], @scheme[top], @scheme[right], and
+ @scheme[bottom] arguments specify which region of the editor is being
+ repainted, in editor coordinates. To get the coordinates for
+ @scheme[dc], offset editor coordinates by adding (@scheme[dx], @scheme[dy]).
+ See @|drawcaretdiscuss| for information about @scheme[draw-caret].
+
+The @method[editor<%> on-paint] method, together with the snips'
+ @method[snip% draw] methods, must be able to draw the entire state of
+ an editor. Never paint directly into an editor's @techlink{display}
+ canvas except from within @method[editor<%> on-paint] or
+ @method[snip% draw]. Instead, put all extra drawing code within
+ @method[editor<%> on-paint] and call @method[editor<%>
+ invalidate-bitmap-cache] when part of the @techlink{display} needs to
+ be repainted.
+
+If an @method[editor<%> on-paint] method uses cached
+ @techlink{location} information, then the cached information should
+ be recomputed in response to a call of @method[editor<%>
+ invalidate-bitmap-cache].
+
+The @method[editor<%> on-paint] method must not make any assumptions
+ about the state of the drawing context (e.g., the current pen),
+ except that the clipping region is already set to something
+ appropriate. Before @method[editor<%> on-paint] returns, it must
+ restore any drawing context settings that it changes.
+
+The editor is internally locked for writing and reflowing during a
+ call to this method (see also @|lockdiscuss|).
+
+See also @method[editor<%> invalidate-bitmap-cache].
+
+}
+@methimpl{
+
+Does nothing.
+
+}}
+
+@defmethod[#:mode 'pubment
+ (on-save-file [filename path?]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy)])
+ void?]{
+@methspec{
+
+Called just before the editor is saved to a file, after calling
+@method[editor<%> can-save-file?] to verify that the save is
+allowed. See also @method[editor<%> after-save-file].
+
+The @scheme[filename] argument is the name the file will be saved
+to. See @method[editor<%> load-file] for information about
+@scheme[format].
+
+Note that the @scheme[filename] argument cannot be a string; it must
+ be a path value.
+
+
+}
+@methimpl{
+
+Does nothing.
+
+}}
+
+
+@defmethod[#:mode 'pubment
+ (on-snip-modified [snip (is-a?/c snip%)]
+ [modified? any/c])
+ void?]{
+@methspec{
+
+This method is called whenever a snip within the editor reports that
+ it has been modified (by calling its adminstrator's
+ @method[snip-admin% modified] method). The method arguments are the
+ snip that reported a modification-state change, and the snip's new
+ modification state.
+
+See also @method[editor<%> set-modified].
+
+}
+@methimpl{
+
+If @scheme[modified?] is true and the editor was not already modified
+ (i.e., its @method[editor<%> is-modified?] method reports
+ @scheme[#f]), then the @method[editor<%> set-modified] method is
+ called with @scheme[#t]. If the editor was already modified, then the
+ internal modify-counter is incremented.
+
+If @scheme[modified?] is @scheme[#f], and if the modify-counter is
+ @scheme[1], then the @method[editor<%> set-modified] method is called
+ with @scheme[#f] (on the assumption that the modify-counter was set
+ to @scheme[1] by an earlier call to this method for the same snip).
+
+}}
+
+@defmethod[(own-caret [own? any/c])
+ void?]{
+@methspec{
+
+Tells the editor to display or not display the caret or selection.
+
+@MonitorMethod[@elem{The focus state of an editor} @elem{by the system} @elem{@method[editor<%> on-focus]} @elem{focus}]
+
+}
+@methimpl{
+
+Propagates the flag to any snip with the editor-local focus. If no
+ sub-editors are active, the editor assumes the caret ownership.
+
+}}
+
+
+@defmethod[(paste [time (and/c exact? integer?) 0])
+ void?]{
+
+Pastes the current contents of the clipboard into the editor.
+
+See @|timediscuss| for a discussion of the @scheme[time] argument. If
+ @scheme[time] is outside the platform-specific range of times,
+ @|MismatchExn|.
+
+The system may execute a paste (in response to other method calls)
+ without calling this method. To extend or re-implement copying,
+ override the @xmethod[text% do-paste] or @xmethod[pasteboard%
+ do-paste] method.
+
+See also @method[editor<%> get-paste-text-only].
+
+}
+
+
+@defmethod[(paste-x-selection [time (and/c exact? integer?) 0])
+ void?]{
+
+Like @method[editor<%> paste], but under X, uses the X selection
+instead of the X clipboard.
+
+See @|timediscuss| for a discussion of the @scheme[time] argument. If
+ @scheme[time] is outside the platform-specific range of times,
+ @|MismatchExn|.
+
+To extend or re-implement copying, override the @xmethod[text%
+ do-paste-x-selection] or @xmethod[pasteboard% do-paste-x-selection]
+ method.
+
+}
+
+
+@defmethod[(print [interactive? any/c #t]
+ [fit-on-page? any/c #t]
+ [output-mode (one-of/c 'standard 'postscript) 'standard]
+ [parent (or/c (or/c @scheme[frame%] (is-a?/c dialog%)) false/c) #f]
+ [force-ps-page-bbox? any/c #t]
+ [as-eps? any/c #f])
+ void?]{
+
+Prints the editor.
+
+If @scheme[interactive?] is true and a PostScript file is created, the
+ is given a dialog for adjusting printing parameters; see also
+ @scheme[get-ps-setup-from-user]. Otherwise, if a PostScript file is
+ created, the settings returned by @scheme[current-ps-setup] are
+ used. (The user may still get a dialog to select an output file name;
+ see @scheme[post-script-dc%] for more details.)
+
+If @scheme[fit-on-page?] is a true value, then during printing for a
+ @scheme[text%] editor, the editor's maximum width is set to the width
+ of the page (less margins) and the autowrapping bitmap is removed.
+
+The @scheme[output-mode] setting is used for Windows and
+ Mac OS X. It determines whether the output is generated
+ directly as a PostScript file (using MrEd's built-in PostScript
+ system) or generated using the platform-specific standard printing
+ mechanism. The possible values are
+
+@itemize{
+
+ @item{@scheme['standard] --- print using the platform-standard
+ mechanism (via a @scheme[printer-dc%]) under Windows and
+ Mac OS X, PostScript for Unix (via a @scheme[post-script-dc%])}
+
+ @item{@scheme['postscript] --- print to a PostScript file (via a
+ @scheme[post-script-dc%])}
+
+}
+
+If @scheme[parent] is not @scheme[#f], it is used as the parent window
+ for configuration dialogs (for either PostScript or platform-standard
+ printing). If @scheme[parent] is @scheme[#f] and if the editor is
+ displayed in a single canvas, then the canvas's top-level frame is
+ used as the parent for configuration dialogs. Otherwise,
+ configuration dialogs will have no parent.
+
+The @scheme[force-ps-page-bbox?] argument is used for PostScript
+ printing, and is used as the third initialization argument when
+ creating the @scheme[post-script-dc%] instance. Unless it is
+ @scheme[#f], the bounding-box of the resulting PostScript file is set
+ to the current paper size.
+
+The @scheme[as-eps?] argument is used for PostScript printing, and is
+ used as the fourth initialization argument when creating the
+ @scheme[post-script-dc%] instance. Unless it is @scheme[#f], the
+ resulting PostScript file is identified as Encapsulated PostScript
+ (EPS).
+
+The printing margins are determined by @method[ps-setup%
+ get-editor-margin] in the current @scheme[ps-setup%] object (as
+ determined by @scheme[current-ps-setup]).
+
+}
+
+
+@defmethod[(print-to-dc [dc (is-a?/c dc<%>)])
+ void?]{
+
+Prints the editor into the given drawing context. See also
+ @method[editor<%> print].
+
+}
+
+
+@defmethod[(put-file [directory (or/c path? false/c)]
+ [default-name (or/c path? false/c)])
+ (or/c path-string? false/c)]{
+@methspec{
+
+Called when the user must be queried for a filename to save an
+ editor. Starting-directory and default-name paths are passed in,
+ but either may be @scheme[#f] to indicate that any directory is fine or
+ there is no default name.
+
+Note that the @scheme[directory] and @scheme[filename] arguments
+ cannot be strings; each must be a path value.
+
+}
+@methimpl{
+
+Calls the global @scheme[put-file] procedure.
+
+If the editor is displayed in a single canvas, then the canvas's
+ top-level frame is used as the parent for the file dialog. Otherwise,
+ the file dialog will have no parent.
+
+}}
+
+
+@defmethod[(read-footer-from-file [stream (is-a?/c editor-stream-in%)]
+ [name string?])
+ boolean?]{
+
+See @method[editor<%> read-header-from-file].
+
+}
+
+
+@defmethod[(read-from-file [stream (is-a?/c editor-stream-in%)]
+ [overwrite-styles? any/c #t])
+ boolean?]{
+
+Reads new contents for the editor from a stream. The return value is
+ @scheme[#t] if there are no errors, @scheme[#f] otherwise. See also
+ @|filediscuss|.
+
+The stream provides either new mappings for names in the editor's
+ style list, or it indicates that the editor should share a
+ previously-read style list (depending on how style lists were shared
+ when the editor was written to the stream; see also @method[editor<%>
+ write-to-file]).
+
+@itemize{
+
+ @item{In the former case, if the @scheme[overwrite-styles?] argument
+ is @scheme[#f], then each style name in the loaded file that is already
+ in the current style list keeps its current style. Otherwise,
+ existing named styles are overwritten with specifications from the
+ loaded file.}
+
+ @item{In the latter case, the editor's style list will be changed to
+ the previously-read list.}
+
+}
+}
+
+
+@defmethod[(read-header-from-file [stream (is-a?/c editor-stream-in%)]
+ [name string?])
+ boolean?]{
+
+Called to handle a named header that is found when reading editor data
+ from a stream. The return value is @scheme[#t] if there are no errors,
+ @scheme[#f] otherwise.
+
+Override this method only to embellish the file format with new header
+ information. Always call the inherited method if the derived reader
+ does not recognize the header.
+
+See also @|filediscuss|.
+}
+
+
+@defmethod[(redo)
+ void?]{
+
+Undoes the last undo, if no other changes have been made since. See
+ @method[editor<%> undo] for information about Emacs-style undo. If
+ the editor is currently performing an undo or redo, the method call
+ is ignored.
+
+The system may perform a redo without calling this method in response
+ to other method calls. Use methods such as
+ @method[editor<%> on-change] to monitor editor content changes.
+
+See also @method[editor<%> add-undo].
+
+}
+
+
+@defmethod[(refresh [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))]
+ [draw-caret (one-of/c 'no-caret 'show-inactive-caret 'show-caret)]
+ [background (or/c (is-a?/c color%) false/c)])
+ void?]{
+
+Repaints a region of the editor, generally called by an editor
+ administrator. See @secref["mr:editorthreads"] for information about
+ edit sequences and refresh requests.
+
+The @scheme[x], @scheme[y], @scheme[width], and @scheme[height] arguments specify
+ the area that needs repainting in editor coordinates.
+
+See @|drawcaretdiscuss| for information about @scheme[draw-caret].
+
+The @scheme[background] color corresponds to the background of the
+ @techlink{display}; if it is @scheme[#f], then the display is transparent.
+ An editor should use the given background color as its own
+ background (or not paint the background of @scheme[background] is
+ @scheme[#f]).
+
+}
+
+
+@defmethod[(refresh-delayed?)
+ boolean?]{
+
+Returns @scheme[#t] if updating on this editor is currently
+ delayed. Updating may be delayed because @method[editor<%>
+ begin-edit-sequence] has been called for this editor, or because the
+ editor has no administrator, or because the editor's administrator
+ returns @scheme[#t] from its @method[editor-admin% refresh-delayed?]
+ method. (The administrator might return @scheme[#t] because an
+ enclosing editor's refresh is delayed.)
+
+See also @method[editor<%> in-edit-sequence?].
+
+}
+
+
+@defmethod[(release-snip [snip (is-a?/c snip%)])
+ void?]{
+
+Requests that the specified snip be deleted and released from the
+ editor. If this editor is not the snip's owner or if the snip cannot
+ be released, then @scheme[#f] is returned. Otherwise, @scheme[#t] is
+ returned and the snip is no longer owned.
+
+See also @xmethod[snip-admin% release-snip] .
+
+}
+
+
+@defmethod[(remove-canvas [canvas (is-a?/c editor-canvas%)])
+ void?]{
+
+Removes a canvas from this editor's list of displaying canvases. (See
+ @method[editor<%> get-canvases].)
+
+Normally, this method is called only by @xmethod[editor-canvas%
+ set-editor].
+
+}
+
+
+@defmethod[(resized [snip (is-a?/c snip%)]
+ [redraw-now? any/c])
+ void?]{
+
+Called (indirectly) by snips within the editor: it forces a
+ recalculation of the display information in which the specified snip
+ has changed its size.
+
+If @scheme[redraw-now?] is @scheme[#f], the editor will require
+ another message to repaint itself. (See also @method[editor<%>
+ needs-update].)
+
+}
+
+
+@defmethod[(save-file [filename (or/c path-string? false/c) #f]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'same]
+ [show-errors? any/c #t])
+ boolean?]{
+
+Saves the editor into a file and returns @scheme[#t]. If an error
+ occurs, an exception is raised.
+
+If @scheme[filename] is @scheme[#f], then the internally stored filename
+ will be used; if @scheme[filename] is @scheme[""] or if the internal name
+ is unset or temporary, then the user will be prompted for a name.
+ The possible values for @scheme[format] are described at
+@method[editor<%> load-file].
+
+The filename and format used to save the file can be retrieved with
+ @method[editor<%> get-filename]. In a @scheme[text%] instance, the
+ format can be retrieved with @method[text% get-file-format].
+
+See also @method[editor<%> on-save-file], @method[editor<%>
+ after-save-file], and @method[editor<%> can-save-file?].
+
+Under Mac OS X, the file's type signature is set to @scheme["TEXT"]
+ for a text-format file or @scheme["WXME"] for a standard-format
+ (binary) file.
+
+The @scheme[show-errors?] argument is no longer used.
+
+}
+
+
+@defmethod[(save-port [port output-port]
+ [format (one-of/c 'guess 'standard 'text 'text-force-cr 'same 'copy) 'same]
+ [show-errors? any/c #t])
+ boolean?]{
+
+Saves the editor into a port and returns @scheme[#t]. If an error
+ occurs, an exception is raised.
+
+The possible values for @scheme[format] are described at
+@method[editor<%> load-file].
+
+The @scheme[show-errors?] argument is no longer used.
+
+}
+
+
+@defmethod[(scroll-line-location [pos (and/c exact? integer?)])
+ (and/c real? (not/c negative?))]{
+
+Maps a vertical scroll position to a vertical @techlink{location}
+ within the editor.
+
+For @scheme[text%] objects: @|FCA| @|EVD|
+
+}
+
+
+@defmethod[(scroll-to [snip (is-a?/c snip%)]
+ [localx real?]
+ [localy real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))]
+ [refresh? any/c]
+ [bias (one-of/c 'start 'end 'none) 'none])
+ boolean?]{
+
+Called (indirectly) by snips within the editor: it causes the editor
+ to be scrolled so that a given @techlink{location} range within a
+ given snip is visible. If the editor is scrolled, @scheme[#t] is
+ returned, otherwise @scheme[#f] is returned.
+
+The @scheme[localx], @scheme[localy], @scheme[width], and @scheme[height]
+ arguments specify the area that needs to be visible in @scheme[snip]'s
+ coordinate system.
+
+When the specified region cannot fit in the visible area, @scheme[bias]
+ indicates which end of the region to display. When @scheme[bias] is
+ @scheme['start], then the top-left of the region is
+ displayed. When @scheme[bias] is @scheme['end], then the
+ bottom-right of the region is displayed. Otherwise, @scheme[bias] must
+ be @scheme['none].
+
+}
+
+
+@defmethod[(select-all)
+ void?]{
+
+Selects all data in the editor
+
+}
+
+@defmethod[(set-active-canvas [canvas (is-a?/c editor-canvas%)])
+ void?]{
+
+Sets the active canvas for this editor. (See @method[editor<%>
+ get-active-canvas].)
+
+Normally, this method is called only by @xmethod[editor-canvas%
+ on-focus] in an editor canvas that is displaying an editor.
+
+}
+
+@defmethod[(set-admin [admin (or/c (is-a?/c editor-admin%) false/c)])
+ void?]{
+
+Sets the editor's administrator. This method is only called by an
+ administrator.
+
+@Unmonitored[@elem{The administrator of an editor} @elem{by the
+system} @elem{the administrator changes} @elem{@method[editor<%>
+get-admin]}]
+
+}
+
+
+@defmethod[(set-caret-owner [snip (or/c (is-a?/c snip%) false/c)]
+ [domain (one-of/c 'immediate 'display 'global) 'immediate])
+ void?]{
+
+Attempts to give the keyboard focus to @scheme[snip]. If @scheme[snip] is
+ @scheme[#f], then the caret is taken away from any snip in the editor
+ that currently has the caret and restored to this editor.
+
+If the keyboard focus is moved to @scheme[snip] and the editor has the
+ real keyboard focus, the @method[snip% own-caret] method of the snip
+ will be called.
+
+If @scheme[#f] is provided as the new owner, then the local focus is
+ moved to the editor itself. Otherwise, the local focus is moved to
+ the specified snip.
+
+The domain of focus-setting is one of:
+
+@itemize{
+
+ @item{@scheme['immediate] --- only set the focus owner within the
+ editor}
+
+ @item{@scheme['display] --- make this editor or the new focus
+ owner get the keyboard focus among the editors in this editor's
+ @techlink{display} (if this is an embedded editor)}
+
+ @item{@scheme['global] --- make this editor or the new focus
+ owner get the keyboard focus among all elements in the editor's frame}
+
+}
+
+@MonitorMethod[@elem{The focus state of an editor} @elem{by the
+system} @elem{@method[editor<%> on-focus]} @elem{focus}]
+
+See also @method[editor<%> get-focus-snip].
+
+}
+
+
+@defmethod[(set-cursor [cursor (or/c (is-a?/c cursor%) false/c)]
+ [override? any/c @scheme[#t]])
+ void?]{
+
+Sets the custom cursor for the editor to @scheme[cursor]. If
+ @scheme[override?] is a true value and @scheme[cursor] is not
+ @scheme[#f], then this cursor overrides cursor settings in embedded
+ editors.
+
+If the custom cursor is @scheme[#f], the current cursor is removed,
+ and a cursor is selected automatically by the editor (depending on
+ whether the cursor is pointing at a clickback). See @method[editor<%>
+ adjust-cursor] for more information about the default selection.
+
+An embedding editor's custom cursor can override the cursor of an
+ embedded editor---even if the embedded editor has the caret---if
+ the cursor is specified as an overriding cursor.
+
+}
+
+
+@defmethod[(set-filename [filename (or/c path-string? false/c)]
+ [temporary? any/c #f])
+ void?]{
+
+Sets the filename to @scheme[filename]. If @scheme[filename] is
+ @scheme[#f] or @scheme[temporary?] is a true value, then the user
+ will still be prompted for a name on future calls to
+ @method[editor<%> save-file] and @method[editor<%> load-file].
+
+This method is also called when the filename changes through any
+ method (such as @method[editor<%> load-file]).
+
+}
+
+
+@defmethod[(set-inactive-caret-threshold [threshold (one-of/c 'no-caret 'show-inactive-caret 'show-caret)])
+ void?]{
+
+Sets the threshold for painting an inactive selection. See
+ @method[editor<%> get-inactive-caret-threshold] for more information.
+
+}
+
+
+@defmethod[(set-keymap [keymap (or/c (is-a?/c keymap%) false/c) #f])
+ void?]{
+
+Sets the current keymap for the editor. A @scheme[#f] argument removes
+ all key mapping.
+
+}
+
+
+@defmethod[(set-load-overwrites-styles [overwrite? any/c])
+ void?]{
+
+Determines whether named styles in the current style list are replaced
+ by @method[editor<%> load-file] when the loaded file contains style
+ specifications.
+
+See also @method[editor<%> get-load-overwrites-styles] and
+ @method[editor<%> read-from-file].
+
+}
+
+
+@defmethod[(set-max-height [width (or/c (and/c real? (not/c negative?)) (one/of 'none))])
+ void?]{
+
+Sets the maximum display height for the contents of the editor. A
+ value less or equal to @scheme[0] indicates that there is no maximum.
+
+Setting the height is disallowed when the editor is internally locked
+ for reflowing (see also @|lockdiscuss|).
+
+}
+
+
+@defmethod[(set-max-undo-history [count (or/c nonnegative-exact-integer? (one/of 'forever))])
+ void?]{
+
+Sets the maximum number of undoables that will be remembered by the
+ editor. The default is @scheme[0], which disables undo. The symbol
+ @indexed-scheme['forever] is accepted as a synonym for a very large
+ number.
+
+}
+
+
+@defmethod[(set-max-width [width (or/c (and/c real? (not/c negative?)) (one/of 'none))])
+ void?]{
+
+Sets the maximum display width for the contents of the editor;
+ zero or @scheme['none] indicates that there is no maximum. In a
+ text editor, having no maximum disables automatic line breaking,
+ and the minimum (positive) maximum width depends on the width of the
+ autowrap bitmap.
+
+Setting the width is disallowed when the editor is internally locked
+ for reflowing (see also @|lockdiscuss|).
+
+See also @method[text% set-autowrap-bitmap].
+
+}
+
+@defmethod[(set-min-height [width (or/c (and/c real? (not/c negative?)) (one/of 'none))])
+ void?]{
+
+Sets the minimum display height for the contents of the editor; zero
+ or @scheme['none] indicates that there is no minimum.
+
+Setting the height is disallowed when the editor is internally locked
+ for reflowing (see also @|lockdiscuss|).
+
+}
+
+@defmethod[(set-min-width [width (or/c (and/c real? (not/c negative?)) (one/of 'none))])
+ void?]{
+
+Sets the minimum display width for the contents of the editor; zero or
+ @scheme['none] indicates that there is no minimum.
+
+Setting the width is disallowed when the editor is internally locked
+for reflowing (see also @|lockdiscuss|).
+
+}
+
+@defmethod[(set-modified [modified? any/c])
+ void?]{
+
+Sets the modified state of the editor. Usually, the state is changed
+ automatically after an insertion, deletion, or style change by
+ calling this method. (This method is also called when the
+ modification state changes through @italic{any} method.) This method
+ is usually not called when the state of the flag is not changing.
+
+See also @method[editor<%> is-modified?] and @method[editor<%>
+on-snip-modified].
+
+When @scheme[modified?] is true, then an internal modify-counter is
+ set to @scheme[1].
+
+When @scheme[modified?] is @scheme[#f] and the editor's undo or redo
+ stack contains a system-created undoer that resets the modified state
+ (because the preceding undo or redo action puts the editor back to a
+ state where the modification state was @scheme[#f]), the undoer is
+ disabled.
+
+Regardless of the value of @scheme[modified?], the editor's
+ adminstrator's @method[editor-admin% modified] method is called.
+
+Finally, if @scheme[modified?] is @scheme[#f] and the internal
+ modify-counter is set to @scheme[0], then the @method[snip%
+ set-unmodified] method is called on every snip within the editor.
+
+}
+
+
+@defmethod[(set-paste-text-only [text-only? any/c])
+ void?]{
+
+Sets whether the editor accepts only text from the clipboard, or both
+ text and snips. By default, an editor accepts both text and
+ snips.
+
+See also @method[editor<%> get-paste-text-only].
+
+}
+
+@defmethod[(set-snip-data [thesnip (is-a?/c snip%)]
+ [data (is-a?/c editor-data%)])
+ void?]{
+
+Sets extra data associated with the snip (e.g., @techlink{location}
+ information in a pasteboard). See @|editordatadiscuss| for more
+ information.
+
+}
+
+
+@defmethod[(set-style-list [style-list (is-a?/c style-list%)])
+ void?]{
+
+Sets the editor's style list. Styles currently in use with the old
+ style list will be ``moved'' to the new style list. In this ``move,''
+ if a named style already exists in the new style list, then the new
+ style with the same name will be used in place of the old style.
+
+Setting the style list is disallowed when the editor is internally
+ locked for reflowing (see also @|lockdiscuss|).
+
+}
+
+
+@defmethod[(style-has-changed [style (or/c (is-a?/c style<%>) false/c)])
+ void?]{
+
+Notifies the editor that a style in its style list has changed. This
+ method is automatically registered with the editor's style list using
+ @xmethod[style-list% notify-on-change] and automatically deregistered
+ when the style list is removed from the editor.
+
+See @xmethod[style-list% notify-on-change] for more information.
+
+}
+
+
+@defmethod[(undo)
+ void?]{
+
+Undoes the last editor change, if undos have been enabled by calling
+ @method[editor<%> set-max-undo-history] with a non-zero integer.
+
+If the editor is currently performing an undo or redo, the method call
+ is ignored.
+
+The user may enable Emacs-style undo for editors; see
+ @|mrprefsdiscuss|. Normally, undo operations add to the redo stack
+ (see @method[editor<%> redo]), and any undoable (non-undo) operation
+ clears the redo stack. With Emacs-style undo, the redo stack is added
+ back to the undo stack, along with the original undos, so that a
+ complete history is kept in the undo stack.
+
+The system may perform an undo without calling this method in response
+ to other method calls. Use methods such as
+ @method[editor<%> on-change] to monitor editor content changes.
+
+See also @method[editor<%> add-undo] .
+
+}
+
+
+@defmethod[(write-footers-to-file [stream (is-a?/c editor-stream-out%)])
+ boolean?]{
+
+See @method[editor<%> write-headers-to-file].
+
+}
+
+
+@defmethod[(write-headers-to-file [stream (is-a?/c editor-stream-out%)])
+ boolean?]{
+
+@methspec{
+
+Called when the editor is being saved to a file. The return value is
+ @scheme[#t] if there are no errors, @scheme[#f] otherwise. Override
+ this method to add custom header data to a file, but always call the
+ inherited method so that it can write its own extra headers.
+
+To write a header item, call @method[editor<%>
+ begin-write-header-footer-to-file], passing a box for an
+ integer. Then write the header data and end by calling
+ @method[editor<%> end-write-header-footer-to-file], passing back the
+ integer that was put into the box. Follow this procedure correctly
+ or the file will be corrupted.
+
+}
+@methimpl{
+
+Does nothing.
+
+}}
+
+@defmethod[(write-to-file [stream (is-a?/c editor-stream-out%)])
+ boolean?]{
+
+Writes the current editor contents to the given stream. The return
+ value is @scheme[#t] if there are no errors, @scheme[#f] otherwise. See
+ also @|filediscuss|.
+
+If the editor's style list has already been written to the stream, it
+ is not re-written. Instead, the editor content indicates that the
+ editor shares a previously-written style list. This sharing will be
+ recreated when the stream is later read.
+}}
diff --git a/collects/scribblings/gui/editor-overview.scrbl b/collects/scribblings/gui/editor-overview.scrbl
new file mode 100644
index 0000000000..7771b6d4d7
--- /dev/null
+++ b/collects/scribblings/gui/editor-overview.scrbl
@@ -0,0 +1,752 @@
+#reader(lib "docreader.ss" "scribble")
+@require[(lib "bnf.ss" "scribble")]
+@require["common.ss"]
+
+@title[#:tag "mr:editor-overview"]{Editor Guide}
+
+The editor toolbox provides a foundation for two common kinds of
+ applications:
+
+@itemize{
+
+ @item{@italic{Programs that need a sophisticated text editor} ---
+ The simple text field control is inadequate for text-intensive
+ applications. Many programs need editors that can handle multiple
+ fonts and non-text items.}
+
+ @item{@italic{Programs that need a canvas with dragable objects} ---
+ The drawing toolbox provides a generic drawing surface for plotting
+ lines and boxes, but many applications need an interactive canvas,
+ where the user can drag and resize individual objects.}
+
+}
+
+Both kinds of applications need an extensible editor that can handle
+ text, images, programmer-defined items, and even embedded
+ editors. The difference between them is the layout of items. MrEd
+ therefore provides two kinds of editors via two classes:
+
+@itemize{
+
+ @item{@scheme[text%] --- in a @deftech{text editor}, items are
+ automatically positioned in a paragraph flow.}
+
+ @item{@scheme[pasteboard%] --- in a @deftech{pasteboard editor},
+ items are explicitly positioned and dragable.}
+
+}
+
+MrEd's editor architecture addresses the full range of real-world
+ issues for an editor---including cut-and-paste, extensible file
+ formats, and layered text styles---while supporting a high level of
+ extensibility. Unfortunately, the system is fairly complex as a
+ result, and using the editor classes effectively requires a solid
+ understanding of the structure and terminology of the editor
+ toolbox. Nevertheless, enough applications fit one (or both) of the
+ descriptions above to justify the depth and complexity of the toolbox
+ and the learning investment required to use it.
+
+A brief example illustrates how MrEd editors work. To start, an editor
+ needs an @scheme[editor-canvas%] to display its contents. Then, we
+ can create a text editor and install it into the canvas:
+
+@schemeblock[
+(define f (new frame% [label "Simple Edit"]
+ [width 200]
+ [height 200]))
+(define c (new editor-canvas% [parent f]))
+(define t (new text%))
+(send c #,(:: editor-canvas% set-editor) t)
+(send f #,(:: top-level-window<%> show) #t)
+]
+
+At this point, the editor is fully functional: the user can type text
+ into the editor, but no cut-and-paste operations are available. We
+ can support all of the standard operations on an editor via the
+ menu bar:
+
+@schemeblock[
+(define mb (new menu-bar% [parent f]))
+(define m-edit (new menu% [label "Edit"] [parent mb]))
+(define m-font (new menu% [label "Font"] [parent mb]))
+(append-editor-operation-menu-items m-edit #f)
+(append-editor-font-menu-items m-font)
+]
+
+Now, the standard cut and paste operations work, and the user can even
+ set font styles. The user can also insert an embedded editor by
+ selecting @onscreen{Insert Text} from the @onscreen{Edit} menu; after
+ selecting the menu item, a box appears in the editor with the caret
+ inside. Typing with the caret in the box stretches the box as text is
+ added, and font operations apply wherever the caret is active. Text
+ on the outside of the box is rearranged as the box changes
+ sizes. Note that the box itself can be copied and pasted.
+
+The content of an editor is made up of @deftech{snips}. An embedded
+ editor is a single snip from the embedding editor's point-of-view. To
+ encode immediate text, a snip can be a single character, but more
+ often a snip is a sequence of adjacent characters on the same
+ line. The @method[text% find-snip] method extracts a snip
+ from a text editor:
+
+@schemeblock[
+(send t #,(:: text% find-snip) 0 'after)
+]
+
+The above expression returns the first snip in the editor, which may
+ be a string snip (for immediate text) or an editor snip (for an
+ embedded editor).
+
+An editor is not permanently attached to any display. We can take the
+ text editor out of our canvas and put a pasteboard editor in the
+ canvas, instead:
+
+@schemeblock[
+(define pb (new pasteboard%))
+(send c #,(:: editor-canvas% set-editor) pb)
+]
+
+With the pasteboard editor installed, the user can no longer type
+ characters directly into the editor (because a pasteboard does not
+ support directly entered text). However, the user can cut text from
+ elsewhere and paste it into pasteboard, or select one of the
+ @onscreen{Insert} menu items in the @onscreen{Edit} menu. Snips are
+ clearly identifiable in a pasteboard editor (unlike a text editor)
+ because each snip is separately dragable.
+
+We can insert the old text editor (which we recently removed from the
+ canvas) as an embedded editor in the pasteboard by explicitly
+ creating an editor snip:
+
+@schemeblock[
+(define s (make-object editor-snip% t)) (code:comment #, @t{@scheme[t] is the old text editor})
+(send pb #,(:: editor:<%> insert) s)
+]
+
+An individual snip cannot be inserted into different editors at the
+ same time, or inserted multiple times in the same editor:
+
+@schemeblock[
+(send pb #,(:: editor<%> insert) s) (code:comment #, @t{no effect})
+]
+
+However, we can make a deep copy of the snip and insert the copy into
+ the pasteboard:
+
+@schemeblock[
+(send pb #,(:: editor<%> insert) (send s #,(:: snip% copy)))
+]
+
+Applications that use the editor classes typically derive new versions
+ of the @scheme[text%] and @scheme[pasteboard%] classes. For
+ example, to implement an append-only editor (which allows insertions
+ only at the end and never allows deletions), derive a new class from
+ @scheme[text%] and override the
+ @method[text% can-insert?] and
+ @method[text% can-delete?] methods:
+
+@schemeblock[
+(define append-only-text%
+ (class text%
+ (inherit #,(:: text% last-position))
+ (define/override (#,(:: text% can-insert?) s l) (= s #,(:: text% last-position)))
+ (define/override (#,(:: text% can-delete?) s l) #f)
+ (super-new)))
+]
+
+@section[#:tag "mr:tb:miaoverview"]{Editor Structure and Terminology}
+
+MrEd supports extensible and nestable editors by decomposing an editor
+ assembly into three functional parts:
+
+@itemize{
+
+ @item{The @deftech{editor} itself stores the state of the text or
+ pasteboard and handles most events and editing operations. The
+ @scheme[editor<%>] interface defines the core editor functionality,
+ but editors are created as instances of @scheme[text%] or
+ @scheme[pasteboard%].}
+
+ @item{A @deftech{snip} is a segment of information within the
+ editor. Each snip can contain a sequence of characters, a picture,
+ or an interactive object (such as an embedded editor). In a text
+ editor, snips are constrained to fit on a single line and generally
+ contain data of a single type. The @scheme[snip%] class implements a
+ basic snip. Other snip classes include @scheme[string-snip%] for
+ managing text, @scheme[image-snip%] for managing pictures, and
+ @scheme[editor-snip%] for managing embedded editors.}
+
+ @item{A @deftech{display} presents the editor on the screen. The
+ display lets the user scroll around an editor or change editors. Most
+ displays are instances of the @scheme[editor-canvas%] class, but the
+ @scheme[editor-snip%] class also acts as a display for embedded
+ editors.}
+
+}
+
+These three parts are illustrated by a simple word processor. The
+ editor corresponds to the text document. The editor object receives
+ keyboard and mouse commands for editing the text. The text itself is
+ distributed among snips. Each character could be a separate snip, or
+ multiple characters on a single line could be grouped together into a
+ snip. The display roughly corresponds to the window in which the
+ text is displayed. While the editor manages the arrangement of the
+ text as it is displayed into a window, the display determines which
+ window to draw into and which part of the editor to display.
+
+Each selectable entity in an editor is an @deftech{item}. In a
+ pasteboard, all selection and dragging operations work on snips, so
+ there is a one-to-one correspondence between snips and items. In an
+ editor, one snip contains one or more consecutive items, and every
+ item belongs to some snip. For example, in a simple text editor, each
+ character is an item, but multiple adjacent characters may be grouped
+ into a single snip. The number of items in a snip is the snip's
+ @deftech{count}.
+
+Each place where the insertion point can appear in a text editor is a
+ @deftech{position}. A text editor with $n$ items contains $n+1$
+ positions: one position before each item, and one position after the
+ last item.
+
+The order of snips within a pasteboard determines each snip's drawing
+ plane. When two snips overlap within the pasteboard, the snip that is
+ earlier in the order is in front of the other snip (i.e., the former
+ is drawn after the latter, such that the former snip may cover part
+ of the latter snip).
+
+When an editor is drawn into a display, each snip and position has a
+ @deftech{location}. The location of a position or snip is specified
+ in coordinates relative to the top-left corner of the
+ editor. Locations in an editor are only meaningful when the editor is
+ displayed.
+
+
+@subsection[#:tag "mr:editoradministrators"]{Administrators}
+
+Two extra layers of administration manage the @techlink{display}-editor and
+ editor-snip connections. An editor never communicates directly with
+ a @techlink{display}; instead, it always communicates with an @deftech{editor
+ administrator}, an instance of the @scheme[editor-admin%] class,
+ which relays information to the @techlink{display}. Similarly, a snip
+ communicates with a @deftech{snip administrator}, an instance of the
+ @scheme[snip-admin%] class.
+
+The administrative layers make the editor hierarchy flexible without
+ forcing every part of an editor assembly to contain the functionality
+ of several parts. For example, a text editor can be a single
+ @techlink{item} within another editor; without administrators, the
+ @scheme[text%] class would also have to contain all the functionality
+ of a @techlink{display} (for the containing editor) and a snip (for
+ the embedded editor). Using administrators, an editor class can serve
+ as both a containing and an embedded editor without directly
+ implementing the @techlink{display} and snip functionality.
+
+A snip belongs to at most one editor via a single administrator. An
+ editor also has only one administrator at a time. However, the
+ administrator that connects the an editor to the standard
+ @techlink{display} (i.e., an editor canvas) can work with other such
+ administrators. In particular, the administrator of an
+ @scheme[editor-canvas%] (each one has its own administrator) can work
+ with other @scheme[editor-canvas%] administrators, allowing an editor
+ to be displayed in multiple @scheme[editor-canvas%] windows at the
+ same time.
+
+When an editor is displayed by multiple canvases, one of the canvases'
+ administrators is used as the editor's primary administrator. To
+ handle user and update events for other canvases, the editor's
+ administrator is temporarily changed and then restored through the
+ editor's @method[editor<%> set-admin] method. The return value of the
+ editor's @method[editor<%> get-admin] method thus depends on the
+ context of the call.
+
+@subsection[#:tag "mr:editorstyles"]{Styles}
+
+A @deftech{style}, an instance of the @scheme[style<%>] interface,
+ parameterizes high-level display information that is common to all
+ snip classes. This includes the font, color, and alignment for
+ drawing the item. A single style is attached to each snip.
+
+Styles are hierarchical: each style is defined in terms of another
+ style. @index*['("Basic style") (list @elem{@scheme["Basic"]
+ style})]{There} is a single @deftech{root style}, named
+ @scheme["Basic"], from which all other styles in an editor are
+ derived. The difference between a base style and each of its derived
+ style is encoded in a @deftech{style delta} (or simply
+ @deftech{delta}). A delta encodes changes such as
+
+@itemize{
+
+ @item{change the font family to @italic{X};}
+
+ @item{enlarge the font by adding @italic{Y} to the point size;}
+
+ @item{toggle the boldness of the font; or}
+
+ @item{change everything to match the style description @italic{Z}.}
+
+}
+
+Style objects are never created separately; rather, they are always
+ created through a @deftech{style list}, an instance of the
+ @scheme[style-list%] class. A style list manages the styles,
+ servicing external requests to find a particular style, and it
+ manages the hierarchical relationship between styles. A global style
+ list is available, @indexed-scheme[the-style-list], but new style
+ lists can be created for managing separate style hierarchies. For
+ example, each editor will typically have its own style list.
+
+Each new style is defined in one of two ways:
+
+@itemize{
+
+ @item{A @deftech{derived style} is defined in terms of a base style
+ and a delta. Every style (except for the root style) has a base
+ style, even if it does not depend on the base style in any way (i.e.,
+ the delta describes a fixed style rather than extensions to an
+ existing style). (This is the usual kind of style inheritance, as
+ found in word processors such as Microsoft Word.)}
+
+ @item{A @deftech{join style} is defined in terms of two other styles:
+ a base style and a @deftech{shift style}. The meaning of a join style
+ is determined by reinterpreting the shift style; in the
+ reinterpretation, the base style is used as the {\em root\/} style
+ for the shift style. (This is analogous to multi-level
+ styles, like the paragraph and character styles in FrameMaker. In
+ this analogy, the paragraph style is the base style, and the
+ character style is the shift style. However, FrameMaker allows only
+ those two levels; with join styles support any number of levels.)}
+
+}
+
+@index*['("Standard style") (list @elem{@scheme["Standard"]
+ style})]{Usually}, when text is inserted into a text editor, it
+ inherits the style of the preceding snip. If text is inserted into an
+ empty editor, the text is usually assigned a style called
+ @scheme["Standard"]. By default, the @scheme["Standard"] style is
+ unmodified from the root style. The default style name can be changed
+ by overriding @method[editor<%> default-style-name].
+
+The exception to the above is when @xmethod[text% change-style] is
+ called with the current selection @techlink{position} (when the
+ selection is a @techlink{position} and not a range). In that case,
+ the style is remembered, and if the next editor-modifying action is a
+ text insertion, the inserted text gets the remembered style.
+
+See @xmethod[text% get-styles-sticky] for more information about the
+ style of inserted text.
+
+
+@section[#:tag "mr:editorfileformat"]{File Format}
+
+To allow editor content to be saved to a file, the editor classes
+ implement a special file format. (The format is used when cutting and
+ pasting between applications or eventspaces, too). The file format is
+ not documented, except that it begins
+ @litchar{WXME01}@nonterm{digit}@nonterm{digit} ## }. Otherwise, the
+ @method[editor<%> load-file] and @method[editor<%> save-file] methods
+ define the format internally. The file format is the same for text
+ and pasteboard editors. When a pasteboard saves its content to a
+ file, it saves the snips from front to back, and also includes extra
+ location information.
+
+Editor data is read and written using @scheme[editor-stream-in%] and
+ @scheme[editor-stream-out%] objects. Editor information can only be
+ read from or written to one stream at a time. To write one or more
+ editors to a stream, first call the function
+ @scheme[write-editor-global-header] to write initialization data into
+ an output stream. When all editors are written to the stream, call
+ @scheme[write-editor-global-footer]. Similarly, reading editors from
+ a stream is initialized with @scheme[read-editor-global-header] and
+ finalized with @scheme[read-editor-global-footer]. Optionally, to
+ support streams that span versions of MrEd, use
+ @scheme[write-editor-version] and @scheme[read-editor-version] before
+ the header operations.
+
+The editor file data format can be embedded within another file, and
+ it can be extended with new kinds of data. The editor file format can
+ be extended in two ways: with snip- or content-specific data, and
+ with editor-specific global data. These are described in the
+ remainder of this section.
+
+@subsection{Encoding Snips}
+
+@index['("snips" "saving")]{@index['("snips" "cut and paste")]{The}}
+ generalized notion of a snip allows new snip types to be defined and
+ immediately used in any editor class. Also, when two applications
+ support the same kinds of snips, snip data can easily be cut and
+ pasted between them, and the same data files will be readable by each
+ program. This interoperability is due to a consistent encoding
+ mechanism that is built into the snip system.
+
+Graceful and extensible encoding of snips requires that
+ two issues are addressed:
+
+@itemize{
+
+ @item{The encoding function for a snip can be associated with the snip
+ itself. To convert a snip from an encoded representation (e.g., as
+ bytes in a file) to a memory object, a decoding function must be
+ provided for each type of snip. Furthermore, a list of such decoders
+ must be available to the high-level decoding process. This decoding
+ mapping is defined by associating a @deftech{snip class} object to
+ every snip. A snip class is an instance of the @scheme[snip-class%]
+ class.}
+
+ @item{Some editors may require additional information to be stored
+ about a snip; this information is orthogonal to the type-specific
+ information stored by the snip itself. For example, a pasteboard
+ needs to remember a snip's @techlink{location}, while a text editor does not
+ need this information. If data is being cut and pasted from one
+ pasteboard to another, then information about relative @techlink{location}s
+ needs to be maintained, but this information should not inhibit
+ pasting into an editor. Extra data is associated with a snip through
+ @deftech{editor data} objects, instances of the
+ @scheme[editor-data%] class; decoding requires that each editor data
+ object has an @deftech{editor data class}, an instance of the
+ @scheme[editor-data-class%] class.}
+
+}
+
+Snip classes, snip data, and snip data classes solve problems related
+ to encoding and decoding snips. In an application that has no need
+ for saving files or cut-and-paste, these issues can be safely
+ ignored.
+
+@subsubsection[#:tag "mr:editorsnipclasses"]{Snip Classes}
+
+Each snip can be associated to a @deftech{snip class}. This ``class''
+ is not a class description in the programmer's language; it is an
+ object which provides a way to create new snips of the appropriate
+ type from an encoded snip specification.
+
+Snip class objects can be added to the eventspace-specific
+ @deftech{snip class list}, which is returned by
+ @scheme[get-the-snip-class-list]. When a snip is encoded, the snip's
+ class name is associated with the encoding; when the snip needs to be
+ decoded, then the snip class list is searched by name to find the
+ snip's class. The snip class will then provide a decoding function
+ that can create a new snip from the encoding.
+
+If a snip class's name is of the form @scheme["(lib ...)"], then the
+ snip class implementation can be loaded on demand. The name is parsed
+ using @scheme[read]; if the result has the form @scheme[(libKW string
+ ...)], then it is supplied to @scheme[dynamic-require] along with
+ @scheme['snip-class]. If the result is a @scheme[snip-class%] object,
+ it is inserted into the current eventspace's snip class list, and
+ loading or saving continues using the new class.
+
+@subsubsection[#:tag "mr:editordata"]{Editor Data}
+
+While a snip belongs to an editor, the editor may store extra
+ information about a snip in some specialized way. When the snip is to
+ be encoded, this extra information needs to be put into an
+ @deftech{editor data} object so that the extra information can be
+ encoded as well. In a text editor, extra information can be
+ associated with ranges of @techlink{item}s, as well as snips.
+
+Just as a snip must be associated with a snip class to be decoded (see
+ @|snipclassdiscuss|), an editor data object needs an @deftech{editor
+ data class} for decoding. Every editor data class object can be added
+ to the eventspace-specific @deftech{editor data class list}, returned
+ by @scheme[get-the-editor-data-class-list]. Alternatively, like snip
+ classes, editor data class names can use the form @scheme["(lib ...)"]
+ to enable on-demand loading. The corresponding module should export an
+ @scheme[editor-data-class%] object named
+ @scheme['editor-data-class].
+
+To store and load information about a snip or region in an editor:
+
+@itemize{
+
+ @item{derive new classes from @scheme[editor-data%] and
+ @scheme[editor-data-class%].}
+
+@item{derive a new class from the @scheme[text%] or
+ @scheme[pasteboard%] class, and override the @method[editor<%>
+ get-snip-data] and @method[editor<%> set-snip-data] methods and/or the
+ @method[text% get-region-data] and @method[text% set-region-data]
+ methods.
+
+ Note: the @method[text% get-region-data] and @method[text%
+ set-region-data] methods are called for cut-and-paste encoding, but
+ not for file-saving encoding; see @|globaleditordatadiscuss| for
+ information on extending the file format.}
+
+}
+
+
+@subsection[#:tag "mr:globaleditordata"]{Global Data: Headers and Footers}
+
+The editor file format provides for adding extra global data in
+ special header and footer sections. To save and load special header
+ and/or footer records:
+
+@itemize{
+
+ @item{Pick a name for each header/footer record. This name should not
+ conflict with any other header/footer record name in use, and no one
+ else should use these names. All names beginning with ``wx'' are
+ reserved for internal use. By tagging extra header and footer records
+ with a unique name, the file can be safely loaded under a system that
+ does not support the records.}
+
+ @item{Derive a new class from the @scheme[text%] or
+ @scheme[pasteboard%] class, and override the @method[editor<%>
+ write-headers-to-file], @method[editor<%> write-footers-to-file],
+ @method[editor<%> read-header-from-file] and/or @method[editor<%>
+ read-footer-from-file] methods.}
+
+}
+
+When an editor is saved, the methods @method[editor<%>
+ write-headers-to-file] and @method[editor<%> write-footers-to-file]
+ are invoked; at this time, the derived @scheme[text%] or
+ @scheme[pasteboard%] object has a chance to save records. To write a
+ header/footer record, first invoke the @method[editor<%>
+ begin-write-header-footer-to-file] method, at which point the record
+ name is provided. Once the record is written, call @method[editor<%>
+ end-write-header-footer-to-file].
+
+When an editor is loaded and a header/footer record is encountered,
+ the @method[editor<%> read-header-from-file] or @method[editor<%>
+ read-footer-from-file] method is invoked, with the record name as the
+ argument. If the name matches a known record type, then the data can
+ be loaded.
+
+See also @method[editor<%> write-headers-to-file] and
+ @method[editor<%> write-headers-to-file].
+
+
+@section[#:tag "mr:editoreol"]{End of Line Ambiguity}
+
+Because an editor can force a line break even when there is no
+ carriage return item, a @techlink{position} alone does not always
+ specify a @techlink{location} for the caret. Consider the last
+ @techlink{position} of a line that is soft-broken (i.e., no carriage
+ return is present): there is no @techlink{item} between the last
+ @techlink{item} of the line and the first @techlink{item} of the next
+ line, so two @techlink{location}s (one end-of-line and one
+ start-of-line) map to the same @techlink{position}.
+
+For this reason, @techlink{position}-setting and
+ @techlink{position}-getting methods often have an extra argument. In
+ the case of a @techlink{position}-setting method, the argument
+ specifies whether the caret should be drawn at the left or right side
+ of the page (in the event that the @techlink{location} is doubly
+ defined); @scheme[#t] means that the caret should be drawn on the
+ right side. Similarly, methods which calculate a @techlink{position}
+ from a @techlink{location} will take an extra boxed boolean; the box
+ is filled with @scheme[#t] if the position is ambiguous and it came
+ from a right-side location, or @scheme[#f] otherwise.
+
+@section[#:tag "mr:editorflattened"]{Flattened Text}
+
+In plain text editors, there is a simple correlation between
+ @techlink{position}s and characters. In an @scheme[editor<%>] object,
+ this is not true much of the time, but it is still sometimes useful
+ to just ``get the text'' of an editor.
+
+Text can be extracted from an editor in either of two forms:
+
+@itemize{
+
+ @item{@deftech{Simple text}, where there is one character per
+ @techlink{item}. @techlink{Item}s that are characters are mapped to
+ themselves, and all other @techlink{item}s are mapped to a
+ period. Line breaks are represented by carriage-return characters
+ (ASCII 13).}
+
+ @item{@deftech{Flattened text}, where each @techlink{item} can map to
+ an arbitrary string. @techlink{Item}s that are characters are still
+ mapped to themselves, but more complicated @techlink{item}s can be
+ represented with a useful string determined by the @techlink{item}'s
+ snip. Newlines are mapped to platform-specific character sequences
+ (linefeed under X, carriage return under Mac OS X, and
+ linefeed-carriage return under Windows). This form is called
+ ``flattened'' because the editor's @techlink{item}s have been reduced
+ to a linear sequence of characters.}
+
+}
+
+@section[#:tag "mr:drawcaretinfo"]{Caret Ownership}
+
+Within a frame, only one object can contain the keyboard focus. This
+ property must be maintained when a frame contains multiple editors in
+ multiple @techlink{display}s, and when a single editor contains other
+ editors as @techlink{item}s.
+
+When an editor has the keyboard focus, it will usually display the
+ current selection or a line indicating the insertion point; the line
+ is called the @deftech{caret}.
+
+When an editor contains other editors, it keeps track of caret
+ ownership among the contained sub-editors. When the caret is taken
+ away from the main editor, it will revoke caret ownership from the
+ appropriate sub-editor.
+
+When an editor or snip is drawn, an argument to the drawing method
+ specifies whether the caret should be drawn with the data. This
+ argument can be any of (in increasing order):
+
+@itemize{
+
+ @item{@indexed-scheme['no-caret] --- The caret should not be drawn at
+ all.}
+
+ @item{@indexed-scheme['show-inactive-caret] --- The caret should be drawn
+ as inactive; items may be identified as the local current selection,
+ but the keyboard focus is elsewhere.}
+
+ @item{@indexed-scheme['show-caret] --- The caret should be drawn to show
+ keyboard focus ownership.}
+
+}
+
+The @scheme['show-inactive-caret] display mode is useful for showing
+ selection ranges in text editors that do not have the focus. This
+ @scheme['show-inactive-caret] mode is distinct from @scheme['no-caret]
+ mode; when editors are embedded, only the locally-active editor shows
+ its selection.
+
+
+@section[#:tag "mr:editorcutandpastetime"]{Cut and Paste Time Stamps}
+
+Methods of @scheme[editor<%>] that use the clipboard --- including
+ @method[editor<%> copy], @method[editor<%> cut], @method[editor<%>
+ paste], and @method[editor<%> do-edit-operation] --- consume a time
+ stamp argument. This time stamp is generally extracted from the
+ @scheme[mouse-event%] or @scheme[key-event%] object that triggered
+ the clipboard action. X uses the time stamp to synchronize clipboard
+ operations among the clipboard clients.
+
+All instances of @scheme[event%] include a time stamp, which can be
+ obtained using @method[event% get-time-stamp].
+
+If the time stamp is 0, it defaults to the current time. Using 0 as the
+ time stamp almost always works fine, but it is considered bad manners
+ under X.
+
+
+@section[#:tag "mr:editorclickback"]{Clickbacks}
+
+@deftech{Clickbacks} in a @scheme[text%] editor facilitate the
+ creation of simple interactive objects, such as hypertext. A
+ clickback is defined by associating a callback function with a range
+ of @techlink{item}s in the editor. When a user clicks on the
+ @techlink{item}s in that range, the callback function is invoked. For
+ example, a hypertext clickback would associate a range to a callback
+ function that changes the selection range in the editor.
+
+By default, the callback function is invoked when the user releases
+ the mouse button. The @method[text% set-clickback] method accepts
+ an optional argument that causes the callback function to be invoked
+ on the button press, instead. This behavior is useful, for example,
+ for a clickback that creates a popup menu.
+
+Note that there is no attempt to save clickback information when a
+ file is saved, since a clickback will have an arbitrary procedure
+ associated with it.
+
+@section[#:tag "mr:lockinfo"]{Internal Editor Locks}
+
+Instances of @scheme[editor<%>] have three levels of internal
+ locking:
+
+@itemize{
+
+ @item{write locking --- When an editor is internally locked for
+ writing, the abstract content of the editor cannot be changed (e.g.,
+ insertion attempts fail silently). However, snips in a text editor
+ can still be split and merged, and the text editor can be changed in
+ ways that affect the flow of lines. The
+ @method[editor<%> locked-for-write?] method reports whether an
+ editor is currently locked for writing.}
+
+ @item{flow locking --- When a text editor is internally locked for
+ reflowing, it is locked for writing, the snip content of the editor
+ cannot change, the @techlink{location} of a snip cannot be computed if it
+ is not already known (see
+ @xmethod[editor% locations-computed?]), and the editor cannot
+ be drawn to a @techlink{display}. A request for uncomputed location
+ information during a flow lock produces undefined results. The
+ @method[editor<%> locked-for-flow?] method reports whether an
+ editor is currently locked for flowing.}
+
+ @item{read locking --- When an editor is internally locked for
+ reading, no operations can be performed on the editor (e.g., a
+ request for the current selection position returns an undefined
+ value). This extreme state is used only during callbacks to its snips
+ for setting the snip's administrator, splitting the snip, or merging
+ snips. The @method[editor<%> locked-for-read?] method reports
+ whether an editor is currently locked for reading.}
+
+}
+
+The internal lock for an editor is {\em not\/} affected by calls to
+ @method[editor<%> lock].
+
+Methods that report @techlink{location}-independent information about an
+ editor never trigger a lock. A method that reports @techlink{location}
+ information may trigger a flow lock or write lock if the relevant
+ information has not been computed since the last modification to the
+ editor (see @xmethod[editor% locations-computed?]). A method
+ that modifies the editor in any way, even setting the selection
+ position, can trigger a read lock, flow lock, or write lock.
+
+@section[#:tag "mr:editorthreads"]{Editors and Threads}
+
+An editor is not tied to any particular thread or eventspace, except
+ to the degree that it is displayed in a canvas (which has an
+ eventspace). Concurrent access of an editor is always safe, in the
+ sense that the editor will not become corrupted. However, because
+ editor access can trigger locks, and because lock-rejected operations
+ tend to fail silently, concurrent access can produce unexpected
+ results.
+
+Nevertheless, the editor supports certain concurrent patterns
+ reliably. One relevant pattern is updating an editor in one thread
+ while the editor is displayed in a canvas that is managed by a
+ different (handler) thread. To ensure that canvas refreshes are not
+ performed while the editor is locked for flowing, and to ensure that
+ refreshes do not prevent editor modifications, the following are
+ guaranteed:
+
+@itemize{
+
+ @item{When an editor's @method[editor<%> refresh] method is
+ called during an edit sequence (which is started by
+ @method[editor<%> begin-edit-sequence] and ended with
+ @method[editor<%> end-edit-sequence]), the requested refresh
+ region is recorded, but the refresh is not performed. Instead, the
+ refresh is delayed until the end of the edit sequence.}
+
+ @item{Attempting to start an edit sequence while a refresh is in
+ progress blocks until the refresh is complete.}
+
+ @item{The @method[editor<%> on-display-size-when-ready] method
+ calls @method[editor<%> on-display-size] only when the editor
+ is not being refreshed and only when an edit sequence is not in
+ progress. In the first case, the
+ @method[editor<%> on-display-size] call is delegated to the
+ refreshing thread to be called after the refresh completes. In the
+ second case, the @method[editor<%> on-display-size] call is
+ delegated to the edit-sequence thread, to be called when the edit
+ sequence is complete.}
+
+}
+
+Thus, disabling an @scheme[editor-canvas%] object (using
+ @method[window<%> enable]) is sufficient to ensure that a
+ background thread can modify an editor displayed by the canvas, as
+ long as all modifications are in edit sequences. The background
+ modifications will impair canvas refreshes minimally and temporarily,
+ and refreshes will not impair modifications in the background thread.
+
+A second supported pattern is reading an editor in a background thread
+ while the editor may be manipulated in other threads. Since no
+ @techlink{location}-independent reads introduce locks, the such reads in
+ the background thread will not impair other threads. However, other
+ threads may interfere with the background thread, causing it to
+ receive erroneous or out-of-date content information. This one-sided
+ guarantee is useful if the background thread's work can be discarded
+ when the editor is modified.
diff --git a/collects/scribblings/gui/font-class.scrbl b/collects/scribblings/gui/font-class.scrbl
new file mode 100644
index 0000000000..b2d0a57888
--- /dev/null
+++ b/collects/scribblings/gui/font-class.scrbl
@@ -0,0 +1,226 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[font% object% ()]{
+
+A @defterm{font} is an object which determines the appearance of text,
+ primarily when drawing text to a device context. A font is determined
+ by seven properties:
+
+@itemize{
+
+ @item{size --- The size of the text, either in points (the default)
+ or logical drawing units, depending on the
+ ``size-in-pixels?''\ property (see below).}
+
+ @item{family --- A platform- and device-independent font
+ designation. The families are:
+
+ @itemize{
+ @item{@indexed-scheme['default]}
+ @item{@indexed-scheme['decorative]}
+ @item{@indexed-scheme['roman]}
+ @item{@indexed-scheme['script]}
+ @item{@indexed-scheme['swiss]}
+ @item{@indexed-scheme['modern] (fixed width)}
+ @item{@indexed-scheme['symbol] (Greek letters and more)}
+ @item{@indexed-scheme['system] (used to draw control labels)}
+ }
+
+ The @scheme['modern] designation is special under Mac OS X and X with
+ fontconfig/Xft; characters in the ASCII range 0-255 are converted to
+ Unicode characters that match Adobe symbols. For example, @litchar{a} is
+ converted to @litchar["\u03B1"].}
+
+ @item{face --- A string face name, such as @scheme["Courier"] (under
+ Windows and Mac OS X), @scheme["-*-courier"] (under
+ X), or @scheme[" Luxi Sans"] (under X with
+ fontconfig/Xft; note the leading space). The format
+ and meaning of a face name is platform- and
+ device-specific. If a font's face name is @scheme[#f],
+ then the font's appearance depends only on the
+ family. If a face is provided but no mapping is
+ available for the face name (for a specific platform
+ or device), then the face name is ignored and the
+ family is used. See @scheme[font-name-directory<%>]
+ for information about how face names are mapped for
+ drawing text.}
+
+@item{style --- The slant style of the font, one of:
+ @itemize{
+ @item{@indexed-scheme['normal]}
+ @item{@indexed-scheme['slant] (Windows, Mac OS X: same as @scheme['italic]; X: tries @scheme['italic] if @scheme['slant] font does not exist)}
+ @item{@indexed-scheme['italic] (X: tries @scheme['slant] if @scheme['italic] font does not exist)}
+ }}
+
+@item{weight --- The weight of the font, one of:
+ @itemize{
+ @item{@indexed-scheme['normal]}
+ @item{@indexed-scheme['light]}
+ @item{@indexed-scheme['bold]}
+ }}
+
+@item{underline? --- @scheme[#t] for underlined, @scheme[#f] for plain.}
+
+@item{smoothing --- Amount of anti-alias smoothing, one of:
+ @itemize{
+ @item{@indexed-scheme['default] (platform-specific, sometimes user-configurable)}
+ @item{@indexed-scheme['partly-smoothed] (Windows: TrueType when available;
+ Mac OS X: 4-bit, pixel-aligned smoothing;
+ X: fontconfig/Xft when available)}
+ @item{@indexed-scheme['smoothed] (Windows: ClearType when available, XP and up;
+ Mac OS X: Quartz smoothing;
+ X: fontconfig/Xft when available)}
+ @item{@indexed-scheme['unsmoothed]}
+ }
+ Special case: @scheme['default] corresponds to
+ @scheme['partly-smoothed] when used with the @scheme['modern] family
+ and a font size between 9 and 13 (inclusive).}
+
+@item{size-in-pixels? --- @scheme[#t] if the size of the font
+ is in logical drawing units (i.e., pixels for an unscaled screen or
+ bitmap drawing context), @scheme[#f] if the size of the font is in
+ points (which can depend on screen resolution).}
+
+}
+
+To avoid creating multiple fonts with the same characteristics, use
+ the global @scheme[font-list%] object @indexed-scheme[the-font-list].
+
+See also
+@scheme[font-name-directory<%>].
+
+
+
+@defconstructor*/make[(()
+ ([size (integer-in 1 255)]
+ [family (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)]
+ [style (one-of/c 'normal 'italic 'slant) 'normal]
+ [weight (one-of/c 'normal 'bold 'light) 'normal]
+ [underline? any/c #f]
+ [smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default]
+ [size-in-pixels? any/c #f])
+ ([size (integer-in 1 255)]
+ [face string?]
+ [family (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)]
+ [style (one-of/c 'normal 'italic 'slant) 'normal]
+ [weight (one-of/c 'normal 'bold 'light) 'normal]
+ [underline? any/c #f]
+ [smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default]
+ [size-in-pixels? any/c #f]))]{
+
+When no arguments are provided, creates an instance of the default
+ font. If no face name is provided, the font is created without a face
+ name. Otherwise, see @scheme[font-name-directory<%>] for information
+ about the way @scheme[face] is interpreted for drawing text on
+ various platforms and devices; when a platform- or device-specific
+ interpretation of @scheme[face] is not available, the @scheme[family]
+ is used to draw text.
+
+See @scheme[font%] for information about @scheme[family],
+ @scheme[style], and @scheme[weight]. @scheme[font-name-directory<%>].
+
+}
+
+@defmethod[(get-face)
+ (or/c string? false/c)]{
+
+Gets the font's face name, or @scheme[#f] if none is specified.
+
+}
+
+@defmethod[(get-family)
+ (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)]{
+
+Gets the font's family. See @scheme[font%] for information about
+families.
+
+}
+
+@defmethod[(get-font-id)
+ (and/c exact? integer?)]{
+
+Gets the font's ID, for use with a
+@scheme[font-name-directory<%>]. The ID is determined by the font's
+face and family specifications, only.
+
+}
+
+@defmethod[(get-point-size)
+ (integer-in 1 255)]{
+
+Gets the font's size (roughly the height). Despite the method name,
+ the size may be in logical units instead of points, depending on the
+ result of @method[font% get-size-in-pixels].
+
+Due to space included in a font by a font designer, a font tends to
+ generate text that is slightly taller than the nominal size.
+
+}
+
+@defmethod[(get-size-in-pixels)
+ boolean?]{
+
+Returns @scheme[#t] if the size reported by @method[font%
+ get-point-size] is in logical drawing units, @scheme[#f] if it is in
+ points.
+
+For a size in points and a screen or bitmap drawing context, the
+ logical height depends on the resolution of the screen.
+
+}
+
+@defmethod[(get-smoothing)
+ (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed)]{
+
+Gets the font's anti-alias smoothing mode. See @scheme[font%] for
+ information about smoothing.
+
+}
+
+@defmethod[(get-style)
+ (one-of/c 'normal 'italic 'slant)]{
+
+Gets the font's slant style. See @scheme[font%] for information about
+ styles.
+
+}
+
+@defmethod[(get-underlined)
+ boolean?]{
+
+Returns @scheme[#t] if the font is underlined or @scheme[#f]
+otherwise.
+
+}
+
+@defmethod[(get-weight)
+ (one-of/c 'normal 'bold 'light)]{
+
+Gets the font's weight. See @scheme[font%] for information about
+ weights.
+
+}
+
+@defmethod[(screen-glyph-exists? [c char]
+ [for-label? any/c #f])
+ boolean?]{
+
+Returns @scheme[#t] if the given character has a corresponding glyph
+ when drawing to the screen or a bitmap, @scheme[#f] otherwise.
+
+If the second argument is true, the result indicates whether the glyph
+ is available for control labels. Otherwise, it indicates whether the
+ glyph is available for @scheme[dc<%>] drawing.
+
+For @scheme[dc<%>] drawing, due to automatic font substitution when
+ drawing or measuring text, the result of this method does not depend
+ on this font's attributes (size, face, etc.). The font's attributes
+ merely provide a hint for the glyph search.
+
+See also @method[dc<%> glyph-exists?] .
+
+}}
diff --git a/collects/scribblings/gui/font-funcs.scrbl b/collects/scribblings/gui/font-funcs.scrbl
new file mode 100644
index 0000000000..c43ffc55a6
--- /dev/null
+++ b/collects/scribblings/gui/font-funcs.scrbl
@@ -0,0 +1,77 @@
+#reader(lib "docreader.ss" "scribble")
+@require["common.ss"]
+
+@title{Fonts}
+
+
+@defproc[(get-face-list [family (one-of/c 'mono 'all) 'all])
+ (listof string?)]{
+
+Returns a list of font face names available on the current system. If
+ @scheme['mono] is provided as the argument, then only faces that are
+ known to correspond to monospace fonts are included in the list.
+
+}
+
+@defproc[(get-family-builtin-face [family (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)])
+ string?]{
+
+Returns the built-in default face mapping for a particular font
+ family. The built-in default can be overridden via preferences, as
+ described in @secref["mr:fontresources"].
+
+See @scheme[font%] for information about @scheme[family].
+
+}
+
+@defthing[menu-control-font (is-a?/c font%)]{
+
+This font is the default for @scheme[popup-menu%] objects.
+
+Under Mac OS X, this font is slightly larger than
+ @scheme[normal-control-font]. Under Windows and X, it is the same
+ size as @scheme[normal-control-font].
+
+}
+
+@defthing[normal-control-font (is-a?/c font%)]{
+
+This font is the default for most controls, except
+ @scheme[list-box%] and @scheme[group-box-panel%] objects.
+
+
+}
+
+@defthing[small-control-font (is-a?/c font%)]{
+
+This font is the default for @scheme[group-box-panel%] objects, and it is
+ a suitable for controls in a floating window and other contexts that
+ need smaller controls.
+
+Under Windows, this font is the same size as
+ @scheme[normal-control-font], since the Windows control font is
+ already relatively small. Under X and Mac OS X, this font is slightly
+ smaller than @scheme[normal-control-font].
+
+
+}
+
+@defthing[tiny-control-font (is-a?/c font%)]{
+
+This font is for tiny controls, and it is smaller than
+ @scheme[small-control-font] on all platforms.
+
+}
+
+@defthing[view-control-font (is-a?/c font%)]{
+
+This font is the default for @scheme[list-box%] objects (but not
+ list box labels, which use @scheme[normal-control-font]).
+
+Under Mac OS X, this font is slightly smaller than
+ @scheme[normal-control-font], and slightly larger than
+ @scheme[small-control-font]. Under Windows and X, it is the same size
+ as @scheme[normal-control-font].
+
+}
diff --git a/collects/scribblings/gui/font-list-class.scrbl b/collects/scribblings/gui/font-list-class.scrbl
new file mode 100644
index 0000000000..0b362bfc34
--- /dev/null
+++ b/collects/scribblings/gui/font-list-class.scrbl
@@ -0,0 +1,42 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[font-list% object% ()]{
+
+A @scheme[font-list%] object maintains a list of @scheme[font%]
+ objects to avoid repeatedly creating fonts.
+
+A global font list, @scheme[the-font-list], is created automatically.
+
+
+@defconstructor/make[()]{
+
+Creates an empty font list.
+
+}
+
+@defmethod*[([(find-or-create-font [size (integer-in 1 255)]
+ [family (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)]
+ [style (one-of/c 'normal 'italic 'slant)]
+ [weight (one-of/c 'normal 'bold 'light)]
+ [underline? any/c #f]
+ [smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default]
+ [size-in-pixels? any/c #f])
+ (is-a?/c font%)]
+ [(find-or-create-font [size (integer-in 1 255)]
+ [face string?]
+ [family (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)]
+ [style (one-of/c 'normal 'italic 'slant)]
+ [weight (one-of/c 'normal 'bold 'light)]
+ [underline any/c #f]
+ [smoothing (one-of/c 'default 'partly-smoothed 'smoothed 'unsmoothed) 'default]
+ [size-in-pixels? any/c #f])
+ void?])]{
+
+Finds an existing font in the list or creates a new one (that is
+ automatically added to the list). The arguments are the same as for
+ creating a @scheme[font%] instance.
+
+}}
diff --git a/collects/scribblings/gui/font-name-directory-intf.scrbl b/collects/scribblings/gui/font-name-directory-intf.scrbl
new file mode 100644
index 0000000000..9a4a5bcb09
--- /dev/null
+++ b/collects/scribblings/gui/font-name-directory-intf.scrbl
@@ -0,0 +1,215 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+@require[(lib "bnf.ss" "scribble")]
+
+@definterface[font-name-directory<%> ()]{
+
+There is one @scheme[font-name-directory<%>] object:
+ @scheme[the-font-name-directory]. It implements the mapping from font
+ specifications (face, family, style, and weight) to information for
+ rendering text on a specific device. The mapping is different for
+ each platform. For example, when drawing to a bitmap in Windows, the
+ rendering information is simply the name of a Windows font. When
+ drawing to a PostScript file, the rendering information is a
+ PostScript font name, which encapsulates the style and weight. When
+ drawing to a bitmap in X, the rendering information is an X font
+ string, which encapsulates the style and weight, parameterized over
+ the size (using a ``\%d'' placeholder).
+
+Programmers rarely need to directly invoke methods of
+ @scheme[the-font-name-directory]. It is used automatically when
+ drawing text to a @scheme[dc<%>] object. Nevertheless,
+ @scheme[the-font-name-directory] is available so that programmers can
+ query or modify the mapping manually. A programmer may also need to
+ understand how the face-and-family mapping works.
+
+To extract mapping information from @scheme[the-font-name-directory],
+ first obtain a @defterm{font ID}, which is an index based on a family
+ and optional face string. Font IDs are returned by
+ @method[font-name-directory<%> find-or-create-font-id] and
+ @method[font-name-directory<%> get-font-id] . A Font ID can be
+ combined with a weight and style to obtain a specific mapping value
+ via @method[font-name-directory<%> get-screen-name] or
+ @method[font-name-directory<%> get-post-script-name].
+
+For a family without a face string, the corresponding font ID has a
+ useful built-in mapping for every platform and device. (The built-in
+ mapping can be overridden through the user's preferences; see
+ @secref["mr:fontresources"] for information.) For a family with a
+ face string, @scheme[the-font-name-directory] interprets the string
+ (in a platform-specific way) to generate a mapping for ``screen''
+ drawing (to a canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a
+ @scheme[printer-dc%]). When drawing to a @scheme[post-script-dc%]
+ object, the face-specific mapping defaults to the family's mapping.
+
+Under Windows and Mac OS X, a face name is interpreted simply as a
+ system font name for drawing to the screen, bitmap, or printer. The
+ mapping succeeds if the system provides a font with the given name,
+ and fails otherwise. For example, under Windows, @scheme["MS Sans
+ Serif"] maps to the font that is typically used for button
+ labels. Under X, a face name has a more complex interpretation:
+
+@itemize{
+
+ @item{If the string begins with a space, then the remainder of the
+ string is interpreted as a fontconfig/Xft font name, but only
+ if fontconfig/Xft support is enabled at compile time (which is
+ the default when available), and only if the RENDER extension
+ is available at run time. Multiple fontconfig/Xft font names
+ can appear after the initial space, separated by commas; the
+ first available font is used to draw text, and later fonts are
+ substituted for missing characters in earlier fonts.}
+
+ @item{If the string begins with @litchar["+"], then the remainder of the
+ string is interpreted as an X font name. These names are
+ usually long, such as
+ @litchar["+-b&h-lucidatypewriter-medium-r-normal-sans-24-240-75-75-m-140-iso8859-1"].
+ As usual for X font names, asterisks may appear in the string
+ as wildcards. Furthermore, the size of the font can be
+ parameterized by using @litchar["%d"] in the place of a specific
+ point size; if an asterisk appears in place of the pixel size,
+ the asterisk and @litchar["%d"] are swapped when the font size is
+ specified in pixels (otherwise the size is always interpreted
+ as points). For rotated text, @litchar["%d"] will be replaced by
+ a transformation matrix.}
+
+ @item{A string of the form
+ @litchar["-"]@nonterm{provider}@litchar{-}@nonterm{font} is
+ equivalent to
+ @litchar["+-"]@nonterm{provider}@litchar{-}@nonterm{font}@litchar{-}@nonterm{weight}@litchar{-}@nonterm{style}@litchar{-normal-*-*-%d-*-*-*-*-*-*},
+ where @nonterm{weight} is either @litchar{medium},
+ @litchar{light}, or @litchar{bold} (depending on the requested
+ weight mapping) and @nonterm{style} is either @litchar{r},
+ @litchar{i}, or @litchar{i} (depending on the requested style
+ mapping).}
+
+ @item{A string of the form @litchar["-"]@nonterm{font} is
+ equivalent to @litchar{-*-}@nonterm{font}.}
+
+ @item{A string of any other format is interpreted as an X font name,
+ optionally parameterized with @litchar{%d}.}
+
+}
+
+The mapping for face names can be overridden (on all platforms)
+ through the user's preferences, as described in
+ @secref["mr:fontresources"].
+
+
+
+@defmethod[(find-family-default-font-id [family (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)])
+ (and/c exact? integer?)]{
+
+Gets the font ID representing the default font for a family. See
+@scheme[font%] for information about font families.
+
+}
+
+@defmethod[(find-or-create-font-id [name string?]
+ [family (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)])
+ (and/c exact? integer?)]{
+
+Gets the face name for a font ID, initializing the mapping for
+ the face name if necessary.
+
+Font ID are useful only as mapping indices for
+ @indexed-scheme[the-font-name-directory].
+
+}
+
+@defmethod[(get-face-name [font-id (and/c exact? integer?)])
+ (or/c string? false/c)]{
+
+Gets the face name for a font ID. If the font ID corresponds to
+ the default font for a particular family, @scheme[#f] is returned.
+
+}
+
+@defmethod[(get-family [font-id (and/c exact? integer?)])
+ (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)]{
+
+Gets the family for a font ID. See
+@scheme[font%] for information about font families.
+
+}
+
+@defmethod[(get-font-id [name string?]
+ [family (one-of/c 'default 'decorative 'roman 'script
+ 'swiss 'modern 'symbol 'system)])
+ (and/c exact? integer?)]{
+
+Gets the font ID for a face name paired with a default family. If the
+ mapping for the given pair is not already initialized, @scheme[0] is
+ returned. See also @method[font-name-directory<%>
+ find-or-create-font-id].
+
+Font ID are useful only as mapping indices for
+ @indexed-scheme[the-font-name-directory].
+
+}
+
+@defmethod[(get-post-script-name [font-id (and/c exact? integer?)]
+ [weight (one-of/c 'normal 'bold 'light)]
+ [style (one-of/c 'normal 'italic 'slant)])
+ (or/c string? false/c)]{
+
+Gets a PostScript font name for a font ID, weight, and style
+ combination. The PostScript font name is used both for the font name
+ in PostScript output (sans character set) and as the @|AFM| file
+ name; see also @secref["mr:postscriptfonts"].
+
+See @scheme[font%] for information about @scheme[weight] and
+ @scheme[style].
+
+}
+
+@defmethod[(get-screen-name [font-id (and/c exact? integer?)]
+ [weight (one-of/c 'normal 'bold 'light)]
+ [style (one-of/c 'normal 'italic 'slant)])
+ (or/c string? false/c)]{
+
+Gets a platform-dependent screen font name (used for drawing to a
+ canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a
+ @scheme[printer-dc%]) for a font ID, weight, and style combination.
+
+See @scheme[font%] for information about @scheme[weight] and
+@scheme[style].
+
+}
+
+@defmethod[(set-post-script-name [font-id (and/c exact? integer?)]
+ [weight (one-of/c 'normal 'bold 'light)]
+ [style (one-of/c 'normal 'italic 'slant)]
+ [name string?])
+ void?]{
+
+Sets a PostScript font name for a font ID, weight, and style
+ combination. See also @method[font-name-directory<%>
+ get-post-script-name].
+
+See @scheme[font%] for information about @scheme[weight] and @scheme[style].
+
+}
+
+@defmethod[(set-screen-name [font-id (and/c exact? integer?)]
+ [weight (one-of/c 'normal 'bold 'light)]
+ [style (one-of/c 'normal 'italic 'slant)]
+ [name string?])
+ void?]{
+
+Sets a platform-dependent screen font name (used for drawing to a
+ canvas's @scheme[dc<%>], a @scheme[bitmap-dc%], or a
+ @scheme[printer-dc%]) for a font ID, weight, and style combination.
+
+Under X, if the screen name contains @litchar{%d}, it is replaced by
+ the size of the font (point size times 10) to obtain the full screen
+ font name.
+
+See @scheme[font%] for information about @scheme[weight] and
+ @scheme[style].
+
+}}
+
diff --git a/collects/scribblings/gui/gl-config-class.scrbl b/collects/scribblings/gui/gl-config-class.scrbl
new file mode 100644
index 0000000000..a8525ca1c8
--- /dev/null
+++ b/collects/scribblings/gui/gl-config-class.scrbl
@@ -0,0 +1,113 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[gl-config% object% ()]{
+
+A @scheme[gl-config%] object encapsulates configuration information
+ for an OpenGL drawing context. Use a @scheme[gl-config%] object as an
+ initialization argument for @scheme[canvas%], or provide it to
+ @xmethod[bitmap% set-gl-config].
+
+
+@defconstructor[()]{
+
+Creates a GL configuration that indicates double buffering, a depth
+ buffer of size one, no stencil buffer, no accumulation buffer, no
+ multisampling, and not stereo.
+
+}
+
+@defmethod[(get-accum-size)
+ (integer-in 0 256)]{
+
+Reports the accumulation-buffer size (for each of red, green, blue,
+ and alpha) that the configuration requests, where zero means no
+ accumulation buffer is requested.
+
+}
+
+@defmethod[(get-depth-size)
+ (integer-in 0 256)]{
+
+Reports the depth-buffer size that the configuration requests, where
+ zero means no depth buffer is requested.
+
+}
+
+@defmethod[(get-double-buffered)
+ boolean?]{
+
+Reports whether the configuration requests double buffering or not.
+
+}
+
+@defmethod[(get-multisample-size)
+ (integer-in 0 256)]{
+
+Reports the multisampling size that the configuration requests, where
+ zero means no multisampling is requested.
+
+}
+
+@defmethod[(get-stencil-size)
+ (integer-in 0 256)]{
+
+Reports the stencil-buffer size that the configuration requests, where
+ zero means no stencil buffer is requested.
+
+}
+
+@defmethod[(get-stereo)
+ boolean?]{
+
+Reports whether the configuration requests stereo or not.
+
+}
+
+@defmethod[(set-accum-size [on? (integer-in 0 256)])
+ void?]{
+
+Adjusts the configuration to request a particular accumulation-buffer
+ size for every channel (red, green, blue, and alpha), where zero
+ means no accumulation buffer is requested.
+
+}
+
+@defmethod[(set-depth-size [on? (integer-in 0 256)])
+ void?]{
+
+Adjusts the configuration to request a particular depth-buffer size,
+ where zero means no depth buffer is requested.
+
+}
+
+@defmethod[(set-double-buffered [on? any/c])
+ void?]{
+
+Adjusts the configuration to request double buffering or not.
+
+}
+
+@defmethod[(set-multisample-size [on? (integer-in 0 256)])
+ void?]{
+
+Adjusts the configuration to request a particular multisample size,
+ where zero means no multisampling is requested. If a multisampling
+ context is not available, this request will be ignored.
+
+}
+
+@defmethod[(set-stencil-size [on? (integer-in 0 256)])
+ void?]{
+
+Adjusts the configuration to request a particular stencil-buffer size,
+ where zero means no stencil buffer is requested.
+
+}
+
+@defmethod[(set-stereo [on? any/c])
+ void?]{
+
+Adjusts the configuration to request stereo or not.
+
+}}
diff --git a/collects/scribblings/gui/gl-context-intf.scrbl b/collects/scribblings/gui/gl-context-intf.scrbl
new file mode 100644
index 0000000000..b7f5ca947e
--- /dev/null
+++ b/collects/scribblings/gui/gl-context-intf.scrbl
@@ -0,0 +1,98 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@definterface[gl-context<%> ()]{
+
+A @scheme[gl-context<%>] object represents a context for drawing with
+ @as-index{OpenGL} to a specific @scheme[dc<%>] instance. To obtain a
+ @scheme[gl-context<%>] object, call @method[dc<%> get-gl-context] of
+ the target drawing context.
+
+Only canvas @scheme[dc<%>] and @scheme[bitmap-dc%] objects support
+ OpenGL (always under Windows and Mac OS X, sometimes under X), and in
+ the case of a @scheme[bitmap-dc%], the context is usable only when
+ the target bitmap is non-monochrome. When the target bitmap for a
+ @scheme[bitmap-dc%] context is changed via @method[bitmap-dc%
+ set-bitmap], the associated OpenGL context is reset, but the
+ @scheme[gl-context<%>] keeps its identity. Canvas contexts are double
+ buffered, and bitmap contexts are single buffered.
+
+MrEd provides no OpenGL routines. Instead, they must be obtained from
+ a separate library, such as @scheme[(lib "sgl.ss" "sgl")]. MrEd
+ merely manages the current OpenGL context, connecting it to windows
+ and bitmaps.
+
+Only one OpenGL context can be active at a time across all threads and
+ eventspaces. Except under Mac OS X, OpenGL contexts are not protected
+ against interference among threads; that is, if a thread selects one
+ of its OpenGL contexts, then other threads can write into the context
+ via OpenGL commands. However, if all threads issue OpenGL commands
+ only within a thunk passed to @method[gl-context<%> call-as-current],
+ then drawing from the separate threads will not interfere, because
+ @method[gl-context<%> call-as-current] uses a lock to serialize
+ context selection across all threads in MrEd.
+
+
+@defmethod[(call-as-current [thunk (-> any)]
+ [alternate evt? never-evt]
+ [enable-breaks? any/c #f])
+ any/c]{
+
+Calls a thunk with this OpenGL context as the current context for
+ OpenGL commands.
+
+The method blocks to obtain a lock that protects the global OpenGL
+ context, and it releases the lock when the thunk returns or
+ escapes. The lock is re-entrant, so a nested use of the method in the
+ same thread with the same OpenGL context does not obtain or release
+ the lock.
+
+The lock prevents interference among OpenGL-using threads. If a
+ thread is terminated while holding the context lock, the lock is
+ released. Continuation jumps into the thunk do not grab the lock or
+ set the OpenGL context. See @scheme[gl-context<%>] for more
+ information on interference.
+
+The method accepts an alternate @tech{synchronizable event} for use
+ while blocking for the context lock; see also @scheme[sync].
+
+The result of the method call is the result of the thunk if it is
+ called, or the result of the alternate event if it is chosen instead
+ of the context lock.
+
+If @method[gl-context<%> ok?] returns @scheme[#f] at the time that
+ this method is called, then @|MismatchExn|.
+
+If @scheme[enable-breaks?] is true, then the method uses
+ @scheme[sync/enable-break] while blocking for the context-setting
+ lock instead of @scheme[sync].
+
+}
+
+@defmethod[(ok?)
+ boolean?]{
+
+Returns @scheme[#t] if this context is available OpenGL drawing,
+ @scheme[#f] otherwise.
+
+A context is unavailable if OpenGL support is disabled at compile time
+ or run time, if the context is associated with a
+ @scheme[bitmap-dc%] with no selected bitmap or with a monochrome
+ selected bitmap, if the context is for a canvas that no longer
+ exists, or if there was a low-level error when preparing the context.
+
+}
+
+@defmethod[(swap-buffers)
+ void?]{
+
+Swaps the front (visible) and back (OpenGL-drawing) buffer for a
+ context associated with a canvas, and has no effect on a bitmap
+ context.
+
+This method implicitly uses @method[gl-context<%> call-as-current] to
+ obtain the context lock. Since the lock is re-entrant, however, the
+ @method[gl-context<%> swap-buffers] method can be safely used within
+ a @method[gl-context<%> call-as-current] thunk.
+
+}}
diff --git a/collects/scribblings/gui/global-draw-funcs.scrbl b/collects/scribblings/gui/global-draw-funcs.scrbl
new file mode 100644
index 0000000000..f04d7e19d0
--- /dev/null
+++ b/collects/scribblings/gui/global-draw-funcs.scrbl
@@ -0,0 +1,100 @@
+#reader(lib "docreader.ss" "scribble")
+@require["common.ss"]
+
+@title{Global Graphics}
+
+@defproc[(flush-display)
+ void?]{
+
+Under X and Mac OS X, flushes pending display messages such that the
+ user's display reflects the actual state of the windows. Under
+ Windows, the procedure has no effect.
+
+}
+
+@defproc[(get-display-depth)
+ nonnegative-exact-integer?]{
+
+Returns the depth of the main display (a value of 1 denotes a monochrome display).
+
+}
+
+@defproc[(get-display-left-top-inset [avoid-bars? bool @scheme[#f]])
+ (values nonnegative-exact-integer? nonnegative-exact-integer?)]{
+
+When the optional argument is @scheme[#f] (the default), this function
+ returns the offset of the main screen's origin from the
+ top-left of the physical screen. Under X and Windows, the result is
+ always @scheme[0] and @scheme[0]; under Mac OS X, the result is
+ @scheme[0] and the height of the menu bar.
+
+When the optional argument is true, this function returns the amount
+ space at the left and top of the main screen that is occupied by the
+ task bar (Windows) or menu bar and dock (Mac OS X). Under X, the
+ result is always @scheme[0] and @scheme[0].
+
+}
+
+@defproc[(get-display-size [full-screen? bool @scheme[#f]])
+ (values nonnegative-exact-integer? nonnegative-exact-integer?)]{
+
+@index["screen resolution"]{Gets} the physical size of the display in
+ pixels. Under Windows, this size does not include the task bar by
+ default. Under Mac OS X, this size does not include the menu bar or
+ dock area by default.
+
+Under Windows and Mac OS X, if the optional argument is true, then
+ the task bar, menu bar, and dock area are included in the result.
+
+Returns the screen's width and height.
+
+}
+
+@defproc[(is-color-display?)
+ boolean?]{
+
+Returns @scheme[#t] if the main display has color, @scheme[#f]
+otherwise.
+
+}
+
+@defproc[(register-collecting-blit [canvas (is-a?/c canvas%)]
+ [x real?]
+ [y real?]
+ [w (and/c real? (not/c negative?))]
+ [h (and/c real? (not/c negative?))]
+ [on (is-a?/c bitmap%)]
+ [off (is-a?/c bitmap%)]
+ [on-x real? 0]
+ [on-y real? 0]
+ [off-x real? 0]
+ [off-y real? 0])
+ void?]{
+
+Registers a blit to occur when garbage collection starts or ends.
+
+When garbage collection starts, @scheme[(send (send canvas #,(::
+ canvas<%> get-dc)) #,(:: dc<%> draw-bitmap-section) on on-x on-y x y w
+ h)] is called. When garbage collection ends, @scheme[(send (send
+ canvas #,(:: canvas<%> get-dc)) #,(:: dc<%> draw-bitmap-section) off
+ off-x off-y x y w h)] is called. If @scheme[canvas]'s device context
+ has a scale, the scale may or may not be temporarily disabled during
+ the bitmap drawing.
+
+The @scheme[canvas] is registered weakly, so it will be automatically
+ unregistered if the canvas becomes invisible and inaccessible.
+ Multiple registrations can be installed for the same canvas.
+
+See also @scheme[unregister-collecting-blit].
+
+}
+
+@defproc[(unregister-collecting-blit [canvas (is-a?/c canvas%)])
+ void?]{
+
+Unregisters a blit request installed with See also
+ @scheme[register-collecting-blit].
+
+Unregisters all blits for @scheme[canvas].
+
+}
diff --git a/collects/scribblings/gui/gui.scrbl b/collects/scribblings/gui/gui.scrbl
index 66582644e7..60cc47a548 100644
--- a/collects/scribblings/gui/gui.scrbl
+++ b/collects/scribblings/gui/gui.scrbl
@@ -1,7 +1,7 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
-@title{PLT Scheme GUI Reference}
+@title{PLT Scheme GUI Toolbox}
This manual describes MrEd.
@@ -12,67 +12,8 @@ This manual describes MrEd.
@;------------------------------------------------------------------------
-@section{GUI Toolbox Organization}
-
-For documentation purposes, the MrEd toolbox is organized into three
-parts:
-
-@itemize{
-
- @item{The @deftech{windowing} toolbox, for implementing form-filling
- GUI programs (such as a database query window) using buttons, menus,
- text fields, and events. The windowing toolbox is documented in
- @secref["mr:windowing"].}
-
- @item{The @deftech{drawing} toolbox, for drawing pictures or
- implementing dynamic GUI programs (such as a video game) using
- drawing canvases, pens, and brushes. The drawing toolbox is
- documented in @secref["mr:drawing"].}
-
- @item{The @deftech{editor} toolbox, for developing traditional text
- editors, editors that mix text and graphics, or free-form layout
- editors (such as a word processor, HTML editor, or icon-based file
- browser). The editor toolbox is documented in @secref["mr:editor"].}
-
-}
-
-These three parts roughly represent layers of increasing
- sophistication. Simple GUI programs access only the windowing toolbox
- directly, more complex programs use both the windowing and drawing
- toolboxes, and large-scale applications rely on all three
- toolboxes. This three-layer view of the toolbox breaks down under
- close scrutiny, because the windowing, drawing, and editor toolboxes
- are actually interdependent and intertwined. Nevertheless, the
- layered separation is a good approximation.
-
-All three parts are immediately available when MrEd is started, as
- well as the base class system from MzLib. The @indexed-file{mred.ss}
- library module of the @file{mred} collection provides all of the
- class, interface, and procedure names defined in this manual. When
- MrEd starts up, it imports the @file{mred.ss} module and MzLib's
- @indexed-file{class.ss} module into the initial namespace (so no
- knowledge about modules is required to understand this manual).
-
-The module @indexed-scheme[#%mred-kernel] is built into the MrEd
- executable, and intended for use only by @file{mred.ss}. Attempting
- to require @file{mred.ss} in a plain MzScheme executable will result
- in a run-time error, because @scheme[#%mred-kernel] will not be
- available.
-
-To create a namespace in which the @file{mred.ss} module will be used,
- call the @scheme[make-namespace-with-mred] procedure. That
- procedure attaches the @file{mred.ss} instance of the current
- namespace to the created namespace. Otherwise, different namespaces
- create different instances of the @file{mred.ss} module, which in
- turn generate distinct classes.
-
-@;------------------------------------------------------------------------
-
-@include-section["windowing.scrbl"]
-
-@;------------------------------------------------------------------------
-
-@include-section["drawing.scrbl"]
+@include-section["guide.scrbl"]
+@include-section["reference.scrbl"]
@;------------------------------------------------------------------------
diff --git a/collects/scribblings/gui/guide.scrbl b/collects/scribblings/gui/guide.scrbl
new file mode 100644
index 0000000000..48b287f252
--- /dev/null
+++ b/collects/scribblings/gui/guide.scrbl
@@ -0,0 +1,58 @@
+#reader(lib "docreader.ss" "scribble")
+@require["common.ss"]
+
+@title[#:style 'toc]{Guide}
+
+For documentation purposes, the MrEd toolbox is organized into three
+parts:
+
+@itemize{
+
+ @item{The @deftech{windowing} toolbox, for implementing form-filling
+ GUI programs (such as a database query window) using buttons, menus,
+ text fields, and events. The windowing toolbox is described in
+ @secref["mr:windowing-overview"].}
+
+ @item{The @deftech{drawing} toolbox, for drawing pictures or
+ implementing dynamic GUI programs (such as a video game) using
+ drawing canvases, pens, and brushes. The drawing toolbox is
+ described in @secref["mr:drawing-overview"].}
+
+ @item{The @deftech{editor} toolbox, for developing traditional text
+ editors, editors that mix text and graphics, or free-form layout
+ editors (such as a word processor, HTML editor, or icon-based file
+ browser). The editor toolbox is described in
+ @secref["mr:editor-overview"].}
+
+}
+
+These three parts roughly represent layers of increasing
+ sophistication. Simple GUI programs access only the windowing toolbox
+ directly, more complex programs use both the windowing and drawing
+ toolboxes, and large-scale applications rely on all three
+ toolboxes. This three-layer view of the toolbox breaks down under
+ close scrutiny, because the windowing, drawing, and editor toolboxes
+ are actually interdependent and intertwined. Nevertheless, the
+ layered separation is a good approximation.
+
+All three parts are immediately available when MrEd is started, as
+ well as the base class system from MzLib. The @indexed-file{mred.ss}
+ library module of the @file{mred} collection provides all of the
+ class, interface, and procedure names defined in this manual. When
+ MrEd starts up, it imports the @file{mred.ss} module and MzLib's
+ @indexed-file{class.ss} module into the initial namespace (so no
+ knowledge about modules is required to understand this manual).
+
+@local-table-of-contents[]
+
+@;------------------------------------------------------------------------
+
+@include-section["win-overview.scrbl"]
+
+@;------------------------------------------------------------------------
+
+@include-section["draw-overview.scrbl"]
+
+@;------------------------------------------------------------------------
+
+@include-section["editor-overview.scrbl"]
diff --git a/collects/scribblings/gui/pen-class.scrbl b/collects/scribblings/gui/pen-class.scrbl
new file mode 100644
index 0000000000..3699e884c2
--- /dev/null
+++ b/collects/scribblings/gui/pen-class.scrbl
@@ -0,0 +1,243 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[pen% object% ()]{
+
+A pen is a drawing tool with a color, width, and style. A pen draws
+ lines and outlines, such as the outline of a rectangle. On a
+ monochrome display, all non-white pens are drawn as black.
+
+In addition to its color, width, and style, a pen can have a stipple
+ bitmap that is a 8 x 8 monochrome bitmap. This stipple is used only
+ in unsmoothed mode (see @method[dc<%> set-smoothing]) or in a
+ PostScript drawing context. Painting with a stipple pen is similar to
+ calling @method[dc<%> draw-bitmap] with the stipple bitmap in region
+ painted by the pen.
+
+A pen's style is one of the following:
+
+@itemize{
+
+ @item{@indexed-scheme['transparent] --- Draws with no effect (on the
+ outline of the drawn shape).}
+
+ @item{@indexed-scheme['solid] --- Draws using the pen's color. If a
+ (monochrome) stipple is installed into the pen, black pixels
+ from the stipple are transferred to the destination using the
+ brush's color, and white pixels from the stipple are not
+ transferred.}
+
+ @item{@indexed-scheme['xor] --- In unsmoothed mode, the pen's color
+ or colored stipple is xor-ed with existing destination pixel
+ values. The @scheme['xor] mapping is unspecified for arbitrary
+ color combinations, but the mapping provides two guarantees:
+ @itemize{
+
+ @item{Black-and-white drawing to a color or monochrome
+ destination always works as expected: black xor white = black,
+ white xor black = black, black xor black = white, and white xor
+ white = white.}
+
+ @item{Performing the same drawing operation twice in a row with
+ @scheme['xor] is equivalent to a no-op.}
+
+ }
+ In a smoothing mode, @scheme['xor] is equivalent to @scheme['solid].}
+
+ @item{@indexed-scheme['hilite] --- In unsmoothed mode, existing
+ destination pixels are ``highlighted'' in a platform-specific
+ way when the pen color is black. Under Windows for a color
+ drawing context, the inverted RGB components of destination
+ pixel are combined with the RGB components of the system-wide
+ highlight color using a bitwise ``or'', and the combination is
+ used. Under Mac OS X for a color drawing context, the
+ inverted RGB components of the system-wide highlight color are
+ subtracted from the RGB components of each destination pixel,
+ and the difference (or 0 for a negative result) is used. Under
+ X or for any monochrome drawing context, @scheme['hilite] is the
+ same as @scheme['xor]. In a smoothing mode, @scheme['hilite] is
+ treated like @scheme['solid].}
+
+ @item{The following special pen modes use the pen's color, and they only
+ apply when a stipple is not used:
+ @itemize{
+ @item{@indexed-scheme['dot]}
+ @item{@indexed-scheme['long-dash]}
+ @item{@indexed-scheme['short-dash]}
+ @item{@indexed-scheme['dot-dash]}
+ @item{@indexed-scheme['xor-dot]}
+ @item{@indexed-scheme['xor-long-dash]}
+ @item{@indexed-scheme['xor-short-dash]}
+ @item{@indexed-scheme['xor-dot-dash]}
+ }}
+
+}
+
+To avoid creating multiple pens with the same characteristics, use the
+ global @scheme[pen-list%] object @indexed-scheme[the-pen-list], or
+ provide a color, width, and style to @xmethod[dc<%> set-pen].
+
+A pen of size @scheme[0] uses the minimum line size for the
+ destination drawing context. In (unscaled) canvases and bitmaps in
+ unsmoothed mode, a zero-width pen behaves the nearly same as a pen of
+ size @scheme[1]. In a smoothing mode (including all
+ @scheme[post-script-dc%] drawing), a pen of size @scheme[0] draws a
+ line thinner than a pen of size @scheme[1]. If the pen's width is not
+ an integer, then the width is truncated to an integer (even before
+ scaling) in unsmoothed mode.
+
+
+
+
+@defconstructor*/make[(()
+ ([color (is-a?/c color%)]
+ [width (real-in 0 255)]
+ [style (one-of/c 'transparent 'solid 'xor 'hilite
+ 'dot 'long-dash 'short-dash 'dot-dash
+ 'xor-dot 'xor-long-dash 'xor-short-dash
+ 'xor-dot-dash)])
+ ([color-name string?]
+ [width (real-in 0 255)]
+ [style (one-of/c 'transparent 'solid 'xor 'dot 'hilite
+ 'long-dash 'short-dash 'dot-dash
+ 'xor-dot 'xor-long-dash 'xor-short-dash
+ 'xor-dot-dash)]))]{
+
+When no argument are provided, the result is a solid black pen of
+ width @scheme[0]. Otherwise, the result is a pen with the given
+ color, width, and style. For the case that the color is specified
+ using a name, see @scheme[color-database<%>] for information about
+ color names; if the name is not known, the pen's color is black.
+
+}
+
+@defmethod[(get-cap)
+ (one-of/c 'round 'projecting 'butt)]{
+
+Returns the pen cap style (Windows unsmoothed, X unsmoothed, all
+ smoothing). The default is @scheme['round].
+
+}
+
+@defmethod[(get-color)
+ (is-a?/c color%)]{
+
+Returns the pen's color object.
+
+}
+
+@defmethod[(get-join)
+ (one-of/c 'round 'bevel 'miter)]{
+
+Returns the pen join style (Windows unsmoothed, X unsmoothed, all
+ smoothing). The default is @scheme['round].
+
+}
+
+@defmethod[(get-stipple)
+ (or/c (is-a?/c bitmap%) false/c)]{
+
+Gets the current stipple bitmap, or returns @scheme[#f] if no stipple
+ bitmap is installed.
+
+}
+
+@defmethod[(get-style)
+ (one-of/c 'transparent 'solid 'xor 'hilite
+ 'dot 'long-dash 'short-dash 'dot-dash
+ 'xor-dot 'xor-long-dash 'xor-short-dash
+ 'xor-dot-dash)]{
+
+Returns the pen style. See @scheme[pen%] for information about
+possible styles.
+
+}
+
+@defmethod[(get-width)
+ (real-in 0 255)]{
+
+Returns the pen width.
+
+}
+
+@defmethod[(set-cap [cap-style (one-of/c 'round 'projecting 'butt)])
+ void?]{
+
+Sets the pen cap style (Windows unsmoothed, X unsmoothed, all
+ smoothing). See @method[pen% get-cap] for information about cap
+ styles.
+
+A pen cannot be modified if it was obtained from a @scheme[pen-list%]
+ or while it is selected into a drawing context.
+
+}
+
+@defmethod*[([(set-color [color (is-a?/c color%)])
+ void?]
+ [(set-color [color-name string?])
+ void?]
+ [(set-color [red (integer-in 0 255)]
+ [green (integer-in 0 255)]
+ [blue (integer-in 0 255)])
+ void?])]{
+
+Sets the pen color.
+
+A pen cannot be modified if it was obtained from a
+ @scheme[pen-list%] or while it is selected into a drawing context.
+
+}
+
+@defmethod[(set-join [join-style (one-of/c 'round 'bevel 'miter)])
+ void?]{
+
+Sets the pen join style (Windows unsmoothed, X unsmoothed, all
+ smoothing). See @method[pen% get-join] for information about join
+ styles.
+
+A pen cannot be modified if it was obtained from a
+ @scheme[pen-list%] or while it is selected into a drawing context.
+
+}
+
+@defmethod[(set-stipple [stipple (or/c (is-a?/c bitmap%) false/c)])
+ void?]{
+
+Sets the pen stipple bitmap, which must be an 8 x 8 monochrome bitmap
+ or @scheme[#f], which turns off the stipple bitmap.
+
+A bitmap cannot be used as a stipple if it is selected into a
+ @scheme[bitmap-dc%] object; if the given bitmap is selected into a
+ @scheme[bitmap-dc%] object, @|MismatchExn|. A pen cannot be modified
+ if it was obtained from a @scheme[pen-list%] or while it is selected
+ into a drawing context.
+
+A pen's stipple is not used in a smoothing mode, except for a
+ @scheme[post-script-dc%] (which is always in smoothed mode).
+
+}
+
+@defmethod[(set-style [style (one-of/c 'transparent 'solid 'xor 'hilite
+ 'dot 'long-dash 'short-dash 'dot-dash
+ 'xor-dot 'xor-long-dash 'xor-short-dash
+ 'xor-dot-dash)])
+ void?]{
+
+Sets the pen style. See @scheme[pen%] for information about the
+ possible styles.
+
+A pen cannot be modified if it was obtained from a
+ @scheme[pen-list%] or while it is selected into a drawing context.
+
+}
+
+@defmethod[(set-width [width (real-in 0 255)])
+ void?]{
+
+Sets the pen width.
+
+A pen cannot be modified if it was obtained from a
+ @scheme[pen-list%] or while it is selected into a drawing context.
+
+}}
+
diff --git a/collects/scribblings/gui/pen-list-class.scrbl b/collects/scribblings/gui/pen-list-class.scrbl
new file mode 100644
index 0000000000..f7eb602f31
--- /dev/null
+++ b/collects/scribblings/gui/pen-list-class.scrbl
@@ -0,0 +1,45 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[pen-list% object% ()]{
+
+A @scheme[pen-list%] object maintains a list of @scheme[pen%]
+ objects to avoid repeatedly creating pen objects. A @scheme[pen%]
+ object in a pen list cannot be mutated.
+
+A global pen list @indexed-scheme[the-pen-list] is created automatically.
+
+
+
+
+
+@defconstructor/make[()]{
+
+Creates an empty pen list.
+
+
+}
+
+@defmethod*[([(find-or-create-pen [color (is-a?/c color%)]
+ [width (real-in 0 255)]
+ [style (one-of/c 'transparent 'solid 'xor 'hilite
+ 'dot 'long-dash 'short-dash 'dot-dash
+ 'xor-dot 'xor-long-dash 'xor-short-dash
+ 'xor-dot-dash)])
+ (is-a?/c pen%)]
+ [(find-or-create-pen [color-name string?]
+ [width (real-in 0 255)]
+ [style (one-of/c 'transparent 'solid 'xor 'hilite
+ 'dot 'long-dash 'short-dash 'dot-dash
+ 'xor-dot 'xor-long-dash 'xor-short-dash
+ 'xor-dot-dash)])
+ (or/c (is-a?/c pen%) false/c)])]{
+
+Finds a pen of the given specification, or creates one and adds it to
+the list. The arguments are the same as for creating a @scheme[pen%]
+instance. When @scheme[color-name] is provided, however, the return
+value is @scheme[#f] when no color matching @scheme[color-name] can be
+found in @scheme[the-color-database].
+
+}}
+
diff --git a/collects/scribblings/gui/point-class.scrbl b/collects/scribblings/gui/point-class.scrbl
new file mode 100644
index 0000000000..10565cdc03
--- /dev/null
+++ b/collects/scribblings/gui/point-class.scrbl
@@ -0,0 +1,41 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[point% object% ()]{
+
+A @scheme[point%] is used for certain drawing commands. It
+ encapsulates two real numbers.
+
+@defconstructor*/make[(()
+ ([x real?]
+ [y real?]))]{
+
+Creates a point. If @scheme[x] and @scheme[y] are not supplied, they
+ are set to @scheme[0].
+}
+
+@defmethod[(get-x)
+ real?]{
+Gets the point x-value.
+
+}
+
+@defmethod[(get-y)
+ real?]{
+Gets the point y-value.
+
+}
+
+@defmethod[(set-x [x real?])
+ void?]{
+Sets the point x-value.
+
+}
+
+@defmethod[(set-y [y real?])
+ void?]{
+
+Sets the point y-value.
+
+}}
+
diff --git a/collects/scribblings/gui/post-script-dc-class.scrbl b/collects/scribblings/gui/post-script-dc-class.scrbl
new file mode 100644
index 0000000000..783e0df89b
--- /dev/null
+++ b/collects/scribblings/gui/post-script-dc-class.scrbl
@@ -0,0 +1,58 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[post-script-dc% object% (dc<%>)]{
+
+A @scheme[post-script-dc%] object is a PostScript device context, that
+ can write PostScript files on any platform. See also
+ @scheme[ps-setup%].
+
+@|PrintNote|
+
+See also @scheme[printer-dc%].
+
+
+@defconstructor[([interactive any/c #t]
+ [parent (or/c (is-a?/c frame%) (is-a?/c dialog%) false/c) #f]
+ [use-paper-bbox any/c #f]
+ [as-eps any/c #t])]{
+
+If @scheme[interactive] is true, the user is given a dialog for
+ setting printing parameters (see @scheme[get-ps-setup-from-user]);
+ the resulting configuration is installed as the current
+ configuration). If the user chooses to print to a file (the only
+ possibility under Windows and Mac OS X), another dialog is given to
+ select the filename. If the user hits cancel in either of these
+ dialogs, then @method[dc<%> ok?] returns @scheme[#f].
+
+If @scheme[parent] is not @scheme[#f], it is used as the parent window of
+ the configuration dialog.
+
+If @scheme[interactive] is @scheme[#f], then the settings returned by
+ @scheme[current-ps-setup] are used. A file dialog is still presented
+ to the user if the @method[ps-setup% get-file] method returns
+ @scheme[#f], and the user may hit cancel in that case so that
+ @method[dc<%> ok?] returns @scheme[#f].
+
+If @scheme[use-paper-bbox] is @scheme[#f], then the PostScript
+ bounding box for the output is determined by drawing commands issued
+ to the object; such a bounding box encloses all parts of the drawing
+ @italic{ignoring} clipping regions (so the bounding box may be
+ approximate). If @scheme[use-paper-bbox] is not @scheme[#f], then the
+ bounding box is determined by the current paper size (as specified by
+ @scheme[current-ps-setup]), and the bounding box does not include the
+ margin (also specified by @scheme[current-ps-setup]).
+
+@index["Encapsulated PostScript (EPS)"]{If} @scheme[as-eps] is
+ @scheme[#f], then the generated PostScript does not include an
+ Encapsulated PostScript (EPS) header, and instead includes a generic
+ PostScript header. Otherwise, the generated PostScript includes a
+ header that identifiers it as EPS.
+
+See also @scheme[ps-setup%] and @scheme[current-ps-setup]. The
+settings for a particular @scheme[post-script-dc%] object are fixed to
+the values in the current configuration when the object is created
+(after the user has interactively adjusted them when
+@scheme[interactive] is true).
+
+}}
diff --git a/collects/scribblings/gui/post-script-funcs.scrbl b/collects/scribblings/gui/post-script-funcs.scrbl
new file mode 100644
index 0000000000..ebef3e979e
--- /dev/null
+++ b/collects/scribblings/gui/post-script-funcs.scrbl
@@ -0,0 +1,25 @@
+#reader(lib "docreader.ss" "scribble")
+@require["common.ss"]
+
+@title{PostScript}
+
+@defparam[current-ps-afm-file-paths paths (listof path?)]{
+
+A parameter determines the list of paths that is used to find AFM
+ files. See @secref["mr:postscriptfonts"] for more information.
+
+}
+
+@defparam[current-ps-cmap-file-paths paths (listof path?)]{
+
+A parameter that determines the list of paths that is used to find
+ CMap files. See @secref["mr:postscriptfonts"] for more information.
+
+}
+
+@defparam[current-ps-setup pss (is-a?/c ps-setup%)]{
+
+A parameter that determines the current PostScript configuration
+ settings. See @scheme[post-script-dc%] and @scheme[printer-dc%].
+
+}
diff --git a/collects/scribblings/gui/printer-dc-class.scrbl b/collects/scribblings/gui/printer-dc-class.scrbl
new file mode 100644
index 0000000000..49b8abfb5c
--- /dev/null
+++ b/collects/scribblings/gui/printer-dc-class.scrbl
@@ -0,0 +1,33 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[printer-dc% object% (dc<%>)]{
+
+A @scheme[printer-dc%] object is a Windows or Mac OS X printer
+ device context. The class cannot be instantiated under X (an
+ @scheme[exn:misc:unsupported] exception is raised).
+
+Under Mac OS X, a newly created @scheme[printer-dc%] object obtains
+ orientation (portrait versus landspace) and scaling information from
+ the current @scheme[ps-setup%] object, as determined by the
+ @scheme[current-ps-setup] parameter. This information can be
+ configured by the user through a dialog shown by
+ @scheme[get-page-setup-from-user].
+
+@|PrintNote|
+
+See also @scheme[post-script-dc%].
+
+When a @scheme[printer-dc%] object is created, the user gets
+ platform-specific modal dialogs for configuring the output.
+ If the user cancels the dialog, the @method[dc<%> ok?] method
+ of the object returns @scheme[#f].
+
+@defconstructor[([parent (or/c (is-a?/c frame%) (is-a?/c dialog%) false/c) #f])]{
+
+If @scheme[parent] is not @scheme[#f], it is used as the parent window
+ of the configuration dialog.
+
+
+}}
+
diff --git a/collects/scribblings/gui/ps-setup-class.scrbl b/collects/scribblings/gui/ps-setup-class.scrbl
new file mode 100644
index 0000000000..eaf4462122
--- /dev/null
+++ b/collects/scribblings/gui/ps-setup-class.scrbl
@@ -0,0 +1,273 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[ps-setup% object% ()]{
+
+A @scheme[ps-setup%] object contains configuration information for
+ producing PostScript files using a @scheme[post-script-dc%] object.
+ To a lesser extent, it contains information for printing with a
+ @scheme[printer-dc%] object.
+
+When a @scheme[post-script-dc%] object is created, its configuration
+ is determined by the @scheme[current-ps-setup] parameter's
+ @scheme[ps-setup%] value. After a @scheme[post-script-dc%] object is
+ created, it is unaffected by changes to the @scheme[current-ps-setup]
+ parameter or mutations to the @scheme[ps-setup%] object.
+
+
+@defconstructor[()]{
+
+Creates a new @scheme[ps-setup%] object with the (platform-specific)
+ default configuration.
+
+}
+
+@defmethod[(copy-from [source (is-a?/c ps-setup%)])
+ void?]{
+
+Copies the settings @scheme[copy-from] to @this-obj[].
+
+}
+
+@defmethod[(get-command)
+ string?]{
+
+Gets the printer command used to print a file in X. The default is
+ @scheme["lpr"]. This value is not used by other platforms.
+
+}
+
+@defmethod[(get-editor-margin [h-margin (box/c nonnegative-real?)]
+ [v-margin (box/c nonnegative-real?)])
+ void?]{
+
+Returns the current settings for horizontal and vertical margins when
+ printing an @scheme[editor<%>]. See also @method[ps-setup%
+ set-editor-margin].
+
+}
+
+@defmethod[(get-file)
+ (or/c path-string? false/c)]{
+
+Gets the PostScript output filename. A @scheme[#f] value (the default)
+ indicates that the user should be prompted for a filename when a
+ @scheme[post-script-dc%] object is created.
+
+}
+
+@defmethod[(get-level-2)
+ boolean?]{
+
+Reports whether Level 2 commands are output in PostScript files.
+
+Currently, Level 2 commands are only needed to include color bitmap
+ images in PostScript output (drawn with @method[dc<%> draw-bitmap]),
+ or bitmap pen and brush stipples. When Level 2 commands are disabled,
+ bitmaps are converted to grayscale images and stipples are not
+ supported.
+
+}
+
+@defmethod[(get-margin [h-margin (box/c nonnegative-real?)]
+ [v-margin (box/c nonnegative-real?)])
+ void?]{
+
+Returns the current settings for horizontal and vertical PostScript
+ margins. See also @method[ps-setup% set-margin].
+
+}
+
+@defmethod[(get-mode)
+ (one-of/c 'preview 'file 'printer)]{
+
+Gets the printing mode that determines where output is sent:
+ @scheme['preview], @scheme['file], or @scheme['printer]. The default
+ for X is @scheme['preview]. The value in Windows and Mac OS X is
+ always @scheme['file].
+
+}
+
+@defmethod[(get-orientation)
+ (one-of/c 'portrait 'landscape)]{
+
+Gets the orientation: @scheme['portrait] or @scheme['landscape]. The
+ default is @scheme['portrait]. Unlike most other settings, this one
+ affects native printing (via @scheme[printer-dc%]) as well as
+ PostScript output.
+
+Landscaped orientation affects the size of the drawing area as
+ reported by @method[dc<%> get-size]: the horizontal and vertical
+ sizes determined by the selected paper type are transposed and then
+ scaled.
+
+}
+
+@defmethod[(get-paper-name)
+ string?]{
+
+Returns the name of the current paper type: @scheme["A4 210 x 297
+ mm"], @scheme["A3 297 x 420 mm"], @scheme["Letter 8 1/2 x 11 in"], or
+ @scheme["Legal 8 1/2 x 14 in"]. The default is @scheme["Letter 8 1/2
+ x 11 in"].
+
+The paper name determines the size of the drawing area as reported by
+ @method[dc<%> get-size] (along with landscape transformations from
+ @method[ps-setup% get-orientation] and/or the scaling factors of
+ @method[ps-setup% get-scaling]). It also determines the bounding box
+ of PostScript output when a @scheme[post-script-dc%] context is
+ created with a true value for the @scheme[use-paper-bbox?]
+ initialization argument.
+
+}
+
+@defmethod[(get-preview-command)
+ string?]{
+
+Gets the command used to view a PostScript file for X. The default is
+ @scheme["gv"]. This value is not used by other platforms.
+
+}
+
+@defmethod[(get-scaling [x (box/c nonnegative-real?)]
+ [y (box/c nonnegative-real?)])
+ void?]{
+
+Gets the scaling factor for PostScript output. @boxisfill[(scheme x)
+ @elem{the horizontal scaling factor}] @boxisfill[(scheme y) @elem{the
+ vertical scaling factor}] The default is @scheme[0.8] by
+ @scheme[0.8].
+
+This scale is in addition to a scale that can be set by @method[dc<%>
+ set-scale] in a @scheme[post-script-dc%] context. The size reported
+ by @method[dc<%> get-size] is the size of the selected paper type
+ (transposed for landscaped mode) divided by this scale.
+
+}
+
+@defmethod[(get-translation [x (box/c nonnegative-real?)]
+ [y (box/c nonnegative-real?)])
+ void?]{
+
+Gets the translation (from the bottom left corner) for PostScript
+ output. @boxisfill[@scheme[x] @elem{the horizontal offset}]
+ @boxisfill[@scheme[y] @elem{the vertical offset}] The default is
+ @scheme[0.0] and @scheme[0.0].
+
+The translation is not scaled by the numbers returned from
+ @method[ps-setup% get-scaling] and the translation does not affect
+ the size of the drawing area.
+
+}
+
+@defmethod[(set-command [command string?])
+ void?]{
+
+Sets the printer command used to print a file under X. See
+ @method[ps-setup% get-command].
+
+}
+
+@defmethod[(set-editor-margin [h nonnegative-exact-integer?]
+ [v nonnegative-exact-integer?])
+ void?]{
+
+Sets the horizontal and vertical margins used when printing an editor
+ with the @method[editor<%> print] method. These margins are always
+ used for printing, whether the drawing destination is a
+ @scheme[post-script-dc%] or @scheme[printer-dc%]. The margins are in
+ the units of the destination @scheme[printer-dc%] or
+ @scheme[post-script-dc%]. In the case of @scheme[post-script-dc%]
+ printing, the editor margin is in addition to the PostScript margin
+ that is determined by @method[ps-setup% set-margin].
+
+}
+
+@defmethod[(set-file [filename (or/c path-string? false/c)])
+ void?]{
+
+Sets the PostScript output filename. See
+ @method[ps-setup% get-file].
+
+}
+
+@defmethod[(set-level-2 [on? any/c])
+ void?]{
+
+Sets whether Level 2 commands are output in PostScript files. See
+ @method[ps-setup% get-level-2].
+
+}
+
+@defmethod[(set-margin [h (and/c real? (not/c negative?))]
+ [v (and/c real? (not/c negative?))])
+ void?]{
+
+Sets the horizontal and vertical PostScript margins. When drawing to a
+ @scheme[post-script-dc%], the page size reported by @method[dc<%>
+ get-size] subtracts these margins from the normal page area (before
+ taking into account scaling affects). In addition, drawing into the
+ @scheme[post-script-dc%] produces PostScript output that is offset by
+ the margins.
+
+When using the output of a @scheme[post-script-dc%] as
+ Encapsulated PostScript, the margin values are effectively
+ irrelevant. Changing the margins moves the PostScript image in
+ absolute coordinates, but it also moves the bounding box.
+
+The margins are in unscaled @scheme[post-script-dc%] units, which
+ are points. The default margins are 16 points.
+
+}
+
+@defmethod[(set-mode [mode (one-of/c 'preview 'file 'printer)])
+ void?]{
+
+Sets the printing mode controlling where output is sent. See
+ @method[ps-setup% get-mode].
+
+Under Windows and Mac OS X, if @scheme['preview] or @scheme['printer]
+ is provided, @|MismatchExn|.
+
+}
+
+@defmethod[(set-orientation [orientation (one-of/c 'portrait 'landscape)])
+ void?]{
+
+Sets the orientation. See @method[ps-setup% get-orientation].
+
+}
+
+@defmethod[(set-paper-name [type string?])
+ void?]{
+
+Sets the name of the current paper type. See @method[ps-setup%
+ get-paper-name].
+
+}
+
+@defmethod[(set-preview-command [command string?])
+ void?]{
+
+Sets the command used to view a PostScript file under X. See
+@method[ps-setup% get-preview-command].
+
+}
+
+@defmethod[(set-scaling [x (and/c real? (not/c negative?))]
+ [y (and/c real? (not/c negative?))])
+ void?]{
+
+Sets the scaling factor for PostScript output. See
+ @method[ps-setup% get-scaling].
+
+}
+
+@defmethod[(set-translation [x real?]
+ [y real?])
+ void?]{
+
+Sets the translation (from the bottom left corner) for PostScript
+ output. See @method[ps-setup% get-translation].
+
+}}
diff --git a/collects/scribblings/gui/windowing.scrbl b/collects/scribblings/gui/reference.scrbl
similarity index 52%
rename from collects/scribblings/gui/windowing.scrbl
rename to collects/scribblings/gui/reference.scrbl
index 259b682527..de750d2c8f 100644
--- a/collects/scribblings/gui/windowing.scrbl
+++ b/collects/scribblings/gui/reference.scrbl
@@ -1,11 +1,12 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
-@require["diagrams.ss"]
-@title[#:tag "mr:windowing" #:style 'toc]{Windowing Toolbox}
+@title[#:style 'toc]{Reference}
@local-table-of-contents[]
-@include-section["win-overview.scrbl"]
@include-section["win-classes.scrbl"]
@include-section["win-funcs.scrbl"]
+@include-section["draw-classes.scrbl"]
+@include-section["draw-funcs.scrbl"]
+@include-section["editor-classes.scrbl"]
diff --git a/collects/scribblings/gui/region-class.scrbl b/collects/scribblings/gui/region-class.scrbl
new file mode 100644
index 0000000000..380330b6d2
--- /dev/null
+++ b/collects/scribblings/gui/region-class.scrbl
@@ -0,0 +1,268 @@
+#reader(lib "defreader.ss" "scribble")
+@require["common.ss"]
+
+@defclass[region% object% ()]{
+
+A @scheme[region%] object specifies a portion of a drawing area
+ (possibly discontinuous). It is normally used for clipping drawing
+ operations.
+
+Each @scheme[region%] object is associated to a particular
+ @scheme[dc<%>] object, specified when the region is created. A region
+ can only be used with its associated @scheme[dc<%>] object. The origin
+ and scale of a drawing context determine the bounding box and drawing
+ location of a region at the time that a region is created (or set); a
+ region is independent of the current scale and origin when the region
+ is used. For an auto-scrolled canvas, the canvas's current scrolling
+ applies when the region is used (and it does not affect the region's
+ bounding box).
+
+See also @xmethod[dc<%> set-clipping-region] and @xmethod[dc<%>
+ get-clipping-region].
+
+
+@defconstructor[([dc (is-a?/c dc<%>)])]{
+
+Creates an empty region.
+
+}
+
+@defmethod[(get-bounding-box)
+ (values real? real? real? real?)]{
+
+Returns a rectangle that encloses the region. The return values are
+ the left, top, width, and height of the rectangle. The bounding box
+ is precisely correct for unsmoothed drawing, but it is only
+ approximate for smoothed drawing.
+
+}
+
+@defmethod[(get-dc)
+ (is-a?/c dc<%>)]{
+
+Returns the region's drawing context.
+
+}
+
+@defmethod[(in-region? [x real?]
+ [y real?])
+ boolean?]{
+
+Returns @scheme[#t] if the given point is approximately within the
+ region, @scheme[#f] otherwise. The given point is scaled and
+ translated according to the region's @scheme[dc<%>]'s current scale
+ and translation.
+
+The approximate in-region test represents the true result for
+ unsmoothed drawing, but it not necessarily for smoothed drawing.
+
+}
+
+@defmethod[(intersect [rgn (is-a?/c region%)])
+ void?]{
+
+Sets the region to the intersection of itself with the given region.
+
+The DC of @scheme[rgn] and @this-obj[] must be the same.
+
+The result is always reliable for unsmoothed and smoothed drawing. For
+ smoothed drawing, an intersect corresponds to clipping with this
+ region's path, and then clipping with the given region's path.
+ Further combining sends to this region correspond to combination with
+ the original path before initial clip, and further combination with
+ this region as an argument correspond to a combination with the given
+ path after the initial clip. Thus, an intersecting region is a poor
+ input for @method[region% union], @method[region% subtract], or
+ @method[region% xor], but it intersects properly in further calls to
+ @method[region% intersect].
+
+}
+
+@defmethod[(is-empty?)
+ boolean?]{
+
+Returns @scheme[#t] if the region is approximately empty, @scheme[#f]
+ otherwise. An approximately empty region is truly empty for
+ unsmoothed drawing, but it may contain points for smoothed drawing.
+
+}
+
+@defmethod[(set-arc [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))]
+ [start-radians real?]
+ [end-radians real?])
+ void?]{
+
+Sets the region to the interior of the specified wedge.
+
+See also @xmethod[dc<%> draw-ellipse], since the region content is
+ determined the same way as brush-based filling in a @scheme[dc<%>].
+
+The result is reliable for both unsmoothed and smoothed drawing. For
+ smoothed drawing, the region corresponds to a clockwise path with a
+ @scheme['winding] fill. The region is also @defterm{atomic} for the
+ purposes of region combination.
+
+}
+
+@defmethod[(set-ellipse [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))])
+ void?]{
+
+Sets the region to the interior of the specified ellipse.
+
+See also @xmethod[dc<%> draw-ellipse], since the region content is
+ determined the same way as brush-based filling in a @scheme[dc<%>].
+
+The result is reliable for both unsmoothed and smoothed drawing. For
+ smoothed drawing, the region corresponds to a clockwise path with a
+ @scheme['winding] fill. The region is also @defterm{atomic} for the
+ purposes of region combination.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(set-path [path (is-a?/c dc-path%)]
+ [xoffset real? 0]
+ [yoffset real? 0]
+ [fill-style (one-of/c 'odd-even 'winding) 'odd-even])
+ void?]{
+
+Sets the region to the content of the given path.
+
+See also @xmethod[dc<%> draw-path], since the region content is
+ determined the same way as brush-based filling in a @scheme[dc<%>].
+
+The result is reliable for both unsmoothed and smoothed drawing. For
+ smoothed drawing, the fill style affects how well the region reliably
+ combines with other regions (via @method[region% union],
+ @method[region% xor], and @method[region% subtract]). The region is
+ also @defterm{atomic} for the purposes of region combination.
+
+}
+
+@defmethod[(set-polygon [points (listof (is-a?/c point%))]
+ [xoffset real? 0]
+ [yoffset real? 0]
+ [fill-style (one-of/c 'odd-even 'winding) 'odd-even])
+ void?]{
+Sets the region to the interior of the specified polygon.
+
+See also @xmethod[dc<%> draw-polygon], since the region content is
+ determined the same way as brush-based filling in a @scheme[dc<%>].
+
+The result is reliable for both unsmoothed and smoothed drawing. For
+ smoothed drawing, the fill style affects how well the region reliably
+ combines with other regions (via @method[region% union],
+ @method[region% xor], and @method[region% subtract]). The region is
+ also @defterm{atomic} for the purposes of region combination.
+
+}
+
+@defmethod[(set-rectangle [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))])
+ void?]{
+
+Sets the region to the interior of the specified rectangle.
+
+See also @xmethod[dc<%> draw-rectangle], since the region content is
+ determined the same way as brush-based filling in a @scheme[dc<%>].
+
+The result is reliable for both unsmoothed and smoothed drawing. For
+ smoothed drawing, the region corresponds to a clockwise path with a
+ @scheme['winding] fill. The region is also @defterm{atomic} for the
+ purposes of region combination.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(set-rounded-rectangle [x real?]
+ [y real?]
+ [width (and/c real? (not/c negative?))]
+ [height (and/c real? (not/c negative?))]
+ [radius real? -0.25])
+ void?]{
+
+Sets the region to the interior of the specified rounded rectangle.
+
+See also @xmethod[dc<%> draw-rounded-rectangle], since the region
+ content is determined the same way as brush-based filling in a
+ @scheme[dc<%>].
+
+The result is reliable for both unsmoothed and smoothed drawing. For
+ smoothed drawing, the region corresponds to a clockwise path with a
+ @scheme['winding] fill. The region is also @defterm{atomic} for the
+ purposes of region combination.
+
+@|DrawSizeNote|
+
+}
+
+@defmethod[(subtract [rgn (is-a?/c region%)])
+ void?]{
+
+Sets the region to the subtraction of itself minus the given region.
+ In other words, a point is removed from the region if it is included
+ in the given region. (The given region may contain points that are
+ not in the current region; such points are ignored.)
+
+This region's DC and given region's DC must be the same.
+
+The result is always reliable for unsmoothed drawing. For smoothed
+ drawing, the result is consistent across platforms and devices, but
+ it is never a true subtraction. A subtraction corresponds to
+ combining the sub-paths of this region with the reversed sub-paths of
+ the given region, then intersecting the result with this region. This
+ fails as a true subtraction, because the boundary of loops (with
+ either @scheme['odd-even] or @scheme['winding] filling) is ambiguous.
+
+}
+
+@defmethod[(union [rgn (is-a?/c region%)])
+ void?]{
+
+Sets the region to the union of itself with the given region.
+
+This region's DC and given region's DC must be the same.
+
+The result is always reliable for unsmoothed drawing. For smoothed
+ drawing, a union corresponds to combining the sub-paths of each
+ region into one path, using an @scheme['odd-even] fill if either of
+ the region uses an @scheme['odd-even] fill (otherwise using a
+ @scheme['winding] fill). Consequently, while the result is consistent
+ across platforms and devices, it is a true union only for certain
+ input regions. For example, it is a true union for non-overlapping
+ atomic and union regions. It is also a true union for atomic and
+ union regions (potentially overlapping) that are all clockwise and
+ use @scheme['winding] fill.
+
+}
+
+@defmethod[(xor [rgn (is-a?/c region%)])
+ void?]{
+
+Sets the region to the xoring of itself with the given region (i.e.,
+ contains points that are enclosed by exactly one of the two regions).
+
+This region's DC and given region's DC must be the same.
+
+The result is always reliable for unsmoothed drawing. For smoothed
+ drawing, the result is consistent across platforms and devices, but
+ it is not necessarily a true xoring. An xoring corresponds to
+ combining the sub-paths of this region with the reversed sub-paths of
+ the given region. The result uses an @scheme['odd-even] fill if either
+ of the region uses an @scheme['odd-even] fill (otherwise using a
+ @scheme['winding] fill). Consequently, the result is a reliable xoring
+ only for certain input regions. For example, it is reliable for
+ atomic and xoring regions that all use @scheme['even-odd] fill.
+
+}}
+
diff --git a/collects/scribblings/gui/win-funcs.scrbl b/collects/scribblings/gui/win-funcs.scrbl
index c671b756e6..88ae8af9eb 100644
--- a/collects/scribblings/gui/win-funcs.scrbl
+++ b/collects/scribblings/gui/win-funcs.scrbl
@@ -1,7 +1,7 @@
#reader(lib "docreader.ss" "scribble")
@require["common.ss"]
-@title[#:style 'toc]{Windowing Function Reference}
+@title{Windowing Function Reference}
@local-table-of-contents[]
diff --git a/collects/scribblings/gui/win-overview.scrbl b/collects/scribblings/gui/win-overview.scrbl
index 0f6a0bf06d..1668159975 100644
--- a/collects/scribblings/gui/win-overview.scrbl
+++ b/collects/scribblings/gui/win-overview.scrbl
@@ -3,9 +3,7 @@
@require["common.ss"]
@require["diagrams.ss"]
-@title[#:tag "mr:windowing-overview" #:style 'toc]{Windowing Toolbox Overview}
-
-@local-table-of-contents[]
+@title[#:tag "mr:windowing-overview"]{Windowing Guide}
@section{Basic GUI Building Blocks}
diff --git a/collects/tests/mzscheme/filelib.ss b/collects/tests/mzscheme/filelib.ss
index fa83b2c688..511ebac9d6 100644
--- a/collects/tests/mzscheme/filelib.ss
+++ b/collects/tests/mzscheme/filelib.ss
@@ -21,9 +21,9 @@
(current-directory))
(let ([rel2 (fold-files (lambda (name kind accum)
- (test kind values (if (file-exists? name)
- 'file
- 'dir))
+ (test kind name (if (file-exists? name)
+ 'file
+ 'dir))
(cons name accum))
null)]
[sort (lambda (l)
@@ -41,9 +41,10 @@
(test kind values (cond
[(link-exists? name) 'link]
[(file-exists? name) 'file]
- [else 'dir]))
+ [(dir-exists? name) 'dir]
+ [else '???]))
(when (member name '("filelib-link.ss" "loop-link"))
- (test kind values 'link))
+ (test kind name 'link))
(add1 accum))
0
#f
@@ -58,7 +59,7 @@
[(file-exists? name) 'file]
[else 'dir]))
(when (member name '("filelib-link.ss"))
- (test kind values 'file))
+ (test kind name 'file))
(add1 accum))
0
#f