Delegated gc stuff delegated_gc
authorStefan Vogel <sv@exept.de>
Thu, 08 May 2014 10:27:51 +0200
branchdelegated_gc
changeset 6472 5b21ff383a12
parent 6247 de34d2e94da1
child 6485 14afc96826c4
Delegated gc stuff
DeviceGraphicsContext.st
DeviceHandle.st
DisplayRootView.st
DisplaySurface.st
Form.st
GraphicsContext.st
GraphicsMedium.st
SimpleView.st
StandardSystemView.st
WindowSensor.st
XWorkstation.st
XftFontDescription.st
--- a/DeviceGraphicsContext.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/DeviceGraphicsContext.st	Thu May 08 10:27:51 2014 +0200
@@ -9,15 +9,32 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 08-05-2014 at 10:06:55'                   !
+
 "{ Package: 'stx:libview' }"
 
 GraphicsContext subclass:#DeviceGraphicsContext
-	instanceVariableNames:'drawableId gcId deviceFont foreground background'
+	instanceVariableNames:'drawableId gcId deviceFont foreground background drawableType
+		parentId'
 	classVariableNames:'CachedScaledForms CachedScales Lobby'
 	poolDictionaries:''
 	category:'Graphics-Support'
 !
 
+DeviceHandle subclass:#DevicePixmapGCHandle
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:DeviceGraphicsContext
+!
+
+DeviceHandle subclass:#DeviceWindowGCHandle
+	instanceVariableNames:'parentId'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:DeviceGraphicsContext
+!
+
 !DeviceGraphicsContext class methodsFor:'documentation'!
 
 copyright
@@ -37,21 +54,21 @@
 documentation
 "
     I provide the common protocol for a graphicsContext which is associated with a particular
-    device (i.e. Bitmaps, Pixmaps, RootWindow and Windows in Xs world, but also postscript 
+    device (i.e. Bitmaps, Pixmaps, RootWindow and Windows in Xs world, but also postscript
     printer pages or fax pages).
 
     My instance variables are mainly caching device-related stuff (such as font- and color-Ids)
     to avoid needless message traffic. This class is abstract, no direct instances of it
     exist in the system.
     All real work is done by my device, which is accessed via the device instance variable.
-    Most drawing requests are simply forwarded to it, others are simulated by using more basic 
+    Most drawing requests are simply forwarded to it, others are simulated by using more basic
     drawing functions (see GraphicsContext drawing vs. basic drawing category).
 
-    The added variables foreground/background are the drawing colors actually 
+    The added variables foreground/background are the drawing colors actually
     used; these are the real (i.e. non dithered) colors supported by the device.
-    Direct access to fg/bg is discouraged, since in the future, these may be 
-    totally replaced by paint/bgPaint 
-    (there are some operations and special cases, for which a direct access to 
+    Direct access to fg/bg is discouraged, since in the future, these may be
+    totally replaced by paint/bgPaint
+    (there are some operations and special cases, for which a direct access to
      fg/bg makes sense)
 
     [Instance variables:]
@@ -80,7 +97,7 @@
 
 initialize
     Lobby isNil ifTrue:[
-        Lobby := Registry new.
+	Lobby := Registry new.
     ]
 
     "Modified: / 29.1.1998 / 12:56:12 / cg"
@@ -96,6 +113,16 @@
 "
     'Warning: DeviceGraphicsContext (' print. self name print. ') should not be created with new' printNL.
 "
+    |device|
+
+    device := Screen current.
+    device isNil ifTrue:[
+	device := Display.
+	device isNil ifTrue:[
+	    (self class name,' [warning]: no Display') infoPrintCR.
+	    Smalltalk openDisplay.
+	].
+    ].
     ^ self onDevice:Screen current "Display"
 !
 
@@ -122,7 +149,7 @@
     newDrawable := self basicNew.
 
     "
-     set display before its initialized 
+     set display before its initialized
      - so it can do something useful (i.e. get font sizes etc.) in its
      intitialize method(s)
     "
@@ -136,7 +163,7 @@
 !DeviceGraphicsContext class methodsFor:'cleanup'!
 
 cleanupLobbyForChildrenOfViewWithDevice:aDevice id:anId
-    "clean all the subcomponents of the handle with id anId.
+    "recursively clean all the subcomponents of the handle with id anId.
      This must be done on finalization, because descendent handles
      are destroyed implicitly when a parent handle is destroyed."
 
@@ -145,17 +172,17 @@
     parents := Array with:anId address.
 
     [
-        newChildren := Set new.
-        Lobby unregisterAllForWhichHandle:[:handle | 
-            |parentId|
-
-            (handle notNil 
-                and:[handle device == aDevice
-                and:[(parentId := handle parentId) notNil 
-                and:[parents includes:parentId]]]
-            ) ifTrue:[newChildren add:handle id. true] ifFalse:[false]
-        ].
-        parents := newChildren.
+	newChildren := Set new.
+	Lobby unregisterAllForWhichHandle:[:handle |
+	    |parentId|
+
+	    (handle notNil
+		and:[handle device == aDevice
+		and:[(parentId := handle parentId) notNil
+		and:[parents includes:parentId]]]
+	    ) ifTrue:[newChildren add:handle id. true] ifFalse:[false]
+	].
+	parents := newChildren.
     ] doWhile:[parents notEmpty].
 !
 
@@ -257,22 +284,22 @@
      operations"
 
     (aColor ~~ bgPaint) ifTrue:[
-        aColor notNil ifTrue:[
-            bgPaint := aColor.
-            gcId notNil ifTrue:[
-                bgPaint isColor ifTrue:[
-                    bgPaint := aColor onDevice:device.
-                    bgPaint colorId notNil ifTrue:[
-                        background := bgPaint.
-                        gcId notNil ifTrue:[
-                            device setBackground:(bgPaint colorId) in:gcId.
-                        ].
-                        ^ self
-                    ]
-                ].
-                self paint:paint on:aColor
-            ]
-        ]
+	aColor notNil ifTrue:[
+	    bgPaint := aColor.
+	    gcId notNil ifTrue:[
+		bgPaint isColor ifTrue:[
+		    bgPaint := aColor onDevice:device.
+		    bgPaint colorId notNil ifTrue:[
+			background := bgPaint.
+			gcId notNil ifTrue:[
+			    device setBackground:(bgPaint colorId) in:gcId.
+			].
+			^ self
+		    ]
+		].
+		self paint:paint on:aColor
+	    ]
+	]
     ].
 !
 
@@ -292,19 +319,19 @@
     |id|
 
     (aFont ~~ font) ifTrue:[
-        aFont notNil ifTrue:[
-            font := aFont.
-            device notNil ifTrue:[
-                font := font onDevice:device.
-                gcId notNil ifTrue:[
-                    id := font fontId.
-                    id notNil ifTrue:[
-                        deviceFont := font.
-                        device setFont:id in:gcId
-                    ]
-                ]
-            ]
-        ]
+	aFont notNil ifTrue:[
+	    font := aFont.
+	    device notNil ifTrue:[
+		font := font onDevice:device.
+		gcId notNil ifTrue:[
+		    id := font fontId.
+		    id notNil ifTrue:[
+			deviceFont := font.
+			device setFont:id in:gcId
+		    ]
+		]
+	    ]
+	]
     ]
 
     "Created: / 23-02-1996 / 17:16:51 / cg"
@@ -324,7 +351,7 @@
     (s ~~ capStyle) ifTrue:[
 	capStyle := s.
 	gcId notNil ifTrue:[
-	    device setLineWidth:lineWidth 
+	    device setLineWidth:lineWidth
 			  style:lineStyle
 			    cap:s
 			   join:joinStyle
@@ -353,7 +380,7 @@
     |rect|
 
     (rect := clipRect) isNil ifTrue:[
-        rect := 0@0 extent:(self extent).
+	rect := 0@0 extent:(self extent).
     ].
 "/ nope - it is already kept in logical coordinates
 "/    transformation notNil ifTrue:[
@@ -376,11 +403,6 @@
     ].
     device noClipIn:drawableId gc:gcId.
     device setClipByChildren:aBoolean in:drawableId gc:gcId.
-"/    device noClipIn:drawableId gc:gcId.
-
-"/
-"/    device setClipX:0 y:0 width:(self width) height:(self height) in:drawableId gc:gcId.
-"/
 
     "Created: 17.7.1996 / 13:25:16 / cg"
     "Modified: 29.4.1997 / 15:33:55 / dq"
@@ -390,101 +412,52 @@
     "set the clipping rectangle for drawing (in logical coordinates);
      a nil argument turn off clipping (i.e. whole view is drawable)"
 
-    |x y w h r|
-
-    (r := aRectangleOrNil) isNil ifTrue:[
+    |x y w h newBounds|
+
+    aRectangleOrNil isNil ifTrue:[
         clipRect isNil ifTrue:[^ self].
         gcId notNil ifTrue:[
             device noClipIn:drawableId gc:gcId
-        ]
-    ] ifFalse:[
-        clipRect notNil ifTrue:[
-            (clipRect = aRectangleOrNil) ifTrue:[^ self]
         ].
-        gcId notNil ifTrue:[
-            x := aRectangleOrNil left.
-            y := aRectangleOrNil top.
-            w := aRectangleOrNil width.
-            h := aRectangleOrNil height.
-            transformation notNil ifTrue:[
-                x := transformation applyToX:x.
-                y := transformation applyToY:y.
-                w := transformation applyScaleX:w.
-                h := transformation applyScaleY:h.
-            ].
-            (x class == SmallInteger) ifFalse:[
-                w := w + (x - x truncated).
-                x := x truncated
-            ].
-            (y class == SmallInteger) ifFalse:[
-                h := h + (y - y truncated).
-                y := y truncated
-            ].
-            (w class == SmallInteger) ifFalse:[
-                w := w truncated + 1
-            ].
-            (h class == SmallInteger) ifFalse:[
-                h := h truncated + 1
-            ].
-            w := w max:0.
-            h := h max:0.
-            device setClipX:x y:y width:w height:h in:drawableId gc:gcId.
-            r := Rectangle left:x top:y width:w height:h
-        ]
+        clipRect := nil.
+        ^ self.
+    ].
+
+    x := aRectangleOrNil left.
+    y := aRectangleOrNil top.
+    w := aRectangleOrNil width.
+    h := aRectangleOrNil height.
+    transformation notNil ifTrue:[
+        x := transformation applyToX:x.
+        y := transformation applyToY:y.
+        w := transformation applyScaleX:w.
+        h := transformation applyScaleY:h.
+    ].
+    (x class == SmallInteger) ifFalse:[
+        w := w + (x - x truncated).
+        x := x truncated
     ].
-    clipRect := r
-
-    "Created: / 28.5.1996 / 19:40:20 / cg"
-    "Modified: / 16.5.1999 / 19:40:37 / cg"
-!
-
-clippingRectangle:aRectangleOrNil
-    "set the clipping rectangle for drawing (in logical coordinates);
-     a nil argument turn off clipping (i.e. whole view is drawable)"
-
-    |x y w h r|
-
-    (r := aRectangleOrNil) isNil ifTrue:[
-        clipRect isNil ifTrue:[^ self].
-        gcId notNil ifTrue:[
-            device noClipIn:drawableId gc:gcId
-        ]
-    ] ifFalse:[
-        clipRect notNil ifTrue:[
-            (clipRect = aRectangleOrNil) ifTrue:[^ self]
-        ].
-        gcId notNil ifTrue:[
-            x := aRectangleOrNil left.
-            y := aRectangleOrNil top.
-            w := aRectangleOrNil width.
-            h := aRectangleOrNil height.
-            transformation notNil ifTrue:[
-                x := transformation applyToX:x.
-                y := transformation applyToY:y.
-                w := transformation applyScaleX:w.
-                h := transformation applyScaleY:h.
-            ].
-            (x class == SmallInteger) ifFalse:[
-                w := w + (x - x truncated).
-                x := x truncated
-            ].
-            (y class == SmallInteger) ifFalse:[
-                h := h + (y - y truncated).
-                y := y truncated
-            ].
-            (w class == SmallInteger) ifFalse:[
-                w := w truncated + 1
-            ].
-            (h class == SmallInteger) ifFalse:[
-                h := h truncated + 1
-            ].
-            w := w max:0.
-            h := h max:0.
-            device setClipX:x y:y width:w height:h in:drawableId gc:gcId.
-            r := Rectangle left:x top:y width:w height:h
-        ]
+    (y class == SmallInteger) ifFalse:[
+        h := h + (y - y truncated).
+        y := y truncated
+    ].
+    (w class == SmallInteger) ifFalse:[
+        w := w truncated + 1
+    ].
+    (h class == SmallInteger) ifFalse:[
+        h := h truncated + 1
     ].
-    clipRect := r
+    w := w max:0.
+    h := h max:0.
+
+    newBounds := Rectangle left:x top:y width:w height:h.
+    (clipRect notNil and:[clipRect = newBounds]) ifTrue:[
+        ^ self
+    ].
+    clipRect := newBounds.
+    gcId notNil ifTrue:[
+        device setClipX:x y:y width:w height:h in:drawableId gc:gcId.
+    ].
 
     "Created: / 28.5.1996 / 19:40:20 / cg"
     "Modified: / 16.5.1999 / 19:40:37 / cg"
@@ -505,7 +478,7 @@
 
     pixel := self atX:x y:y.
     device getScaledRGBFrom:pixel into:[:r :g :b |
-        ^ Color scaledRed:r scaledGreen:g scaledBlue:b
+	^ Color scaledRed:r scaledGreen:g scaledBlue:b
     ].
 
     "Created: 1.8.1997 / 20:01:32 / cg"
@@ -520,7 +493,7 @@
 dashStyle:aDashList offset:dashOffset
     "define dashes. Each element of the dashList specifies the length
      of a corresponding dash. For example, setting it to [4 4]
-     defines 4on-4off dashing; 
+     defines 4on-4off dashing;
      Setting it to [1 2 4 2] defines 1on-2off-4on-2off dashes.
      The dashOffset specifies where in the dashList the dashing starts.
      This may not be supported by all graphics devices."
@@ -546,35 +519,54 @@
     device := aDevice
 !
 
-deviceClippingRectangle:aRectangleOrNil
+deviceClippingBounds:aRectangleOrNil
     "set the clipping rectangle for drawing (in device coordinates);
      a nil argument turns off clipping (i.e. whole view is drawable - incl. margins)"
 
-    |x y w h|
+    clipRect = aRectangleOrNil ifTrue:[
+        ^ self
+    ].
+    clipRect := aRectangleOrNil.
+
+    gcId isNil ifTrue:[
+        ^ self.
+    ].
 
     aRectangleOrNil isNil ifTrue:[
-        clipRect isNil ifTrue:[^ self].
-        gcId notNil ifTrue:[
-            device noClipIn:drawableId gc:gcId
-        ]
+        device noClipIn:drawableId gc:gcId
     ] ifFalse:[
-        clipRect notNil ifTrue:[
-            (clipRect = aRectangleOrNil) ifTrue:[^ self]
-        ].
-        gcId notNil ifTrue:[
-            x := aRectangleOrNil left.
-            y := aRectangleOrNil top.
-            w := aRectangleOrNil width.
-            h := aRectangleOrNil height.
-            device setClipX:x y:y width:w height:h in:drawableId gc:gcId
-        ]
+        device setClipX:aRectangleOrNil left 
+                    y:aRectangleOrNil top 
+                    width:aRectangleOrNil width 
+                    height:aRectangleOrNil height 
+                    in:drawableId
+                    gc:gcId
     ].
-    clipRect := aRectangleOrNil
 
     "Modified: / 22.5.1996 / 13:12:07 / cg"
     "Created: / 14.9.1998 / 18:50:31 / cg"
 !
 
+deviceClippingBoundsOrNil
+    "get the clipping rectangle for drawing (in device coordinates);
+     a nil clipping rectangle means: no clipping (i.e. whole view is drawable - incl. margins)"
+
+    ^ clipRect
+!
+
+deviceClippingRectangle
+    <resource: #obsolete>
+    "get the clipping rectangle for drawing (in device coordinates);
+     a nil clipping rectangle means: no clipping (i.e. whole view is drawable - incl. margins)"
+
+    ^ clipRect
+!
+
+deviceClippingRectangle:aRectangleOrNil
+    <resource: #obsolete>
+    self deviceClippingBounds:aRectangleOrNil
+!
+
 drawableId
     "return the id of the drawable on the device"
 
@@ -586,7 +578,7 @@
      the GC is realized."
 
     device notNil ifTrue:[
-        font := font onDevice:device
+	font := font onDevice:device
     ].
     ^ font
 !
@@ -598,7 +590,6 @@
 
     (aFont ~~ font) ifTrue:[
         self basicFont:aFont.
-        self changed:#font.
     ]
 
     "Modified: 6.3.1996 / 18:17:40 / cg"
@@ -647,9 +638,9 @@
     ].
     (s ~~ joinStyle) ifTrue:[
 	joinStyle := s.
-        
+
 	gcId notNil ifTrue:[
-	    device setLineWidth:lineWidth 
+	    device setLineWidth:lineWidth
 			  style:lineStyle
 			    cap:capStyle
 			   join:s
@@ -668,17 +659,17 @@
     |s|
 
     (s := aSymbol) isNil ifTrue:[
-        s := #solid
+	s := #solid
     ].
     (s ~~ lineStyle) ifTrue:[
-        lineStyle := s.
-        gcId notNil ifTrue:[
-            device setLineWidth:lineWidth 
-                          style:s
-                            cap:capStyle
-                           join:joinStyle
-                             in:gcId
-        ]
+	lineStyle := s.
+	gcId notNil ifTrue:[
+	    device setLineWidth:lineWidth
+			  style:s
+			    cap:capStyle
+			   join:joinStyle
+			     in:gcId
+	]
     ]
 
     "Modified: 12.5.1996 / 22:21:25 / cg"
@@ -698,7 +689,7 @@
 	    n := n rounded
 	].
 	gcId notNil ifTrue:[
-	    device setLineWidth:n 
+	    device setLineWidth:n
 			  style:lineStyle
 			    cap:capStyle
 			   join:joinStyle
@@ -741,18 +732,18 @@
     (maskOrigin isNil or:[
      ((x ~= maskOrigin x) or:[y ~= maskOrigin y]) ]) ifTrue:[
 
-        maskOrigin := aPoint.
-
-        transformation notNil ifTrue:[
-            x := transformation applyToX:x.
-            y := transformation applyToY:y.
-        ].
-        x := x rounded.
-        y := y rounded.
-
-        gcId notNil ifTrue:[
-            device setMaskOriginX:x y:y in:gcId
-        ]
+	maskOrigin := aPoint.
+
+	transformation notNil ifTrue:[
+	    x := transformation applyToX:x.
+	    y := transformation applyToY:y.
+	].
+	x := x rounded.
+	y := y rounded.
+
+	gcId notNil ifTrue:[
+	    device setMaskOriginX:x y:y in:gcId
+	]
     ]
 
     "Created: / 26.1.1998 / 19:03:02 / cg"
@@ -764,11 +755,11 @@
     |x y|
 
     transformation notNil ifTrue:[
-        x := transformation applyToX:orgX.
-        y := transformation applyToY:orgY.
+	x := transformation applyToX:orgX.
+	y := transformation applyToY:orgY.
     ] ifFalse:[
-        x := orgX.
-        y := orgY
+	x := orgX.
+	y := orgY
     ].
     x := x rounded.
     y := y rounded.
@@ -776,10 +767,10 @@
     (maskOrigin isNil or:[
      ((x ~~ maskOrigin x) or:[y ~~ maskOrigin y]) ]) ifTrue:[
 
-        maskOrigin := x @ y.
-        gcId notNil ifTrue:[
-            device setMaskOriginX:x y:y in:gcId
-        ]
+	maskOrigin := x @ y.
+	gcId notNil ifTrue:[
+	    device setMaskOriginX:x y:y in:gcId
+	]
     ]
 
     "Created: / 26.1.1998 / 18:51:18 / cg"
@@ -811,69 +802,69 @@
 !
 
 paint:fgColor on:bgColor
-    "set the paint and background-paint color. 
+    "set the paint and background-paint color.
      The bg-paint is used in opaque-draw operations"
 
     |fgId bgId|
 
     ((fgColor ~~ paint) or:[bgColor ~~ bgPaint]) ifTrue:[
-        fgColor notNil ifTrue:[
-            paint := fgColor
-        ].
-        bgColor notNil ifTrue:[
-            bgPaint := bgColor
-        ].
-        gcId notNil ifTrue:[
-            paint isColor ifTrue:[
-                paint := paint onDevice:device.
-            ].
-            paint isColor ifTrue:[
-                fgId := paint colorId.
-                fgId notNil ifTrue:[
-                    mask notNil ifTrue:[
-                        mask := nil.
-                        device setBitmapMask:nil in:gcId
-                    ]. 
-                    bgPaint isColor ifTrue:[
-                        bgPaint := bgPaint onDevice:device.
-                    ].
-                    bgPaint isColor ifTrue:[
-                        bgId := bgPaint colorId.
-                        bgId notNil ifTrue:[
-                            "the common case, both are real colors"
-                            (paint ~~ foreground) ifTrue:[
-                                foreground := paint.
-                                (bgPaint ~~ background) ifTrue:[
-                                    background := bgPaint.
-                                    device setForeground:fgId background:bgId in:gcId.
-                                    ^ self
-                                ].
-                                device setForeground:fgId in:gcId.
-                                ^ self
-                            ].
-                            (bgPaint ~~ background) ifTrue:[
-                                background := bgPaint.
-                                device setBackground:bgId in:gcId.
-                            ].
-                            ^ self
-                        ].
-                        "bgPaint is dithered, setup paint here, leave bgPaint
-                         till next opaque draw comes around."
-
-                        (paint ~~ foreground) ifTrue:[
-                            foreground := paint.
-                            device setForeground:fgId in:gcId
-                        ].
-                        ^ self
-                    ]
-                ]
-            ].
-            "either paint or bgPaint (or both) are dithered colors,
-             setup for paint, leave bg-problem till next opaque draw
-             comes around.
-            "
-            self setGCForPaint.
-        ]
+	fgColor notNil ifTrue:[
+	    paint := fgColor
+	].
+	bgColor notNil ifTrue:[
+	    bgPaint := bgColor
+	].
+	gcId notNil ifTrue:[
+	    paint isColor ifTrue:[
+		paint := paint onDevice:device.
+	    ].
+	    paint isColor ifTrue:[
+		fgId := paint colorId.
+		fgId notNil ifTrue:[
+		    mask notNil ifTrue:[
+			mask := nil.
+			device setBitmapMask:nil in:gcId
+		    ].
+		    bgPaint isColor ifTrue:[
+			bgPaint := bgPaint onDevice:device.
+		    ].
+		    bgPaint isColor ifTrue:[
+			bgId := bgPaint colorId.
+			bgId notNil ifTrue:[
+			    "the common case, both are real colors"
+			    (paint ~~ foreground) ifTrue:[
+				foreground := paint.
+				(bgPaint ~~ background) ifTrue:[
+				    background := bgPaint.
+				    device setForeground:fgId background:bgId in:gcId.
+				    ^ self
+				].
+				device setForeground:fgId in:gcId.
+				^ self
+			    ].
+			    (bgPaint ~~ background) ifTrue:[
+				background := bgPaint.
+				device setBackground:bgId in:gcId.
+			    ].
+			    ^ self
+			].
+			"bgPaint is dithered, setup paint here, leave bgPaint
+			 till next opaque draw comes around."
+
+			(paint ~~ foreground) ifTrue:[
+			    foreground := paint.
+			    device setForeground:fgId in:gcId
+			].
+			^ self
+		    ]
+		]
+	    ].
+	    "either paint or bgPaint (or both) are dithered colors,
+	     setup for paint, leave bg-problem till next opaque draw
+	     comes around.
+	    "
+	    self setGCForPaint.
+	]
     ]
 
     "Modified: / 31-08-2007 / 10:56:49 / cg"
@@ -888,6 +879,13 @@
     "Modified: 16.5.1996 / 15:36:35 / cg"
 !
 
+setClippingBounds:aRectangleOrNil
+    "set the clipping rectangle for drawing (in physical coordinates.
+     Only set the variable, do not change the gc"
+
+    clipRect := aRectangleOrNil
+!
+
 setGraphicsExposures:aBoolean
     "want to if aBoolean is true - or dont want to be notified
      of graphics exposures"
@@ -895,11 +893,26 @@
     gcId notNil ifTrue:[
 	device setGraphicsExposures:aBoolean in:gcId
     ]
+!
+
+setPaint:fgColor on:bgColor
+    "set the paint and background-paint color.
+     The bg-paint is used in opaque-draw operations.
+     Only set the variables, but do not send it to the device,
+     Used on initialization."
+
+    fgColor notNil ifTrue:[
+	foreground := paint := fgColor
+    ].
+    bgColor notNil ifTrue:[
+	background := bgPaint := bgColor
+    ].
 ! !
 
 !DeviceGraphicsContext methodsFor:'accessing-internals'!
 
 background
+    <resource: #obsolete>
     "return the current background drawing color.
      OBSOLETE: use #paint: / #backgroundPaint: / #paint:on:"
 
@@ -909,37 +922,39 @@
 !
 
 background:aColor
+    <resource: #obsolete>
     "set the internal background color for drawing - aColor must be a real color.
      OBSOLETE: this method will vanish; use #paint: / #backgroundPaint: / #paint:on:"
 
     |bgId|
 
     (aColor ~~ background) ifTrue:[
-        aColor notNil ifTrue:[
-            background := aColor.
-            gcId notNil ifTrue:[
-                background := background onDevice:device.
-                bgId := background colorId.
-
-                "
-                 mhmh the following is a kludge ....
-                "
-                bgId isNil ifTrue:[
-                    (background grayIntensity >= 50) ifTrue:[
-                        bgId := device whitepixel
-                    ] ifFalse:[
-                        bgId := device blackpixel
-                    ]
-                ].
-                device setBackground:bgId in:gcId
-            ]
-        ]
+	aColor notNil ifTrue:[
+	    background := aColor.
+	    gcId notNil ifTrue:[
+		background := background onDevice:device.
+		bgId := background colorId.
+
+		"
+		 mhmh the following is a kludge ....
+		"
+		bgId isNil ifTrue:[
+		    (background grayIntensity >= 50) ifTrue:[
+			bgId := device whitepixel
+		    ] ifFalse:[
+			bgId := device blackpixel
+		    ]
+		].
+		device setBackground:bgId in:gcId
+	    ]
+	]
     ]
 
     "Modified: 28.5.1996 / 20:44:55 / cg"
 !
 
 foreground
+    <resource: #obsolete>
     "return the current foreground drawing color.
      OBSOLETE: use #paint: / #paint:on:"
 
@@ -949,83 +964,86 @@
 !
 
 foreground:aColor
+    <resource: #obsolete>
     "set the internal foreground color for drawing - aColor must be a real color.
      OBSOLETE: this method will vanish; use #paint: / #paint:on:"
 
     |fgId|
 
     (aColor ~~ foreground) ifTrue:[
-        aColor notNil ifTrue:[
-            foreground := aColor.
-            gcId notNil ifTrue:[
-                (foreground class == SmallInteger) ifTrue:[
-                    fgId := foreground
-                ] ifFalse:[
-                    foreground := foreground onDevice:device.
-                    fgId := foreground colorId.
-                ].
-
-                "mhmh the following is a kludge ...."
-                fgId isNil ifTrue:[
-                    (foreground grayIntensity >= 50) ifTrue:[
-                        fgId := device whitepixel
-                    ] ifFalse:[
-                        fgId := device blackpixel
-                    ]
-                ].
-                device setForeground:fgId in:gcId.
-                paint := foreground
-            ]
-        ]
+	aColor notNil ifTrue:[
+	    foreground := aColor.
+	    gcId notNil ifTrue:[
+		(foreground class == SmallInteger) ifTrue:[
+		    fgId := foreground
+		] ifFalse:[
+		    foreground := foreground onDevice:device.
+		    fgId := foreground colorId.
+		].
+
+		"mhmh the following is a kludge ...."
+		fgId isNil ifTrue:[
+		    (foreground grayIntensity >= 50) ifTrue:[
+			fgId := device whitepixel
+		    ] ifFalse:[
+			fgId := device blackpixel
+		    ]
+		].
+		device setForeground:fgId in:gcId.
+		paint := foreground
+	    ]
+	]
     ]
 
     "Modified: 28.5.1996 / 20:45:02 / cg"
 !
 
 foreground:fgColor background:bgColor
-    "set both internal foreground and internal background colors 
+    <resource: #obsolete>
+    "set both internal foreground and internal background colors
      - these must be real colors.
      OBSOLETE: this method will vanish; use #paint: / #paint:on:"
 
     |fgPixel bgPixel|
 
     ((fgColor ~~ foreground) or:[bgColor ~~ background]) ifTrue:[
-        fgColor notNil ifTrue:[
-            foreground := fgColor
-        ].
-        bgColor notNil ifTrue:[
-            background := bgColor
-        ].
-        gcId notNil ifTrue:[
-            foreground := foreground onDevice:device.
-            background := background onDevice:device.
-            fgPixel := foreground colorId.
-            bgPixel := background colorId.
-
-            "mhmh the following is a kludge ...."
-            fgPixel isNil ifTrue:[
-                (foreground grayIntensity >= 50) ifTrue:[
-                    fgPixel := device whitepixel
-                ] ifFalse:[
-                    fgPixel := device blackpixel
-                ]
-            ].
-            bgPixel isNil ifTrue:[
-                (background grayIntensity >= 50) ifTrue:[
-                    bgPixel := device whitepixel
-                ] ifFalse:[
-                    bgPixel := device blackpixel
-                ]
-            ].
-            device setForeground:fgPixel background:bgPixel in:gcId.
-            paint := foreground
-        ]
+	fgColor notNil ifTrue:[
+	    foreground := fgColor
+	].
+	bgColor notNil ifTrue:[
+	    background := bgColor
+	].
+	gcId notNil ifTrue:[
+	    foreground := foreground onDevice:device.
+	    background := background onDevice:device.
+	    fgPixel := foreground colorId.
+	    bgPixel := background colorId.
+
+	    "mhmh the following is a kludge ...."
+	    fgPixel isNil ifTrue:[
+		(foreground grayIntensity >= 50) ifTrue:[
+		    fgPixel := device whitepixel
+		] ifFalse:[
+		    fgPixel := device blackpixel
+		]
+	    ].
+	    bgPixel isNil ifTrue:[
+		(background grayIntensity >= 50) ifTrue:[
+		    bgPixel := device whitepixel
+		] ifFalse:[
+		    bgPixel := device blackpixel
+		]
+	    ].
+	    device setForeground:fgPixel background:bgPixel in:gcId.
+	    paint := foreground
+	]
     ]
 
     "Modified: 28.5.1996 / 20:45:27 / cg"
 !
 
 foreground:fgColor background:bgColor function:fun
+    <resource: #obsolete>
     "set foreground, background colors and function.
      OBSOLETE: this method will vanish; use #paint: / #paint:on:"
 
@@ -1036,30 +1054,31 @@
 !
 
 foreground:aColor function:fun
+    <resource: #obsolete>
     "set the foreground color and function for drawing.
      OBSOLETE: this method will vanish; use #paint: / #paint:on:"
 
     |fgPixel|
 
     ((aColor ~~ foreground) or:[fun ~~ function]) ifTrue:[
-        foreground := aColor.
-        function := fun.
-        gcId notNil ifTrue:[
-            foreground := foreground onDevice:device.
-            fgPixel := foreground colorId.
-
-            "mhmh the following is a kludge ...."
-            fgPixel isNil ifTrue:[
-                (foreground grayIntensity >= 50) ifTrue:[
-                    fgPixel := device whitepixel
-                ] ifFalse:[
-                    fgPixel := device blackpixel
-                ]
-            ].
-            device setForeground:fgPixel in:gcId.
-            device setFunction:fun in:gcId.
-            paint := foreground
-        ]
+	foreground := aColor.
+	function := fun.
+	gcId notNil ifTrue:[
+	    foreground := foreground onDevice:device.
+	    fgPixel := foreground colorId.
+
+	    "mhmh the following is a kludge ...."
+	    fgPixel isNil ifTrue:[
+		(foreground grayIntensity >= 50) ifTrue:[
+		    fgPixel := device whitepixel
+		] ifFalse:[
+		    fgPixel := device blackpixel
+		]
+	    ].
+	    device setForeground:fgPixel in:gcId.
+	    device setFunction:fun in:gcId.
+	    paint := foreground
+	]
     ]
 
     "Modified: 28.5.1996 / 20:45:09 / cg"
@@ -1071,43 +1090,41 @@
     "copy bits from a smalltalk byteArray.
      The bits found there are supposed to be in the devices native format (i.e.
      translated to allocated color indices on pseudoColor devices and padded as required.
-     The byteOrder is MSB and will be converted as appropriate by the underlying devices 
+     The byteOrder is MSB and will be converted as appropriate by the underlying devices
      method to whatever the device needs."
 
     device
         drawBits:aByteArray
-	bitsPerPixel:bpp 
-	depth:depth  
-	padding:pad
+        bitsPerPixel:bpp
+        depth:depth
+        padding:pad
         width:srcW height:srcH
         x:srcX y:srcY
         into:drawableId
-        x:dstX y:dstY 
-        width:(self width) height:(self height)
+        x:dstX y:dstY
+        width:srcW height:srcH       "all senders set srcW/srcH to self width / self height"
         with:gcId.
 !
 
-copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY
+copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY 
     "copy bits from a smalltalk byteArray.
      The bits found there are supposed to be in the devices native format (i.e.
      translated to allocated color indices on pseudoColor devices and padded as required.
-     The byteOrder is MSB and will be converted as appropriate by the underlying devices 
+     The byteOrder is MSB and will be converted as appropriate by the underlying devices
      method to whatever the device needs.
      Assumes the source bits are in ST/X's natural padding (i.e. 8-bit padded)"
-
-    device
-	drawBits:aByteArray
-	bitsPerPixel:bpp 
-	depth:depth  
-	padding:8
-	width:srcW height:srcH
-	x:srcX y:srcY
-	into:drawableId
-	x:dstX y:dstY 
-	width:(self width) height:(self height)
-	with:gcId.
-
-    "Created: 21.10.1995 / 00:04:22 / cg"
+    
+    self 
+        copyBitsFrom:aByteArray
+        bitsPerPixel:bpp
+        depth:depth
+        padding:8
+        width:srcW
+        height:srcH
+        x:srcX
+        y:srcY
+        toX:dstX
+        y:dstY
 !
 
 copyFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h
@@ -1116,11 +1133,11 @@
      All coordinates are in device coordinates."
 
     ^ self
-        copyFrom:aDrawable 
-        x:srcX y:srcY 
-        toX:dstX y:dstY 
-        width:w height:h
-        async:false
+	copyFrom:aDrawable
+	x:srcX y:srcY
+	toX:dstX y:dstY
+	width:w height:h
+	async:false
 
     "Modified: 29.1.1997 / 13:12:36 / cg"
 !
@@ -1129,15 +1146,15 @@
     "copy from aDrawable into the receiver;
      the source may be the receiver as well - in this case its a scroll.
      All coordinates are in device coordinates.
-     If the receiver is a view AND async is true, the call returns immediately 
+     If the receiver is a view AND async is true, the call returns immediately
      - otherwise, it returns when the scroll operation is finished.
      (not all devices care for this).
      If the receiver is a pixmap, the call always returns immediately."
 
-    |deviceDrawable id srcGCId asy|
+    |deviceDrawable id srcGCId|
 
     ((aDrawable graphicsDevice ~~ device)
-    or:[aDrawable isImage]) ifTrue:[
+     or:[aDrawable isImage]) ifTrue:[
         deviceDrawable := aDrawable asFormOn:device.
     ] ifFalse:[
         deviceDrawable := aDrawable
@@ -1147,8 +1164,8 @@
 
     "temporary ...
      this fixes a problem after restart on another display,
-     when a file-bitmap was not found. 
-     In this case, the id of the bitmap will be nil. 
+     when a file-bitmap was not found.
+     In this case, the id of the bitmap will be nil.
      This will be fixed soon (no longer use device>>bitmapFromFile:).
     "
     id isNil ifTrue:[
@@ -1167,61 +1184,53 @@
         deviceDrawable isForm ifTrue:[
             device
                 copyPlaneFromPixmapId:id
-                x:srcX 
-                y:srcY 
+                x:srcX
+                y:srcY
                 gc:srcGCId
                 to:drawableId
-                x:dstX 
-                y:dstY 
+                x:dstX
+                y:dstY
                 gc:gcId
-                width:w 
+                width:w
                 height:h
         ] ifFalse:[
             device
                 copyPlaneFromId:id
-                x:srcX 
-                y:srcY 
+                x:srcX
+                y:srcY
                 gc:srcGCId
                 to:drawableId
-                x:dstX 
-                y:dstY 
+                x:dstX
+                y:dstY
                 gc:gcId
-                width:w 
+                width:w
                 height:h
         ]
     ] ifFalse:[
         deviceDrawable isForm ifTrue:[
             device
                 copyFromPixmapId:id
-                x:srcX 
-                y:srcY 
+                x:srcX
+                y:srcY
                 gc:srcGCId
                 to:drawableId
-                x:dstX 
-                y:dstY 
+                x:dstX
+                y:dstY
                 gc:gcId
-                width:w 
+                width:w
                 height:h
         ] ifFalse:[
-            asy := async or:[self isView not].
-            asy ifFalse:[
-                self catchExpose
-            ].
             device
                 copyFromId:id
-                x:srcX 
-                y:srcY 
+                x:srcX
+                y:srcY
                 gc:srcGCId
                 to:drawableId
-                x:dstX 
-                y:dstY 
+                x:dstX
+                y:dstY
                 gc:gcId
-                width:w 
+                width:w
                 height:h.
-            asy ifFalse:[
-                device flush.
-                self waitForExpose
-            ]
         ]
     ]
 
@@ -1240,55 +1249,55 @@
 
     ((aDrawable graphicsDevice ~~ device)
     or:[aDrawable isImage]) ifTrue:[
-        deviceDrawable := aDrawable asFormOn:device.
+	deviceDrawable := aDrawable asFormOn:device.
     ] ifFalse:[
-        deviceDrawable := aDrawable
+	deviceDrawable := aDrawable
     ].
 
     id := deviceDrawable id.
 
     "temporary ...
      this fixes a problem after restart on another display,
-     when a file-bitmap was not found. 
+     when a file-bitmap was not found.
      In this case, the id of the bitmap will be nil.
      This will be fixed soon (no longer use device>>bitmapFromFile:).
     "
     id isNil ifTrue:[
-        'DeviceGraphicsContext [warning]: invalid copyPlane - ignored' errorPrintCR.
-        ^ self
+	'DeviceGraphicsContext [warning]: invalid copyPlane - ignored' errorPrintCR.
+	^ self
     ].
 
     gcId isNil ifTrue:[
-        self initGC
+	self initGC
     ].
 
     deviceDrawable isForm ifTrue:[
-        deviceDrawable gcId isNil ifTrue:[
-            deviceDrawable initGC
-        ].
-        device
-            copyPlaneFromPixmapId:id
-            x:srcX 
-            y:srcY 
-            gc:(deviceDrawable gcId)
-            to:drawableId
-            x:dstX 
-            y:dstY 
-            gc:gcId
-            width:w 
-            height:h
+	deviceDrawable gcId isNil ifTrue:[
+	    deviceDrawable initGC
+	].
+	device
+	    copyPlaneFromPixmapId:id
+	    x:srcX
+	    y:srcY
+	    gc:(deviceDrawable gcId)
+	    to:drawableId
+	    x:dstX
+	    y:dstY
+	    gc:gcId
+	    width:w
+	    height:h
     ] ifFalse:[
-        device
-            copyPlaneFromId:id
-            x:srcX 
-            y:srcY 
-            gc:(deviceDrawable gcId)
-            to:drawableId
-            x:dstX 
-            y:dstY 
-            gc:gcId
-            width:w 
-            height:h
+	device
+	    copyPlaneFromId:id
+	    x:srcX
+	    y:srcY
+	    gc:(deviceDrawable gcId)
+	    to:drawableId
+	    x:dstX
+	    y:dstY
+	    gc:gcId
+	    width:w
+	    height:h
     ]
 
     "Modified: / 22.8.1998 / 15:15:52 / cg"
@@ -1296,14 +1305,6 @@
 
 !DeviceGraphicsContext methodsFor:'copying'!
 
-executor
-    "I am abstract"
-
-    self subclassResponsibility.
-
-    "Created: 2.4.1997 / 19:22:11 / cg"
-!
-
 postCopy
     "this may not be enough to allow copying of views ..."
 
@@ -1332,11 +1333,11 @@
 	nW := transformation applyScaleX:w.
 	nH := transformation applyScaleY:h.
 	nW < 0 ifTrue:[
-	      nW := nW abs.  
+	      nW := nW abs.
 	      pX := pX - nW.
 	].
 	nH < 0 ifTrue:[
-	      nH := nH abs.  
+	      nH := nH abs.
 	      pY := pY - nH.
 	].
     ] ifFalse:[
@@ -1357,13 +1358,13 @@
     a isInteger ifFalse:[a := a asFloat].
 
     device
-	  displayArcX:pX 
-		    y:pY 
-		width:nW 
-	       height:nH 
-		 from:sA 
+	  displayArcX:pX
+		    y:pY
+		width:nW
+	       height:nH
+		 from:sA
 		angle:a
-		   in:drawableId 
+		   in:drawableId
 		 with:gcId
 
     "Created: 8.5.1996 / 08:31:30 / cg"
@@ -1371,13 +1372,13 @@
 !
 
 displayForm:formToDraw x:x y:y
-    "draw a form or image non opaque; 
+    "draw a form or image non opaque;
      if its a 1-plane bitmap, 1-bits are drawn in the
      current paint-color, leaving pixels with 0-bits unchanged
      (i.e. only 1-bits are drawn from the form).
      If its a deep form (i.e. a pixmap) the current paint
-     settings are ignored and the form is drawn as-is. 
-     Care must be taken, that the paint color is correctly allocated 
+     settings are ignored and the form is drawn as-is.
+     Care must be taken, that the paint color is correctly allocated
      (by sending #on: to the color) before doing so.
      Using functions other than #copy only makes sense if you are
      certain, that the colors are real colors (actually, only for
@@ -1388,44 +1389,44 @@
     realForm := formToDraw.
 
     transformation notNil ifTrue:[
-        pX := transformation applyToX:x.
-        pY := transformation applyToY:y.
-
-        transformation noScale ifFalse:[
-            w := formToDraw width.
-            h := formToDraw height.
-
-            nW := (transformation applyScaleX:w) rounded.
-            nH := (transformation applyScaleY:h) rounded.
-
-            ((nW ~= w) or:[nH ~= h]) ifTrue:[
-                "/
-                "/ hard case - someone is drawing forms with scaling in effect
-                "/ look if we have a scaled version in our pocket ...
-                "/
-                realForm := nil.
-                CachedScaledForms notNil ifTrue:[
-                    (CachedScales at:formToDraw ifAbsent:nil) = transformation scale ifTrue:[
-                        realForm := CachedScaledForms at:formToDraw ifAbsent:nil.
-                    ]
-                ].
-                realForm isNil ifTrue:[
-                    "/
-                    "/ nope - must do the work ...
-                    "/
-                    realForm := formToDraw magnifiedBy:(nW / w) @ (nH / h).
-                    CachedScaledForms isNil ifTrue:[
-                        CachedScaledForms := WeakIdentityDictionary new.
-                        CachedScales := WeakIdentityDictionary new.
-                    ].
-                    CachedScaledForms at:formToDraw put:realForm.
-                    CachedScales at:formToDraw put:transformation scale.
-                ]
-            ]
-        ]
+	pX := transformation applyToX:x.
+	pY := transformation applyToY:y.
+
+	transformation noScale ifFalse:[
+	    w := formToDraw width.
+	    h := formToDraw height.
+
+	    nW := (transformation applyScaleX:w) rounded.
+	    nH := (transformation applyScaleY:h) rounded.
+
+	    ((nW ~= w) or:[nH ~= h]) ifTrue:[
+		"/
+		"/ hard case - someone is drawing forms with scaling in effect
+		"/ look if we have a scaled version in our pocket ...
+		"/
+		realForm := nil.
+		CachedScaledForms notNil ifTrue:[
+		    (CachedScales at:formToDraw ifAbsent:nil) = transformation scale ifTrue:[
+			realForm := CachedScaledForms at:formToDraw ifAbsent:nil.
+		    ]
+		].
+		realForm isNil ifTrue:[
+		    "/
+		    "/ nope - must do the work ...
+		    "/
+		    realForm := formToDraw magnifiedBy:(nW / w) @ (nH / h).
+		    CachedScaledForms isNil ifTrue:[
+			CachedScaledForms := WeakIdentityDictionary new.
+			CachedScales := WeakIdentityDictionary new.
+		    ].
+		    CachedScaledForms at:formToDraw put:realForm.
+		    CachedScales at:formToDraw put:transformation scale.
+		]
+	    ]
+	]
     ] ifFalse:[
-        pX := x.
-        pY := y.
+	pX := x.
+	pY := y.
     ].
 
     self displayDeviceForm:realForm x:pX y:pY
@@ -1439,52 +1440,52 @@
     |pX0 pY0 pX1 pY1 easy fgId bgId|
 
     gcId isNil ifTrue:[
-        self initGC
+	self initGC
     ].
 
     lineStyle == #doubleDashed ifTrue:[
-        "
-         if bgPaint or paint is not a real color, we have to do it the hard way ...
-        "
-        easy := true.
-        paint isColor ifFalse:[
-            easy := false
-        ] ifTrue:[
-            fgId := paint colorId.
-            fgId isNil ifTrue:[
-                easy := false
-            ]
-        ].
-        bgPaint isColor ifFalse:[
-            easy := false
-        ] ifTrue:[
-            bgId := bgPaint colorId.
-            bgId isNil ifTrue:[
-                easy := false
-            ]
-        ].
-
-        easy ifTrue:[
-            ((foreground ~~ paint) or:[background ~~ bgPaint]) ifTrue:[
-                device setForeground:fgId background:bgId in:gcId.
-                foreground := paint.
-                background := bgPaint.
-            ].
-        ] ifFalse:[
-            'DeviceGraphicsContext [warning]: cannot draw dashes with dithered colors' errorPrintCR
-        ].
+	"
+	 if bgPaint or paint is not a real color, we have to do it the hard way ...
+	"
+	easy := true.
+	paint isColor ifFalse:[
+	    easy := false
+	] ifTrue:[
+	    fgId := paint colorId.
+	    fgId isNil ifTrue:[
+		easy := false
+	    ]
+	].
+	bgPaint isColor ifFalse:[
+	    easy := false
+	] ifTrue:[
+	    bgId := bgPaint colorId.
+	    bgId isNil ifTrue:[
+		easy := false
+	    ]
+	].
+
+	easy ifTrue:[
+	    ((foreground ~~ paint) or:[background ~~ bgPaint]) ifTrue:[
+		device setForeground:fgId background:bgId in:gcId.
+		foreground := paint.
+		background := bgPaint.
+	    ].
+	] ifFalse:[
+	    'DeviceGraphicsContext [warning]: cannot draw dashes with dithered colors' errorPrintCR
+	].
     ].
 
     transformation notNil ifTrue:[
-        pX0 := transformation applyToX:x0.
-        pY0 := transformation applyToY:y0.
-        pX1 := transformation applyToX:x1.
-        pY1 := transformation applyToY:y1.
+	pX0 := transformation applyToX:x0.
+	pY0 := transformation applyToY:y0.
+	pX1 := transformation applyToX:x1.
+	pY1 := transformation applyToY:y1.
     ] ifFalse:[
-        pX0 := x0.
-        pY0 := y0.
-        pX1 := x1.
-        pY1 := y1
+	pX0 := x0.
+	pY0 := y0.
+	pX1 := x1.
+	pY1 := y1
     ].
 
     pX0 := pX0 rounded.
@@ -1498,67 +1499,67 @@
 !
 
 displayOpaqueForm:formToDraw x:x y:y
-    "draw a form or image opaque; 
+    "draw a form or image opaque;
      if its a 1-plane bitmap, 1-bits are drawn in the
      current paint-color and 0-bits in the bgPaint color.
      If its a deep form (i.e. a pixmap) the current paint/bgPaint
-     settings are ignored and the form drawn as-is. 
-     In the 1-plane case, special care must be taken if paint and/or bgPaint 
-     dithered colors or patterns, since are that the colors are correctly allocated 
+     settings are ignored and the form drawn as-is.
+     In the 1-plane case, special care must be taken if paint and/or bgPaint
+     dithered colors or patterns, since are that the colors are correctly allocated
      (by sending #on: to the colors) before doing so.
      If there is a transformation, the image is scaled as appropiate."
 
     |w h realForm pX pY nW nH|
 
     bgPaint isNil ifTrue:[
-        "/
-        "/ actually not an opaque draw
-        "/
-        self displayForm:formToDraw x:x y:y.
-        ^ self
+	"/
+	"/ actually not an opaque draw
+	"/
+	self displayForm:formToDraw x:x y:y.
+	^ self
     ].
 
     realForm := formToDraw.
 
     transformation notNil ifTrue:[
-        pX := transformation applyToX:x.
-        pY := transformation applyToY:y.
-
-        transformation noScale ifFalse:[
-            w := formToDraw width.
-            h := formToDraw height.
-
-            nW := (transformation applyScaleX:w) rounded.
-            nH := (transformation applyScaleY:h) rounded.
-
-            ((nW ~= w) or:[nH ~= h]) ifTrue:[
-                "/
-                "/ hard case - someone is drawing forms with scaling in effect
-                "/ look if we have a scaled version in our pocket ...
-                "/
-                realForm := nil.
-                CachedScaledForms notNil ifTrue:[
-                    (CachedScales at:formToDraw ifAbsent:nil) = transformation scale ifTrue:[
-                        realForm := CachedScaledForms at:formToDraw ifAbsent:nil.
-                    ]
-                ].
-                realForm isNil ifTrue:[
-                    "/
-                    "/ nope - must do the work ...
-                    "/
-                    realForm := formToDraw magnifiedBy:(nW / w) @ (nH / h).
-                    CachedScaledForms isNil ifTrue:[
-                        CachedScaledForms := WeakIdentityDictionary new.
-                        CachedScales := WeakIdentityDictionary new.
-                    ].
-                    CachedScaledForms at:formToDraw put:realForm.
-                    CachedScales at:formToDraw put:transformation scale.
-                ]
-            ]
-        ]
+	pX := transformation applyToX:x.
+	pY := transformation applyToY:y.
+
+	transformation noScale ifFalse:[
+	    w := formToDraw width.
+	    h := formToDraw height.
+
+	    nW := (transformation applyScaleX:w) rounded.
+	    nH := (transformation applyScaleY:h) rounded.
+
+	    ((nW ~= w) or:[nH ~= h]) ifTrue:[
+		"/
+		"/ hard case - someone is drawing forms with scaling in effect
+		"/ look if we have a scaled version in our pocket ...
+		"/
+		realForm := nil.
+		CachedScaledForms notNil ifTrue:[
+		    (CachedScales at:formToDraw ifAbsent:nil) = transformation scale ifTrue:[
+			realForm := CachedScaledForms at:formToDraw ifAbsent:nil.
+		    ]
+		].
+		realForm isNil ifTrue:[
+		    "/
+		    "/ nope - must do the work ...
+		    "/
+		    realForm := formToDraw magnifiedBy:(nW / w) @ (nH / h).
+		    CachedScaledForms isNil ifTrue:[
+			CachedScaledForms := WeakIdentityDictionary new.
+			CachedScales := WeakIdentityDictionary new.
+		    ].
+		    CachedScaledForms at:formToDraw put:realForm.
+		    CachedScales at:formToDraw put:transformation scale.
+		]
+	    ]
+	]
     ] ifFalse:[
-        pX := x.
-        pY := y.
+	pX := x.
+	pY := y.
     ].
 
     self displayDeviceOpaqueForm:realForm x:pX y:pY
@@ -1569,28 +1570,28 @@
 displayOpaqueString:aString from:index1 to:index2 x:x y:y
     "draw a substring at the coordinate x/y - draw foreground pixels in
      paint-color and background pixels in bgPaint-color.
-     If the transformation involves scaling, 
+     If the transformation involves scaling,
      the fonts point-size is scaled as appropriate.
      Assuming that device can only draw in device colors, we have to handle
      the case where paint and/or bgPaint are dithered colors"
 
-    self displayString:aString from:index1 to:index2 x:x y:y opaque:true
+    self displayString:aString from:index1 to:index2 x:x y:y opaque:true maxWidth:nil
 !
 
 displayOpaqueString:aString x:x y:y
     "draw a string at the coordinate x/y - draw foreground pixels in paint-color,
-     background pixels in bgPaint color. If the transformation involves scaling, 
+     background pixels in bgPaint color. If the transformation involves scaling,
      the fonts point-size is scaled as appropriate.
      Assuming that device can only draw in device colors, we have to handle
      the case where paint and/or bgPaint are dithered colors or images."
 
     (aString isString not or:[aString isText]) ifTrue:[
-        "
-         hook for non-strings (i.e. attributed text)
-         that 'thing' should know how to display itself ...
-        "
-        aString displayOpaqueOn:self x:x y:y.
-        ^ self
+	"
+	 hook for non-strings (i.e. attributed text)
+	 that 'thing' should know how to display itself ...
+	"
+	aString displayOpaqueOn:self x:x y:y.
+	^ self
     ].
 
     self displayOpaqueString:aString from:1 to:(aString size) x:x y:y
@@ -1631,14 +1632,14 @@
     ] ifFalse:[
 	newPolygon := aPolygon
     ].
-    (newPolygon findFirst:[:p | 
-	(p isPoint not 
+    (newPolygon findFirst:[:p |
+	(p isPoint not
 	or:[(p x class ~~ SmallInteger)
 	or:[(p y class ~~ SmallInteger)]])
      ]) ~~ 0 ifTrue:[
 	newPolygon := newPolygon collect:[:p | p asPoint rounded]
     ].
-        
+
     device displayPolygon:newPolygon in:drawableId with:gcId
 !
 
@@ -1649,60 +1650,60 @@
     |pX pY nW nH easy fgId bgId|
 
     gcId isNil ifTrue:[
-        self initGC
+	self initGC
     ].
 
     lineStyle == #doubleDashed ifTrue:[
-        "
-         if bgPaint or paint is not a real color, we have to do it the hard way ...
-        "
-        easy := true.
-        paint isColor ifFalse:[
-            easy := false
-        ] ifTrue:[
-            fgId := paint colorId.
-            fgId isNil ifTrue:[
-                easy := false
-            ]
-        ].
-        bgPaint isColor ifFalse:[
-            easy := false
-        ] ifTrue:[
-            bgId := bgPaint colorId.
-            bgId isNil ifTrue:[
-                easy := false
-            ]
-        ].
-
-        easy ifTrue:[
-            ((foreground ~~ paint) or:[background ~~ bgPaint]) ifTrue:[
-                device setForeground:fgId background:bgId in:gcId.
-                foreground := paint.
-                background := bgPaint.
-            ].
-        ] ifFalse:[
-            'DeviceGraphicsContext [warning]: cannot draw dashes with dithered colors' errorPrintCR
-        ].
+	"
+	 if bgPaint or paint is not a real color, we have to do it the hard way ...
+	"
+	easy := true.
+	paint isColor ifFalse:[
+	    easy := false
+	] ifTrue:[
+	    fgId := paint colorId.
+	    fgId isNil ifTrue:[
+		easy := false
+	    ]
+	].
+	bgPaint isColor ifFalse:[
+	    easy := false
+	] ifTrue:[
+	    bgId := bgPaint colorId.
+	    bgId isNil ifTrue:[
+		easy := false
+	    ]
+	].
+
+	easy ifTrue:[
+	    ((foreground ~~ paint) or:[background ~~ bgPaint]) ifTrue:[
+		device setForeground:fgId background:bgId in:gcId.
+		foreground := paint.
+		background := bgPaint.
+	    ].
+	] ifFalse:[
+	    'DeviceGraphicsContext [warning]: cannot draw dashes with dithered colors' errorPrintCR
+	].
     ].
 
     transformation notNil ifTrue:[
-        pX := transformation applyToX:x.
-        pY := transformation applyToY:y.
-        nW := transformation applyScaleX:w.
-        nH := transformation applyScaleY:h.
-        nW < 0 ifTrue:[
-              nW := nW abs.  
-              pX := pX - nW.
-        ].
-        nH < 0 ifTrue:[
-              nH := nH abs.  
-              pY := pY - nH.
-        ].
+	pX := transformation applyToX:x.
+	pY := transformation applyToY:y.
+	nW := transformation applyScaleX:w.
+	nH := transformation applyScaleY:h.
+	nW < 0 ifTrue:[
+	      nW := nW abs.
+	      pX := pX - nW.
+	].
+	nH < 0 ifTrue:[
+	      nH := nH abs.
+	      pY := pY - nH.
+	].
     ] ifFalse:[
-        pX := x.
-        pY := y.
-        nW := w.
-        nH := h
+	pX := x.
+	pY := y.
+	nW := w.
+	nH := h
     ].
 
     pX := pX rounded.
@@ -1715,34 +1716,41 @@
      a rectangle using the same extents.
      I'm not certain if is the right thing to do ...
     "
-    device displayRectangleX:pX 
-                           y:pY 
-                       width:(nW - 1) 
-                      height:(nH - 1)
-                          in:drawableId with:gcId
+    device displayRectangleX:pX
+			   y:pY
+		       width:(nW - 1)
+		      height:(nH - 1)
+			  in:drawableId with:gcId
 
     "Modified: 10.1.1997 / 17:46:41 / cg"
 !
 
 displayString:aString from:index1 to:index2 x:x y:y
-    "draw a substring at the coordinate x/y -  
-     draw foreground-pixels only (in current paint-color), 
+    "draw a substring at the coordinate x/y -
+     draw foreground-pixels only (in current paint-color),
      leaving background as-is. If the transformation involves scaling,
      the fonts point-size is scaled as appropriate."
 
-    self displayString:aString from:index1 to:index2 x:x y:y opaque:false
+    self displayString:aString from:index1 to:index2 x:x y:y opaque:false maxWidth:nil
 !
 
-displayString:aString from:index1Arg to:index2Arg x:x y:y opaque:opaqueArg
+displayString:aString from:index1 to:index2 x:x y:y opaque:opaque
+    "draw part of a string with both fg and bg at x/y in current font"
+
+    ^ self displayString:aString from:index1 to:index2 x:x y:y opaque:opaque maxWidth:nil.
+!
+
+displayString:aStringArg from:index1Arg to:index2Arg x:x y:y opaque:opaqueArg maxWidth:maxWidth
     "draw a substring at the coordinate x/y - draw foreground pixels in
      paint-color and (if opaque is true), background pixels in bgPaint-color.
      If the transformation involves scaling, the font's point-size is scaled as appropriate.
      Assuming that device can only draw in device colors, we have to handle
-     the case where paint and/or bgPaint are dithered colors"
+     the case where paint and/or bgPaint are dithered colors.
+     maxWidth is the maximum width of the string in pixels or nil if unknown."
 
     |opaque index1 index2 easy w h savedPaint fgId bgId
-     fontId pX pY fontUsed fontsEncoding sz s
-     nSkipLeft nChars wString wSkipLeft wMax index2Guess|
+     fontId pX pY fontUsed fontsEncoding aString
+     nSkipLeft nChars wString wSkipLeft index2Guess|
 
     index1 := index1Arg.
     index2 := index2Arg.
@@ -1756,37 +1764,42 @@
         opaque := false.
     ].
 
-    (aString isString not or:[aString isText]) ifTrue:[
+    gcId isNil ifTrue:[
+        self initGC
+    ].
+
+    (aStringArg isString not or:[aStringArg isText]) ifTrue:[
         "
          hook for non-strings (i.e. attributed text)
          that 'thing' should know how to display itself ...
         "
-        aString displayOn:self x:x y:y from:index1 to:index2 opaque:opaque.
+        aStringArg displayOn:self x:x y:y from:index1 to:index2 opaque:opaque.
         ^ self
     ].
-    font isAlienFont ifTrue:[
-        "
-         hook for alien fonts
-         that 'font' should know how to display the string...
-        "
-        font displayString:aString from:index1 to:index2 x:x rounded y:y rounded in:self opaque:opaque.
-        ^ self
-    ].
-
-    gcId isNil ifTrue:[
-        self initGC
+
+    "/ transcode the string into the fonts encoding...
+    aString := aStringArg.
+    fontsEncoding := font encoding.
+    (characterEncoding ~~ fontsEncoding) ifTrue:[
+        [
+            aString := CharacterEncoder encodeString:aString from:characterEncoding into:fontsEncoding.
+        ] on:CharacterEncoderError do:[:ex|
+            "substitute a default value for codes that cannot be represented
+             in the new character set"
+            ex proceedWith:ex defaultValue.
+        ].
     ].
 
     fontUsed := font.
+
     transformation notNil ifTrue:[
         pX := transformation applyToX:x.
         pY := transformation applyToY:y.
         transformation noScale ifFalse:[
+            |sz|
+
             sz := font size.
-            sz isNil ifTrue:[
-                "/ oops - not a real font; use original font
-                fontUsed := font
-            ] ifFalse:[
+            sz notNil ifTrue:[
                 fontUsed := font asSize:(transformation applyScaleY:sz) rounded.
             ]
         ]
@@ -1794,24 +1807,20 @@
         pX := x.
         pY := y.
     ].
+
+    fontUsed isAlienFont ifTrue:[
+        "
+         hook for alien fonts
+         that 'font' should know how to display the string...
+        "
+        fontUsed displayString:aString from:index1 to:index2 x:x rounded y:y rounded in:self opaque:opaque maxWidth:maxWidth.
+        ^ self
+    ].
+
     pX := pX rounded.
     pY := pY rounded.
 
     fontUsed := fontUsed onDevice:device.
-
-    "/ transcode the string into the fonts encoding...
-    s := aString.
-    fontsEncoding := fontUsed encoding.
-    (characterEncoding ~~ fontsEncoding) ifTrue:[
-        [
-            s := CharacterEncoder encodeString:s from:characterEncoding into:fontsEncoding.
-        ] on:CharacterEncoderError do:[:ex|
-            "substitute a default value for codes that cannot be represented
-             in the new character set"
-            ex proceedWith:ex defaultValue.
-        ].
-    ].
-
     fontId := fontUsed fontId.
     fontId isNil ifTrue:[
         "this should not happen, since #onDevice tries replacement fonts"
@@ -1822,23 +1831,23 @@
     "
      if bgPaint or paint is not a real Color (aka a pattern), we have to do it the hard way ...
     "
-    easy := true.
-    paint isColor ifFalse:[
-        easy := false
-    ] ifTrue:[
+    paint isColor ifTrue:[
+        easy := true.
         fgId := paint colorId.
         fgId isNil ifTrue:[
             easy := false
         ]
+    ] ifFalse:[
+        easy := false
     ].
     opaque ifTrue:[
-        bgPaint isColor ifFalse:[
-            easy := false
-        ] ifTrue:[
+        bgPaint isColor ifTrue:[
             bgId := bgPaint colorId.
             bgId isNil ifTrue:[
                 easy := false
             ]
+        ] ifFalse:[
+            easy := false
         ].
     ].
 
@@ -1850,14 +1859,13 @@
     "/ check if this string is too long and cut it into a managable size.
     "/ this is due to win32 limitations which seems to be unable to handle strings
     "/ which are drawn longer than 32k pixels.
-    (index2 - index1) > 500 ifTrue:[
+    (maxWidth notNil and:[(index2 - index1) > 500]) ifTrue:[
         nSkipLeft := wSkipLeft := 0.
-        wMax := self width.
 
         "/ if the draw starts to the left of the window start,
         "/ skip some characters at the beginning...
         pX < 0 ifTrue:[
-"/ ('x=%d wMax=%d l=%d i1=%d i2=%d' printfWith:x with:wMax with:aString size with:index1 with:index2) printCR.
+"/ ('x=%d wMax=%d l=%d i1=%d i2=%d' printfWith:x with:maxWidth with:aString size with:index1 with:index2) printCR.
             nSkipLeft := (pX negated // font width) min:index2.                         "/ estimate
             wSkipLeft := fontUsed widthOf:aString from:index1 to:index1+nSkipLeft-1.    "/ actual number of pixels
             [ ((pX+wSkipLeft) > 0) and:[nSkipLeft > 0]] whileTrue:[                      "/ too many
@@ -1869,16 +1877,11 @@
 "/ ('skip %d w=%d x=%d' printfWith:nSkipLeft with:wSkipLeft with:x) printCR.
         ].
 
-        "/ if the draw ends to the right of the window ends,
-        "/ skip some characters at the end...
-        nChars := wMax // font width + 2.                                       "/ estimate
-        index2Guess := (index1+nChars-1) min:index2.
-        wString := fontUsed widthOf:aString from:index1 to:index2Guess.     "/ actual number of pixels
 "/ ('n=%d w=%d' printfWith:nChars with:wString) printCR.
-        [ ((pX+wString) < wMax) and:[ index2Guess < index2] ] whileTrue:[  "/ not enough...       
+        [ ((pX+wString) < maxWidth) and:[ index2Guess < index2] ] whileTrue:[  "/ not enough...
             nChars := (nChars * 1.1) rounded.
             index2Guess := (index1+nChars-1) min:index2.
-            wString := fontUsed widthOf:aString from:index1 to:index2Guess. 
+            wString := fontUsed widthOf:aString from:index1 to:index2Guess.
         ].
 "/ ('n=%d w=%d' printfWith:nChars with:wString) printCR.
         index2 := index2Guess.
@@ -1892,11 +1895,15 @@
             device setForeground:fgId in:gcId.
         ].
         foreground := paint.
-        device displayString:s from:index1 to:index2 x:pX y:pY in:drawableId with:gcId opaque:opaque.
+        device displayString:aString from:index1 to:index2 x:pX y:pY in:drawableId with:gcId opaque:opaque.
         ^ self
     ].
 
-    w := fontUsed widthOf:s from:index1 to:index2.
+    "/
+    "/ do it the hard way - either forground or background is not a plain color,
+    "/ but dithered or a pattern
+    "/
+    w := fontUsed widthOf:aString from:index1 to:index2.
     h := fontUsed height.
 
     (fgId notNil and:[function == #copy]) ifTrue:[
@@ -1911,43 +1918,35 @@
         "
          then draw using fgPaint (which is a real color)
         "
-        device displayString:s from:index1 to:index2 x:pX y:pY in:drawableId with:gcId opaque:false.
+        device displayString:aString from:index1 to:index2 x:pX y:pY in:drawableId with:gcId opaque:false.
         ^ self
     ].
 
     "/ the very hard case (fg-dither)
 
-    self displayDeviceOpaqueString:s from:index1 to:index2 in:fontUsed x:pX y:pY.
+    self displayDeviceOpaqueString:aString from:index1 to:index2 in:fontUsed x:pX y:pY.
 
     "Modified: / 30-06-1997 / 15:06:15 / cg"
     "Modified: / 14-04-2011 / 11:11:00 / Stefan Vogel <sv@exept.de>"
 !
 
 displayString:aString x:x y:y
-    "draw a string at the coordinate x/y - 
-     draw foreground-pixels only (in current paint-color), 
-     leaving background as-is. If the transformation involves scaling, 
+    "draw a string at the coordinate x/y -
+     draw foreground-pixels only (in current paint-color),
+     leaving background as-is. If the transformation involves scaling,
      the fonts point-size is scaled as appropriate."
 
-    (aString isString not or:[aString isText]) ifTrue:[
-        "
-         hook for non-strings (i.e. attributed text)
-         that 'thing' should know how to display itself ...
-        "
-        ^ aString displayOn:self x:x y:y
-    ].
-
-    self displayString:aString from:1 to:aString size x:x y:y
+    self displayString:aString from:1 to:aString size x:x y:y opaque:false maxWidth:nil
 !
 
 displayUnscaledForm:formToDraw x:x y:y
-    "draw a form or image non opaque and unscaled; 
+    "draw a form or image non opaque and unscaled;
      if its a 1-plane bitmap, 1-bits are drawn in the
      current paint-color, leaving pixels with 0-bits unchanged
      (i.e. only 1-bits are drawn from the form).
      If its a deep form (i.e. a pixmap) the current paint
-     settings are ignored and the form is drawn as-is. 
-     Care must be taken, that the paint color is correctly allocated 
+     settings are ignored and the form is drawn as-is.
+     Care must be taken, that the paint color is correctly allocated
      (by sending #on: to the color) before doing so.
      Using functions other than #copy only makes sense if you are
      certain, that the colors are real colors (actually, only for
@@ -1957,11 +1956,11 @@
     |pX pY|
 
     transformation notNil ifTrue:[
-        pX := transformation applyToX:x.
-        pY := transformation applyToY:y.
+	pX := transformation applyToX:x.
+	pY := transformation applyToY:y.
     ] ifFalse:[
-        pX := x.
-        pY := y.
+	pX := x.
+	pY := y.
     ].
 
     self displayDeviceForm:formToDraw x:pX y:pY
@@ -1970,21 +1969,21 @@
 !
 
 displayUnscaledOpaqueForm:formToDraw x:x y:y
-    "draw a form or image opaque and unscaled; 
+    "draw a form or image opaque and unscaled;
      if its a 1-plane bitmap, 1-bits are drawn in the
      current paint-color, 0 bits in background color.
      If its a deep form (i.e. a pixmap) the current paint
-     settings are ignored and the form is drawn as-is (opaque). 
+     settings are ignored and the form is drawn as-is (opaque).
      The origins coordinate is transformed, but the image itself is unscaled."
 
     |pX pY|
 
     transformation notNil ifTrue:[
-        pX := transformation applyToX:x.
-        pY := transformation applyToY:y.
+	pX := transformation applyToX:x.
+	pY := transformation applyToY:y.
     ] ifFalse:[
-        pX := x.
-        pY := y.
+	pX := x.
+	pY := y.
     ].
 
     self displayDeviceOpaqueForm:formToDraw x:pX y:pY
@@ -2059,25 +2058,25 @@
 !DeviceGraphicsContext methodsFor:'drawing in device coordinates'!
 
 displayDeviceForm:aForm x:x y:y
-    "draw a form or image non opaque (i.e. only foreground color is drawn); 
+    "draw a form or image non opaque (i.e. only foreground color is drawn);
      If its a 1-plane bitmap, 1-bits are drawn in the
      current paint-color, leaving pixels with 0-bits unchanged
      (i.e. only 1-bits are drawn from the form).
      If its a deep form (i.e. a pixmap) the current paint
-     settings are ignored and the form is drawn as-is; 
+     settings are ignored and the form is drawn as-is;
      however, the mask is applied if present.
 
      The form should must have been allocated on the same device,
      otherwise its converted here, which slows down the draw.
      No transformation or scaling is done.
-     Care must be taken, that the paint color is correctly allocated 
+     Care must be taken, that the paint color is correctly allocated
      (by sending #on: to the color) before doing so.
      Using functions other than #copy only makes sense if you are
      certain, that the colors are real colors (actually, only for
      noColor or allColor)."
 
-    |id w h easy paintDither tmpForm tmpId tmpGCId 
-     fgId noColor allColor allBits pX pY 
+    |id w h easy paintDither tmpForm tmpId tmpGCId
+     fgId noColor allColor allBits pX pY
      mask maskId deviceForm deviceFormGCId deviceMask colorMap|
 
     w := aForm width.
@@ -2088,24 +2087,24 @@
 
     deviceForm := aForm asFormOn:device.
     deviceForm isNil ifTrue:[
-        'DeviceGraphicsContext [warning]: cannot create device-form' errorPrintCR.
-        ^self
+	'DeviceGraphicsContext [warning]: cannot create device-form' errorPrintCR.
+	^self
     ].
     id := deviceForm id.
 
     id isNil ifTrue:[
-        'DeviceGraphicsContext [warning]: invalid form draw - ignored' errorPrintCR.
-        ^ self
+	'DeviceGraphicsContext [warning]: invalid form draw - ignored' errorPrintCR.
+	^ self
     ].
     gcId isNil ifTrue:[
-        self initGC
+	self initGC
     ].
     (deviceFormGCId := deviceForm gcId) isNil ifTrue:[
-        "/ device needGCForBitmapSource  - i.e. WIN32
-        device platformName ~= 'X11' ifTrue:[
-            deviceForm initGC.
-            deviceFormGCId := deviceForm gcId.
-        ]
+	"/ device needGCForBitmapSource  - i.e. WIN32
+	device platformName ~= 'X11' ifTrue:[
+	    deviceForm initGC.
+	    deviceFormGCId := deviceForm gcId.
+	]
     ].
 
     "
@@ -2113,197 +2112,197 @@
     "
     mask := aForm mask.
 
-    ((aForm depth ~~ 1) 
+    ((aForm depth ~~ 1)
     or:[mask notNil]) ifTrue:[
-        mask notNil ifTrue:[
-            mask depth == 1 ifFalse:[
-                'DEVGC: alpha channel not yet supported' errorPrintCR.
-            ] ifTrue:[
-                deviceMask := mask asFormOn:device.
-                deviceMask isNil ifTrue:[
-                    'DeviceGraphicsContext [warning]: cannot create device-mask' errorPrintCR.
-                    ^self
-                ].
-                maskId := deviceMask id.
-                maskId notNil ifTrue:[
-                    deviceMask gcId isNil ifTrue:[deviceMask initGC].
-                    allColor := Color allColor.
-                    allBits := allColor colorId.
-
-                    (deviceForm depth == device depth 
-                    and:[aForm maskedPixelsAre0]) ifTrue:[
-                        "/ can do it without a temporary pixmap:
-                        "/   or-in the form into the inverse stamped-out area 
-                        "/   of the destination.
-                        "/   Oring is of course only possible if we know that
-                        "/   masked pixels are already zero in the form.
-
-                        "/ stamp out using mask
-                        device setForeground:0 background:allBits in:gcId.
-                        device setFunction:#and in:gcId.
-                        device
-                            copyPlaneFromPixmapId:maskId
-                            x:0 
-                            y:0 
-                            gc:(deviceMask gcId)
-                            to:drawableId
-                            x:pX 
-                            y:pY 
-                            gc:gcId
-                            width:w 
-                            height:h.
-                        "/ or-in the form
-                        device setFunction:#or in:gcId.
-                        device
-                            copyFromPixmapId:id
-                            x:0 
-                            y:0 
-                            gc:deviceFormGCId
-                            to:drawableId
-                            x:pX 
-                            y:pY 
-                            gc:gcId
-                            width:w 
-                            height:h.
-                    ] ifFalse:[
-                        "/ must do it slow, using a temporary form ..
-
-                        "
-                         create temp-form;
-                        "
-                        tmpForm := Form width:w height:h depth:device depth onDevice:device.
-                        tmpForm isNil ifTrue:[
-                            'DeviceGraphicsContext [warning]: cannot create temp form' errorPrintCR.
-                            ^self
-                        ].
-                        tmpForm initGC.
-                        tmpId := tmpForm id.
-                        tmpGCId := tmpForm gcId.
-
-                        "
-                         fill tempform with image
-                        "
-                        aForm depth == 1 ifTrue:[
-                            (colorMap := aForm colorMap) notNil ifTrue:[
-                                colorMap size < 2 ifTrue:[
-                                    device 
-                                        setForegroundColor:(colorMap at:1) 
-                                        in:tmpGCId.
-                                ] ifFalse:[
-                                    device 
-                                        setForegroundColor:(colorMap at:2) 
-                                        backgroundColor:(colorMap at:1) 
-                                        in:tmpGCId.
-                                ]
-                            ].
-                            device
-                                copyPlaneFromPixmapId:id
-                                x:0 
-                                y:0 
-                                gc:deviceFormGCId
-                                to:tmpId
-                                x:0 
-                                y:0 
-                                gc:tmpGCId
-                                width:w 
-                                height:h.
-                        ] ifFalse:[
-                            device
-                                copyFromPixmapId:id
-                                x:0 
-                                y:0 
-                                gc:deviceFormGCId
-                                to:tmpId
-                                x:0 
-                                y:0 
-                                gc:tmpGCId
-                                width:w 
-                                height:h.
-                        ].
-
-                        "
-                         stamp out mask in temp form
-                        "
-                        device setForeground:allBits background:0 in:tmpGCId.
-                        device setFunction:#and in:tmpGCId.
-                        device
-                            copyPlaneFromPixmapId:maskId
-                            x:0 
-                            y:0 
-                            gc:(deviceMask gcId)
-                            to:tmpId
-                            x:0 
-                            y:0 
-                            gc:tmpGCId
-                            width:w 
-                            height:h.
-
-                        "
-                         stamp out mask in destination
-                        "
-                        device setForeground:0 background:allBits in:gcId.
-                        device setFunction:#and in:gcId.
-                        device
-                            copyPlaneFromPixmapId:maskId
-                            x:0 
-                            y:0 
-                            gc:(deviceMask gcId)
-                            to:drawableId
-                            x:pX 
-                            y:pY 
-                            gc:gcId
-                            width:w 
-                            height:h.
-
-                        "
-                         or-in tempform-bits ...
-                        "
-                        device setFunction:#or in:gcId.
-                        device
-                            copyFromPixmapId:tmpId
-                            x:0 
-                            y:0 
-                            gc:tmpGCId
-                            to:drawableId
-                            x:pX 
-                            y:pY 
-                            gc:gcId
-                            width:w 
-                            height:h.
-
-                        "
-                         release tempForm immediately
-                         (although GC will eventually do it, 
-                          this creates less stress to the Xserver in the meanwhile ...)
-                        "
-                        tmpForm destroy.
-                    ].
-
-                    "/ restore GC
-                    foreground notNil ifTrue:[
-                        device setForegroundColor:foreground in:gcId.
-                    ].
-                    background notNil ifTrue:[
-                        device setBackgroundColor:background in:gcId 
-                    ].
-                    device setFunction:function in:gcId.
-                    ^ self
-                ]
-            ]
-        ].
-
-        device
-            copyFromPixmapId:id
-            x:0 
-            y:0 
-            gc:deviceForm gcId
-            to:drawableId
-            x:pX 
-            y:pY 
-            gc:gcId
-            width:w 
-            height:h.
-        ^ self
+	mask notNil ifTrue:[
+	    mask depth == 1 ifFalse:[
+		'DEVGC: alpha channel not yet supported' errorPrintCR.
+	    ] ifTrue:[
+		deviceMask := mask asFormOn:device.
+		deviceMask isNil ifTrue:[
+		    'DeviceGraphicsContext [warning]: cannot create device-mask' errorPrintCR.
+		    ^self
+		].
+		maskId := deviceMask id.
+		maskId notNil ifTrue:[
+		    deviceMask gcId isNil ifTrue:[deviceMask initGC].
+		    allColor := Color allColor.
+		    allBits := allColor colorId.
+
+		    (deviceForm depth == device depth
+		    and:[aForm maskedPixelsAre0]) ifTrue:[
+			"/ can do it without a temporary pixmap:
+			"/   or-in the form into the inverse stamped-out area
+			"/   of the destination.
+			"/   Oring is of course only possible if we know that
+			"/   masked pixels are already zero in the form.
+
+			"/ stamp out using mask
+			device setForeground:0 background:allBits in:gcId.
+			device setFunction:#and in:gcId.
+			device
+			    copyPlaneFromPixmapId:maskId
+			    x:0
+			    y:0
+			    gc:(deviceMask gcId)
+			    to:drawableId
+			    x:pX
+			    y:pY
+			    gc:gcId
+			    width:w
+			    height:h.
+			"/ or-in the form
+			device setFunction:#or in:gcId.
+			device
+			    copyFromPixmapId:id
+			    x:0
+			    y:0
+			    gc:deviceFormGCId
+			    to:drawableId
+			    x:pX
+			    y:pY
+			    gc:gcId
+			    width:w
+			    height:h.
+		    ] ifFalse:[
+			"/ must do it slow, using a temporary form ..
+
+			"
+			 create temp-form;
+			"
+			tmpForm := Form width:w height:h depth:device depth onDevice:device.
+			tmpForm isNil ifTrue:[
+			    'DeviceGraphicsContext [warning]: cannot create temp form' errorPrintCR.
+			    ^self
+			].
+			tmpForm initGC.
+			tmpId := tmpForm id.
+			tmpGCId := tmpForm gcId.
+
+			"
+			 fill tempform with image
+			"
+			aForm depth == 1 ifTrue:[
+			    (colorMap := aForm colorMap) notNil ifTrue:[
+				colorMap size < 2 ifTrue:[
+				    device
+					setForegroundColor:(colorMap at:1)
+					in:tmpGCId.
+				] ifFalse:[
+				    device
+					setForegroundColor:(colorMap at:2)
+					backgroundColor:(colorMap at:1)
+					in:tmpGCId.
+				]
+			    ].
+			    device
+				copyPlaneFromPixmapId:id
+				x:0
+				y:0
+				gc:deviceFormGCId
+				to:tmpId
+				x:0
+				y:0
+				gc:tmpGCId
+				width:w
+				height:h.
+			] ifFalse:[
+			    device
+				copyFromPixmapId:id
+				x:0
+				y:0
+				gc:deviceFormGCId
+				to:tmpId
+				x:0
+				y:0
+				gc:tmpGCId
+				width:w
+				height:h.
+			].
+
+			"
+			 stamp out mask in temp form
+			"
+			device setForeground:allBits background:0 in:tmpGCId.
+			device setFunction:#and in:tmpGCId.
+			device
+			    copyPlaneFromPixmapId:maskId
+			    x:0
+			    y:0
+			    gc:(deviceMask gcId)
+			    to:tmpId
+			    x:0
+			    y:0
+			    gc:tmpGCId
+			    width:w
+			    height:h.
+
+			"
+			 stamp out mask in destination
+			"
+			device setForeground:0 background:allBits in:gcId.
+			device setFunction:#and in:gcId.
+			device
+			    copyPlaneFromPixmapId:maskId
+			    x:0
+			    y:0
+			    gc:(deviceMask gcId)
+			    to:drawableId
+			    x:pX
+			    y:pY
+			    gc:gcId
+			    width:w
+			    height:h.
+
+			"
+			 or-in tempform-bits ...
+			"
+			device setFunction:#or in:gcId.
+			device
+			    copyFromPixmapId:tmpId
+			    x:0
+			    y:0
+			    gc:tmpGCId
+			    to:drawableId
+			    x:pX
+			    y:pY
+			    gc:gcId
+			    width:w
+			    height:h.
+
+			"
+			 release tempForm immediately
+			 (although GC will eventually do it,
+			  this creates less stress to the Xserver in the meanwhile ...)
+			"
+			tmpForm destroy.
+		    ].
+
+		    "/ restore GC
+		    foreground notNil ifTrue:[
+			device setForegroundColor:foreground in:gcId.
+		    ].
+		    background notNil ifTrue:[
+			device setBackgroundColor:background in:gcId
+		    ].
+		    device setFunction:function in:gcId.
+		    ^ self
+		]
+	    ]
+	].
+
+	device
+	    copyFromPixmapId:id
+	    x:0
+	    y:0
+	    gc:deviceForm gcId
+	    to:drawableId
+	    x:pX
+	    y:pY
+	    gc:gcId
+	    width:w
+	    height:h.
+	^ self
     ].
 
     "
@@ -2319,114 +2318,114 @@
      if paint is not a real color, we have to do it the hard way ...
     "
     easy ifTrue:[
-        paint isColor ifFalse:[
-            paintDither := paint.
-            easy := false
-        ] ifTrue:[
-            paintDither := paint ditherForm.
-            paintDither notNil ifTrue:[
-                easy := false.
-            ]
-        ].
+	paint isColor ifFalse:[
+	    paintDither := paint.
+	    easy := false
+	] ifTrue:[
+	    paintDither := paint ditherForm.
+	    paintDither notNil ifTrue:[
+		easy := false.
+	    ]
+	].
     ].
 
     allColor := Color allColor.
     allBits := allColor colorId.
 
     easy ifTrue:[
-        "
-         paint is a real color
-        "
-
-        "
-         if paint color is all-0 or all-1's, we can do it in one
-         operation ...
-        "
-        fgId := paint colorId.
-
-        ((fgId ~~ ((1 bitShift:device depth)-1))
-        and:[fgId ~~ allBits]) ifTrue:[
-            "
-             clear fg-bits ...
-            "
-            device setForeground:0 background:allBits in:gcId.
-            device setFunction:#and in:gcId.
-            device
-                copyPlaneFromPixmapId:id
-                x:0 
-                y:0 
-                gc:deviceFormGCId
-                to:drawableId
-                x:pX 
-                y:pY 
-                gc:gcId
-                width:w 
-                height:h.
-        ].
-
-        fgId ~~ 0 ifTrue:[
-            "
-             or-in fg-bits ...
-            "
-            device setForeground:fgId background:0 in:gcId.
-            device setFunction:#or in:gcId.
-            device
-                copyPlaneFromPixmapId:id
-                x:0 
-                y:0 
-                gc:deviceFormGCId
-                to:drawableId
-                x:pX 
-                y:pY 
-                gc:gcId
-                width:w 
-                height:h
-        ].
-        "
-         flush foreground/background cache
-        "
-        foreground := nil.
-        background := nil.
-        device setFunction:function in:gcId.
-        ^ self
+	"
+	 paint is a real color
+	"
+
+	"
+	 if paint color is all-0 or all-1's, we can do it in one
+	 operation ...
+	"
+	fgId := paint colorId.
+
+	((fgId ~~ ((1 bitShift:device depth)-1))
+	and:[fgId ~~ allBits]) ifTrue:[
+	    "
+	     clear fg-bits ...
+	    "
+	    device setForeground:0 background:allBits in:gcId.
+	    device setFunction:#and in:gcId.
+	    device
+		copyPlaneFromPixmapId:id
+		x:0
+		y:0
+		gc:deviceFormGCId
+		to:drawableId
+		x:pX
+		y:pY
+		gc:gcId
+		width:w
+		height:h.
+	].
+
+	fgId ~~ 0 ifTrue:[
+	    "
+	     or-in fg-bits ...
+	    "
+	    device setForeground:fgId background:0 in:gcId.
+	    device setFunction:#or in:gcId.
+	    device
+		copyPlaneFromPixmapId:id
+		x:0
+		y:0
+		gc:deviceFormGCId
+		to:drawableId
+		x:pX
+		y:pY
+		gc:gcId
+		width:w
+		height:h
+	].
+	"
+	 flush foreground/background cache
+	"
+	foreground := nil.
+	background := nil.
+	device setFunction:function in:gcId.
+	^ self
     ].
 
     function == #or ifTrue:[
-        easy := paint notNil
-                and:[paint isColor
-                and:[paint ditherForm isNil]].
-        easy ifTrue:[
-            easy := bgPaint isNil
-                        or:[bgPaint isColor
-                            and:[bgPaint colorId == 0]]
-        ].
-        easy ifTrue:[
-            fgId := paint colorId.
-
-            fgId ~~ 0 ifTrue:[
-                "
-                 or-in fg-bits ...
-                "
-                device setForeground:fgId background:0 in:gcId.
-                device
-                    copyPlaneFromPixmapId:id
-                    x:0 
-                    y:0 
-                    gc:deviceFormGCId
-                    to:drawableId
-                    x:pX 
-                    y:pY 
-                    gc:gcId
-                    width:w 
-                    height:h
-            ].
-            "
-             flush foreground/background cache
-            "
-            foreground := nil.
-            background := nil.
-            ^ self
-        ].
+	easy := paint notNil
+		and:[paint isColor
+		and:[paint ditherForm isNil]].
+	easy ifTrue:[
+	    easy := bgPaint isNil
+			or:[bgPaint isColor
+			    and:[bgPaint colorId == 0]]
+	].
+	easy ifTrue:[
+	    fgId := paint colorId.
+
+	    fgId ~~ 0 ifTrue:[
+		"
+		 or-in fg-bits ...
+		"
+		device setForeground:fgId background:0 in:gcId.
+		device
+		    copyPlaneFromPixmapId:id
+		    x:0
+		    y:0
+		    gc:deviceFormGCId
+		    to:drawableId
+		    x:pX
+		    y:pY
+		    gc:gcId
+		    width:w
+		    height:h
+	    ].
+	    "
+	     flush foreground/background cache
+	    "
+	    foreground := nil.
+	    background := nil.
+	    ^ self
+	].
     ].
 
     "
@@ -2440,8 +2439,8 @@
     "
     tmpForm := Form width:w height:h depth:device depth onDevice:device.
     tmpForm isNil ifTrue:[
-        'DeviceGraphicsContext [warning]: cannot create temp form' errorPrintCR.
-        ^self
+	'DeviceGraphicsContext [warning]: cannot create temp form' errorPrintCR.
+	^self
     ].
     "
      fill tempform
@@ -2460,16 +2459,16 @@
     device setForeground:0 background:allBits in:gcId.
     device setFunction:#and in:gcId.
     device
-        copyPlaneFromPixmapId:id
-        x:0 
-        y:0 
-        gc:deviceFormGCId
-        to:drawableId
-        x:pX 
-        y:pY 
-        gc:gcId
-        width:w 
-        height:h.
+	copyPlaneFromPixmapId:id
+	x:0
+	y:0
+	gc:deviceFormGCId
+	to:drawableId
+	x:pX
+	y:pY
+	gc:gcId
+	width:w
+	height:h.
     "
      or-in temp into destination
     "
@@ -2477,20 +2476,20 @@
     device setFunction:#or in:gcId.
 
     device
-        copyFromPixmapId:tmpForm id
-        x:0 
-        y:0 
-        gc:tmpForm gcId
-        to:drawableId
-        x:pX 
-        y:pY 
-        gc:gcId
-        width:w 
-        height:h.
+	copyFromPixmapId:tmpForm id
+	x:0
+	y:0
+	gc:tmpForm gcId
+	to:drawableId
+	x:pX
+	y:pY
+	gc:gcId
+	width:w
+	height:h.
 
     "
      release tempForm immediately
-     (although GC will eventually do it, 
+     (although GC will eventually do it,
       this creates less stress to the Xserver in the meanwhile ...)
     "
 
@@ -2516,20 +2515,20 @@
 !
 
 displayDeviceOpaqueForm:aForm x:x y:y
-    "draw a form or image opaque (i.e. both fg and bg is drawn); 
+    "draw a form or image opaque (i.e. both fg and bg is drawn);
      If its a 1-plane bitmap, 1-bits are drawn in the
      current paint-color and 0-bits in the bgPaint color.
      If its a deep form (i.e. a pixmap) the current paint/bgPaint
-     settings are ignored and the form drawn as-is. 
+     settings are ignored and the form drawn as-is.
      Any mask is ignored.
-     In the 1-plane case, special care must be taken if paint and/or bgPaint 
+     In the 1-plane case, special care must be taken if paint and/or bgPaint
      dithered colors or patterns, since are that the colors are correctly allocated (by sending #on:
      to the colors) before doing so.
      The form should have been allocated on the same device; otherwise,
      its converted here, which slows down the draw.
      Drawing is in device coordinates; no scaling is done."
 
-    |id w h easy savedPaint bgForm fgForm tmpForm 
+    |id w h easy savedPaint bgForm fgForm tmpForm
      fgId bgId noColor allColor allBits dx dy
      pX pY deviceDepth deviceForm|
 
@@ -2537,18 +2536,18 @@
     id := deviceForm id.
 
     "temporary ..."
-    (id isNil 
+    (id isNil
     or:[aForm graphicsDevice ~~ device]) ifTrue:[
-        deviceForm := deviceForm asFormOn:device.
-        id := deviceForm id.
-        id isNil ifTrue:[
-            'DeviceGraphicsContext [warning]: invalid form draw - ignored' errorPrintCR.
-            ^ self
-        ].
+	deviceForm := deviceForm asFormOn:device.
+	id := deviceForm id.
+	id isNil ifTrue:[
+	    'DeviceGraphicsContext [warning]: invalid form draw - ignored' errorPrintCR.
+	    ^ self
+	].
     ].
 
     gcId isNil ifTrue:[
-        self initGC
+	self initGC
     ].
     deviceForm gcId isNil ifTrue:[deviceForm initGC].
 
@@ -2563,25 +2562,25 @@
      and is always drawn opaque.
     "
     (aForm depth ~~ 1) ifTrue:[
-        device
-            copyFromPixmapId:id
-            x:0 
-            y:0 
-            gc:deviceForm gcId
-            to:drawableId
-            x:pX 
-            y:pY 
-            gc:gcId
-            width:w 
-            height:h.
-        ^ self
+	device
+	    copyFromPixmapId:id
+	    x:0
+	    y:0
+	    gc:deviceForm gcId
+	    to:drawableId
+	    x:pX
+	    y:pY
+	    gc:gcId
+	    width:w
+	    height:h.
+	^ self
     ].
 
     "/ if no bgPaint is set, this is a non-opaque draw
 
     bgPaint isNil ifTrue:[
-        self displayDeviceForm:aForm x:x y:y.
-        ^ self
+	self displayDeviceForm:aForm x:x y:y.
+	^ self
     ].
 
     "the following code is somewhat complicated, since it has to deal
@@ -2595,43 +2594,43 @@
     "
     easy := true.
     paint isColor ifFalse:[
-        easy := false
+	easy := false
     ] ifTrue:[
-        fgId := paint colorId.
-        fgId isNil ifTrue:[
-            easy := false
-        ]
+	fgId := paint colorId.
+	fgId isNil ifTrue:[
+	    easy := false
+	]
     ].
     bgPaint isColor ifFalse:[
-        easy := false
+	easy := false
     ] ifTrue:[
-        bgId := bgPaint colorId.
-        bgId isNil ifTrue:[
-            easy := false
-        ]
+	bgId := bgPaint colorId.
+	bgId isNil ifTrue:[
+	    easy := false
+	]
     ].
 
     easy ifTrue:[
-        "
-         easy: both paint and bgPaint are real colors
-        "
-        ((foreground ~~ paint) or:[background ~~ bgPaint]) ifTrue:[
-            device setForeground:fgId background:bgId in:gcId.
-            foreground := paint.
-            background := bgPaint.
-        ].
-        device
-            copyPlaneFromPixmapId:id
-            x:0 
-            y:0 
-            gc:(deviceForm gcId)
-            to:drawableId
-            x:pX 
-            y:pY 
-            gc:gcId
-            width:w 
-            height:h.
-        ^ self
+	"
+	 easy: both paint and bgPaint are real colors
+	"
+	((foreground ~~ paint) or:[background ~~ bgPaint]) ifTrue:[
+	    device setForeground:fgId background:bgId in:gcId.
+	    foreground := paint.
+	    background := bgPaint.
+	].
+	device
+	    copyPlaneFromPixmapId:id
+	    x:0
+	    y:0
+	    gc:(deviceForm gcId)
+	    to:drawableId
+	    x:pX
+	    y:pY
+	    gc:gcId
+	    width:w
+	    height:h.
+	^ self
     ].
 
     "
@@ -2642,120 +2641,120 @@
     deviceDepth := device depth.
 
     (fgId notNil and:[function == #copy]) ifTrue:[
-        "
-         only bg is dithered; fill with bg first ...
-        "
-        savedPaint := paint.
-        self paint:bgPaint.
-        self fillDeviceRectangleX:pX y:pY width:w height:h.
-        self paint:savedPaint.
-
-        "
-         if paint color is all-0 or all-1's, we can do it in one
-         operation ...
-        "
-        ((fgId ~~ ((1 bitShift:deviceDepth)-1))
-        and:[fgId ~~ allBits]) ifTrue:[
-            "
-             clear fg-bits ...
-            "
-            device setForeground:0 background:allBits in:gcId.
-            device setFunction:#and in:gcId.
-            device
-                copyPlaneFromPixmapId:id
-                x:0 
-                y:0 
-                gc:(deviceForm gcId)
-                to:drawableId
-                x:pX 
-                y:pY 
-                gc:gcId
-                width:w 
-                height:h
-        ].
-
-        fgId ~~ 0 ifTrue:[
-            "
-             or-in fg-bits ...
-            "
-            device setForeground:fgId background:0 in:gcId.
-            device setFunction:#or in:gcId.
-            device
-                copyPlaneFromPixmapId:id
-                x:0 
-                y:0 
-                gc:(deviceForm gcId)
-                to:drawableId
-                x:pX 
-                y:pY 
-                gc:gcId
-                width:w 
-                height:h
-        ].
-        "
-         flush foreground/background cache
-        "
-        foreground := nil.
-        background := nil.
-        device setFunction:function in:gcId.
-        ^ self
+	"
+	 only bg is dithered; fill with bg first ...
+	"
+	savedPaint := paint.
+	self paint:bgPaint.
+	self fillDeviceRectangleX:pX y:pY width:w height:h.
+	self paint:savedPaint.
+
+	"
+	 if paint color is all-0 or all-1's, we can do it in one
+	 operation ...
+	"
+	((fgId ~~ ((1 bitShift:deviceDepth)-1))
+	and:[fgId ~~ allBits]) ifTrue:[
+	    "
+	     clear fg-bits ...
+	    "
+	    device setForeground:0 background:allBits in:gcId.
+	    device setFunction:#and in:gcId.
+	    device
+		copyPlaneFromPixmapId:id
+		x:0
+		y:0
+		gc:(deviceForm gcId)
+		to:drawableId
+		x:pX
+		y:pY
+		gc:gcId
+		width:w
+		height:h
+	].
+
+	fgId ~~ 0 ifTrue:[
+	    "
+	     or-in fg-bits ...
+	    "
+	    device setForeground:fgId background:0 in:gcId.
+	    device setFunction:#or in:gcId.
+	    device
+		copyPlaneFromPixmapId:id
+		x:0
+		y:0
+		gc:(deviceForm gcId)
+		to:drawableId
+		x:pX
+		y:pY
+		gc:gcId
+		width:w
+		height:h
+	].
+	"
+	 flush foreground/background cache
+	"
+	foreground := nil.
+	background := nil.
+	device setFunction:function in:gcId.
+	^ self
     ].
 
     (bgId notNil and:[function == #copy]) ifTrue:[
-        "
-         only fg is dithered; fill with fg first ...
-        "
-        self fillDeviceRectangleX:pX y:pY width:w height:h.
-
-        "
-         if paint color is all-0 or all-1's, we can do it in one
-         operation ...
-        "
-        ((bgId ~~ ((1 bitShift:deviceDepth)-1))
-        and:[bgId ~~ allBits]) ifTrue:[
-            "
-             clear bg-bits ...
-            "
-            device setForeground:allBits background:0 in:gcId.
-            device setFunction:#and in:gcId.
-            device
-                copyPlaneFromPixmapId:id
-                x:0 
-                y:0 
-                gc:(deviceForm gcId)
-                to:drawableId
-                x:pX 
-                y:pY 
-                gc:gcId
-                width:w 
-                height:h
-        ].
-
-        "
-         or-in bg-bits ...
-        "
-        bgId ~~ 0 ifTrue:[
-            device setForeground:0 background:bgId in:gcId.
-            device setFunction:#or in:gcId.
-            device
-                copyPlaneFromPixmapId:id
-                x:0 
-                y:0 
-                gc:(deviceForm gcId)
-                to:drawableId
-                x:pX 
-                y:pY 
-                gc:gcId
-                width:w 
-                height:h
-        ].
-        "
-         flush foreground/background cache
-        "
-        foreground := nil.
-        background := nil.
-        device setFunction:function in:gcId.
-        ^ self
+	"
+	 only fg is dithered; fill with fg first ...
+	"
+	self fillDeviceRectangleX:pX y:pY width:w height:h.
+
+	"
+	 if paint color is all-0 or all-1's, we can do it in one
+	 operation ...
+	"
+	((bgId ~~ ((1 bitShift:deviceDepth)-1))
+	and:[bgId ~~ allBits]) ifTrue:[
+	    "
+	     clear bg-bits ...
+	    "
+	    device setForeground:allBits background:0 in:gcId.
+	    device setFunction:#and in:gcId.
+	    device
+		copyPlaneFromPixmapId:id
+		x:0
+		y:0
+		gc:(deviceForm gcId)
+		to:drawableId
+		x:pX
+		y:pY
+		gc:gcId
+		width:w
+		height:h
+	].
+
+	"
+	 or-in bg-bits ...
+	"
+	bgId ~~ 0 ifTrue:[
+	    device setForeground:0 background:bgId in:gcId.
+	    device setFunction:#or in:gcId.
+	    device
+		copyPlaneFromPixmapId:id
+		x:0
+		y:0
+		gc:(deviceForm gcId)
+		to:drawableId
+		x:pX
+		y:pY
+		gc:gcId
+		width:w
+		height:h
+	].
+	"
+	 flush foreground/background cache
+	"
+	foreground := nil.
+	background := nil.
+	device setFunction:function in:gcId.
+	^ self
     ].
 
     "
@@ -2775,8 +2774,8 @@
     "
     dx := dy := 0.
     maskOrigin notNil ifTrue:[
-        dx := maskOrigin x.
-        dy := maskOrigin y
+	dx := maskOrigin x.
+	dy := maskOrigin y
     ].
 
     bgForm paint:bgPaint.
@@ -2819,20 +2818,20 @@
     "
     device setForeground:0 background:allBits in:gcId.
     device
-        copyFromPixmapId:tmpForm id
-        x:0 
-        y:0 
-        gc:tmpForm gcId
-        to:drawableId
-        x:pX 
-        y:pY 
-        gc:gcId
-        width:w 
-        height:h.
+	copyFromPixmapId:tmpForm id
+	x:0
+	y:0
+	gc:tmpForm gcId
+	to:drawableId
+	x:pX
+	y:pY
+	gc:gcId
+	width:w
+	height:h.
 
     "
      release tempForms immediately
-     (although GC will eventually do it, 
+     (although GC will eventually do it,
       this creates less stress to the Xserver in the meanwhile ...)
     "
     fgForm destroy.
@@ -2848,7 +2847,7 @@
     "Modified: 22.4.1997 / 21:44:10 / cg"
 !
 
-displayDeviceOpaqueString:aString from:index1 to:index2 in:font x:x y:y
+displayDeviceOpaqueString:aStringArg from:index1 to:index2 in:font x:x y:y
     "draw a substring at the coordinate x/y - draw foreground pixels in
      paint-color and background pixels in bgPaint-color.
      Assuming that device can only draw in device colors, we have to handle
@@ -2856,7 +2855,7 @@
      No translation or scaling is done."
 
     |easy w h savedPaint fgId bgId allColor allBits noColor
-     id bgForm fgForm tmpForm maskForm dx dy pX pY fontUsed s
+     id bgForm fgForm tmpForm maskForm dx dy pX pY fontUsed aString
      deviceDepth fontsEncoding ascent|
 
     "
@@ -2864,23 +2863,34 @@
      this is a non-opaque draw
     "
     bgPaint isNil ifTrue:[
-        self displayDeviceString:aString from:index1 to:index2 x:x y:y.
+        self displayDeviceString:aStringArg from:index1 to:index2 x:x y:y.
         ^ self
     ].
 
-    (aString isString not
-    or:[aString isText]) ifTrue:[
+    (aStringArg isString not or:[aStringArg isText]) ifTrue:[
         "
          hook for non-strings (i.e. attributed text)
          that 'thing' should know how to display itself ...
         "
-        aString displayOpaqueOn:self x:x y:y from:index1 to:index2.
+        aStringArg displayOpaqueOn:self x:x y:y from:index1 to:index2.
         ^ self
     ].
 
     pX := x rounded.
     pY := y rounded.
 
+    aString := aStringArg.
+    fontsEncoding := font encoding.
+    (characterEncoding ~~ fontsEncoding) ifTrue:[
+        [
+            aString := CharacterEncoder encodeString:aString from:characterEncoding into:fontsEncoding.
+        ] on:CharacterEncoderError do:[:ex|
+            "substitute a default value for codes that cannot be represented
+             in the new character set"
+            ex proceedWith:ex defaultValue.
+        ].
+    ].
+
     font isAlienFont ifTrue:[
         "
          hook for alien fonts
@@ -2894,20 +2904,7 @@
         self initGC
     ].
 
-
-    s := aString.
     fontUsed := font onDevice:device.
-    fontsEncoding := fontUsed encoding.
-    (characterEncoding ~~ fontsEncoding) ifTrue:[
-        [
-            s := CharacterEncoder encodeString:s from:characterEncoding into:fontsEncoding.
-        ] on:CharacterEncoderError do:[:ex|
-            "substitute a default value for codes that cannot be represented
-             in the new character set"
-            ex proceedWith:ex defaultValue.
-        ].
-    ].
-
     id := fontUsed fontId.
     id isNil ifTrue:[
         "this should not happen, since #onDevice tries replacement fonts"
@@ -2945,11 +2942,11 @@
         device setForeground:fgId background:bgId in:gcId.
         foreground := paint.
         background := bgPaint.
-        device displayOpaqueString:s from:index1 to:index2 x:pX y:pY in:drawableId with:gcId.
+        device displayOpaqueString:aString from:index1 to:index2 x:pX y:pY in:drawableId with:gcId.
         ^ self
     ].
 
-    w := fontUsed widthOf:s from:index1 to:index2.
+    w := fontUsed widthOf:aString from:index1 to:index2.
     h := fontUsed height.
     ascent := fontUsed ascent.
 
@@ -2965,7 +2962,7 @@
         "
          then draw using fgPaint (which is a real color)
         "
-        device displayString:s from:index1 to:index2 x:pX y:pY in:drawableId with:gcId.
+        device displayString:aString from:index1 to:index2 x:pX y:pY in:drawableId with:gcId.
         ^ self
     ].
 
@@ -2997,9 +2994,9 @@
 "/          "
 "/          device setForeground:allBits background:0 in:gcId.
 "/          device setFunction:#and in:gcId.
-"/          device displayOpaqueString:s 
+"/          device displayOpaqueString:s
 "/                                from:index1 to:index2
-"/                                   x:pX y:pY 
+"/                                   x:pX y:pY
 "/                                  in:drawableId with:gcId.
 "/      ].
 "/
@@ -3009,9 +3006,9 @@
 "/      bgId ~~ 0 ifTrue:[
 "/          device setForeground:0 background:bgId in:gcId.
 "/          device setFunction:#or in:gcId.
-"/          device displayOpaqueString:s 
+"/          device displayOpaqueString:s
 "/                                from:index1 to:index2
-"/                                   x:pX y:pY 
+"/                                   x:pX y:pY
 "/                                  in:drawableId with:gcId.
 "/      ].
 "/      "
@@ -3042,7 +3039,7 @@
             ].
         ].
 
-        device displayString:s from:index1 to:index2 x:pX y:pY in:drawableId with:gcId.
+        device displayString:aString from:index1 to:index2 x:pX y:pY in:drawableId with:gcId.
         ^ self.
     ].
 
@@ -3083,14 +3080,14 @@
     bgForm font:fontUsed.
     bgForm paint:noColor on:allColor.
     bgForm function:#and.
-    bgForm displayString:s from:index1 to:index2 x:0 y:ascent.
+    bgForm displayString:aString from:index1 to:index2 x:0 y:ascent.
 
     "
      stamp-out foreground
     "
     maskForm font:fontUsed.
     maskForm paint:allColor on:noColor.
-    maskForm displayOpaqueString:s from:index1 to:index2 x:0 y:ascent.
+    maskForm displayOpaqueString:aString from:index1 to:index2 x:0 y:ascent.
 
     fgForm function:#and.
     fgForm copyFrom:maskForm x:0 y:0 toX:0 y:0 width:w height:h.
@@ -3121,7 +3118,7 @@
 
     "
      release tempForms immediately
-     (although GC will eventually do it, 
+     (although GC will eventually do it,
       this creates less stress to the Xserver in the meanwhile ...)
     "
     tmpForm destroy.
@@ -3156,50 +3153,49 @@
     self displayDeviceOpaqueString:aString from:1 to:(aString size) in:font x:x y:y
 !
 
-displayDeviceString:aString from:index1 to:index2 in:font x:x y:y
-    "draw a substring at the coordinate x/y -  
+displayDeviceString:aStringArg from:index1 to:index2 in:font x:x y:y
+    "draw a substring at the coordinate x/y -
      draw foreground-pixels only (in current paint-color), leaving background as-is.
      No translation or scaling is done"
 
-    |id pX pY fontUsed s fontsEncoding|
+    |id pX pY fontUsed aString fontsEncoding|
 
     "
      hook for non-strings (i.e. attributed text)
     "
-    (aString isString not
-    or:[aString isText]) ifTrue:[
-        ^ aString displayOn:self x:x y:y from:index1 to:index2
+    (aStringArg isString not or:[aStringArg isText]) ifTrue:[
+        ^ aStringArg displayOn:self x:x y:y from:index1 to:index2
     ].
 
     pX := x rounded.
     pY := y rounded.
 
+    gcId isNil ifTrue:[
+        self initGC
+    ].
+
+    aString := aStringArg.
+    fontsEncoding := font encoding.
+    (characterEncoding ~~ fontsEncoding) ifTrue:[
+        [
+            aString := CharacterEncoder encodeString:aString from:characterEncoding into:fontsEncoding.
+        ] on:CharacterEncoderError do:[:ex|
+            "substitute a default value for codes that cannot be represented
+             in the new character set"
+            ex proceedWith:ex defaultValue.
+        ].
+    ].
+
     font isAlienFont ifTrue:[
         "
          hook for alien fonts
          that 'font' should know how to display the string ...
         "
-        font displayOpaqueString:aString from:index1 to:index2 x:pX y:pY in:self.
+        font displayString:aString from:index1 to:index2 x:pX y:pY in:self.
         ^ self
     ].
 
-    gcId isNil ifTrue:[
-        self initGC
-    ].
-
-    s := aString.
     fontUsed := font onDevice:device.
-    fontsEncoding := fontUsed encoding.
-    (characterEncoding ~~ fontsEncoding) ifTrue:[
-        [
-            s := CharacterEncoder encodeString:s from:characterEncoding into:fontsEncoding.
-        ] on:CharacterEncoderError do:[:ex|
-            "substitute a default value for codes that cannot be represented
-             in the new character set"
-            ex proceedWith:ex defaultValue.
-        ].
-    ].
-
     id := fontUsed fontId.
     id isNil ifTrue:[
         "this should not happen, since #onDevice tries replacement fonts"
@@ -3210,14 +3206,14 @@
             device setFont:id in:gcId.
             deviceFont := fontUsed
         ].
-        device displayString:s from:index1 to:index2 x:pX y:pY in:drawableId with:gcId
+        device displayString:aString from:index1 to:index2 x:pX y:pY in:drawableId with:gcId
     ]
 
     "Modified: 1.7.1997 / 17:08:48 / cg"
 !
 
 displayDeviceString:aString from:index1 to:index2 x:x y:y
-    "draw a substring at the coordinate x/y -  
+    "draw a substring at the coordinate x/y -
      draw foreground-pixels only (in current paint-color), leaving background as-is.
      No translation or scaling is done"
 
@@ -3225,7 +3221,7 @@
 !
 
 displayDeviceString:aString x:x y:y
-    "draw a string at the coordinate x/y -  
+    "draw a string at the coordinate x/y -
      draw foreground-pixels only (in current paint-color), leaving background as-is.
      No translation or scaling is done"
 
@@ -3240,7 +3236,7 @@
 	self initGC
     ].
     device
-	fillRectangleX:x 
+	fillRectangleX:x
 		     y:y
 		 width:w
 		height:h
@@ -3345,17 +3341,17 @@
     bgPixel := device whitepixel.
 
     gcId isNil ifTrue:[
-        self initGC
+	self initGC
     ].
     oldFunction := function.
     device setForeground:(fgPixel bitXor:bgPixel)
-              background:bgPixel
-                      in:gcId.
+	      background:bgPixel
+		      in:gcId.
     device setFunction:#xor in:gcId.
     aBlock value.
 
     paint := bgPaint := nil.        "invalidate"
-    foreground := device blackColor.   
+    foreground := device blackColor.
     background := device whiteColor.
     device setForeground:fgPixel background:bgPixel in:gcId.
     device setFunction:oldFunction in:gcId.
@@ -3399,11 +3395,11 @@
 	nW := transformation applyScaleX:w.
 	nH := transformation applyScaleY:h.
 	nW < 0 ifTrue:[
-	      nW := nW abs.  
+	      nW := nW abs.
 	      pX := pX - nW.
 	].
 	nH < 0 ifTrue:[
-	      nH := nH abs.  
+	      nH := nH abs.
 	      pY := pY - nH.
 	].
     ] ifFalse:[
@@ -3424,10 +3420,10 @@
     a isInteger ifFalse:[a := a asFloat].
 
     device
-	  fillArcX:pX 
-		 y:pY 
+	  fillArcX:pX
+		 y:pY
 	     width:nW
-	    height:nH 
+	    height:nH
 	      from:sA
 	     angle:a
 		in:drawableId
@@ -3443,24 +3439,24 @@
     |newPolygon|
 
     gcId isNil ifTrue:[
-        self initGC
+	self initGC
     ].
     transformation notNil ifTrue:[
-        newPolygon := aPolygon collect:[:point | transformation applyTo:point].
+	newPolygon := aPolygon collect:[:point | transformation applyTo:point].
     ] ifFalse:[
-        newPolygon := aPolygon
+	newPolygon := aPolygon
     ].
-    (newPolygon contains:[:p | 
-        (p isPoint not 
-        or:[(p x class ~~ SmallInteger)
-        or:[(p y class ~~ SmallInteger)]])
+    (newPolygon contains:[:p |
+	(p isPoint not
+	or:[(p x class ~~ SmallInteger)
+	or:[(p y class ~~ SmallInteger)]])
      ]) ifTrue:[
-        newPolygon := newPolygon collect:[:p | p asPoint rounded]
+	newPolygon := newPolygon collect:[:p | p asPoint rounded]
     ].
     device
-        fillPolygon:newPolygon
-                 in:drawableId
-               with:gcId
+	fillPolygon:newPolygon
+		 in:drawableId
+	       with:gcId
 !
 
 fillRectangleX:x y:y width:w height:h
@@ -3477,11 +3473,11 @@
 	nW := transformation applyScaleX:w.
 	nH := transformation applyScaleY:h.
 	nW < 0 ifTrue:[
-	      nW := nW abs.  
+	      nW := nW abs.
 	      pX := pX - nW.
 	].
 	nH < 0 ifTrue:[
-	      nH := nH abs.  
+	      nH := nH abs.
 	      pY := pY - nH.
 	].
     ] ifFalse:[
@@ -3496,15 +3492,40 @@
     nH := nH rounded.
 
     device
-	fillRectangleX:pX 
-		     y:pY 
-		 width:nW 
-		height:nH 
+	fillRectangleX:pX
+		     y:pY
+		 width:nW
+		height:nH
 		    in:drawableId with:gcId
 
     "Modified: 4.6.1996 / 17:58:49 / cg"
 ! !
 
+!DeviceGraphicsContext methodsFor:'finalization'!
+
+executor
+    drawableType == #window ifTrue:[
+        ^ DeviceWindowGCHandle basicNew
+            setDevice:self graphicsDevice id:self drawableId gcId:self gcId parentId:parentId.
+    ] ifFalse:[
+        ^ DevicePixmapGCHandle basicNew
+            setDevice:self graphicsDevice id:self drawableId gcId:self gcId.
+    ].
+!
+
+finalizationLobby
+    "answer the registry used for finalization.
+     DeviceGraphicContexts have their own Registry"
+
+    ^ Lobby
+!
+
+registerChange
+    "register a change with the finalizationLobby"
+
+    Lobby registerChange:self.
+! !
+
 !DeviceGraphicsContext methodsFor:'initialization & release'!
 
 close
@@ -3521,38 +3542,30 @@
      really drawn, none is created up to the first draw.
      This method is sent, when the first drawing happens"
 
-    gcId := device gcFor:drawableId.
+    drawableType == #pixmap ifTrue:[
+        gcId := device gcForBitmap:drawableId.
+    ] ifFalse:[
+        gcId := device gcFor:drawableId.
+    ].
     Lobby registerChange:self.
 
     "Modified: 19.3.1997 / 11:07:52 / cg"
 !
 
-createGCForBitmap
-    "physically create a device GC.
-     Since we do not need a gc-object for the drawable until something is
-     really drawn, none is created up to the first draw.
-     This method is sent, when the first drawing happens.
-     Redefined here to create a bitmap GC (some devices (i.e. windows) require
-     different GC's for different canvases."
-
-    gcId := device gcForBitmap:drawableId.
-    Lobby registerChange:self.
-!
-
 destroy
-    "I am abstract"
-
-    self subclassResponsibility.
-
-"/    "when the drawable is destroyed, the associated GC must be destroyed with it"
-"/
-"/    gcId notNil ifTrue:[
-"/        device destroyGC:gcId.
-"/        gcId := nil.
-"/        Lobby registerChange:self.
-"/    ]
-
-    "Modified: 2.4.1997 / 19:37:53 / cg"
+    |id|
+
+    self destroyGC .
+    id := drawableId.
+    id notNil ifTrue:[
+        drawableId := nil.
+        drawableType == #window ifTrue:[
+            device destroyView:nil withId:id.
+        ] ifFalse:[
+            device destroyPixmap:id.
+        ].
+    ].
+    Lobby unregister:self.
 !
 
 destroyGC
@@ -3560,21 +3573,9 @@
 
     id := gcId.
     id notNil ifTrue:[
-        gcId := nil.
-        device destroyGC:id.
-    ].
-    (id := drawableId) notNil ifTrue:[
-        drawableId := nil.
-        device destroyView:self withId:id.
+	gcId := nil.
+	device destroyGC:id.
     ].
-    Lobby unregister:self.
-!
-
-finalizationLobby
-    "answer the registry used for finalization.
-     DeviceGraphicContexts have their own Registry"
-
-    ^ Lobby
 !
 
 initGC
@@ -3634,11 +3635,11 @@
     paint := nil.
     self paint:p.
 
-    ((lineWidth ~~ 0) 
-    or:[(lineStyle ~~ #solid) 
+    ((lineWidth ~~ 0)
+    or:[(lineStyle ~~ #solid)
     or:[(capStyle ~~ #butt)
     or:[joinStyle ~~ #miter]]]) ifTrue:[
-        device setLineWidth:lineWidth 
+        device setLineWidth:lineWidth
                       style:lineStyle
                         cap:capStyle
                        join:joinStyle
@@ -3657,7 +3658,7 @@
     ].
     (function ~~ #copy) ifTrue:[device setFunction:function in:gcId].
 
-    "defer the getting of a device font 
+    "defer the getting of a device font
      - this is now done when the first drawstring occurs,
      since many views (layout-views) will never draw strings and
      therefore, the overhead of aquiring a font can be avoided.
@@ -3689,14 +3690,14 @@
     "/ just in case, someone redefined new without setting device
     (device isNil and:[Screen notNil]) ifTrue:[device := Screen current].
 
-    foreground isNil ifTrue:[foreground := Black].
-    background isNil ifTrue:[background := White].
+    foreground isNil ifTrue:[foreground := self blackColor].
+    background isNil ifTrue:[background := self whiteColor].
 
     "Modified: 10.1.1997 / 17:46:51 / cg"
 !
 
 prepareForReinit
-    "kludge - clear drawableId and gcId 
+    "kludge - clear drawableId and gcId
      needed after snapin"
 
     gcId := nil.
@@ -3708,6 +3709,7 @@
     "sent after a snapin or a migration, reinit draw stuff for new device"
 
     gcId := nil.
+    drawableId := nil.
     foreground notNil ifTrue:[
         foreground := foreground onDevice:device
     ].
@@ -3727,15 +3729,8 @@
     "Modified: 28.10.1996 / 13:25:02 / cg"
 !
 
-reinitialize
-    'DeviceGraphicsContext [warning]: reinit of ' errorPrint. self classNameWithArticle errorPrint.
-    ' failed' errorPrintCR
-
-    "Modified: 10.1.1997 / 17:47:06 / cg"
-!
-
 releaseGC
-    "destroy the associated device GC resource - can be done to be nice to the 
+    "destroy the associated device GC resource - can be done to be nice to the
      display if you know that you are done with a drawable."
 
     |id|
@@ -3744,9 +3739,9 @@
 
     id := gcId.
     id notNil ifTrue:[
-        gcId := nil.
-        device destroyGC:id.
-        Lobby registerChange:self.
+	gcId := nil.
+	device destroyGC:id.
+	Lobby registerChange:self.
     ].
 
     "Created: 11.6.1996 / 22:07:30 / cg"
@@ -3771,67 +3766,67 @@
     |dither map pixelId p fg bg vOrg ditherDepth deviceDepth|
 
     gcId notNil ifTrue:[
-        paint isSymbol ifTrue:[
-            "map symbols to colors"
-            paint := Color perform:paint ifNotUnderstood:[Color yellow].
-        ].
-        p := paint. 
-
-        p isColor ifTrue:[
-            paint := p := p onDevice:device.
-            pixelId := p colorId.
-            pixelId notNil ifTrue:[
-                "
-                 a real (undithered) color
-                "
-                mask notNil ifTrue:[
-                    mask := nil.
-                    device setBitmapMask:nil in:gcId
-                ]. 
-                (p ~~ foreground) ifTrue:[
-                    foreground := paint.
-                    device setForeground:pixelId in:gcId
-                ].
-                ^ self
-            ].
-            "a dithered color"
-            dither := paint ditherForm.
-        ] ifFalse:[
-            "mhmh - seems to be some kind of form ..."
-            paint := paint onDevice:device.
-            dither := paint.
-        ].
-        "
-         a dithered color or image
-        "
-        (ditherDepth := dither depth) == 1 ifTrue:[
-            "a simple 0/1 bitmap"
-            map := dither colorMap.
-            "temporary (kludgy) fix for destroyed paint"
-            p := paint.
-            map isNil ifTrue:[
-                fg := Color black.
-                bg := Color white.
-            ] ifFalse:[
-                fg := map at:2.
-                bg := map at:1.
-            ].
-            self foreground:fg background:bg.
-            paint := p
-        ] ifFalse:[
-            deviceDepth := device depth.
-            (ditherDepth ~~ deviceDepth) ifTrue:[
-                dither := dither asFormOn:device.
-                ditherDepth := dither depth.
-                (dither isNil or:[ditherDepth ~~ deviceDepth]) ifTrue:[
-                    self error:'bad dither'.
-                    ^ self
-                ]
-            ]
-        ].
-        self mask:dither.
-        vOrg := self viewOrigin.
-        self maskOriginX:vOrg x negated y:vOrg y negated.
+	paint isSymbol ifTrue:[
+	    "map symbols to colors"
+	    paint := Color perform:paint ifNotUnderstood:[Color yellow].
+	].
+	p := paint.
+
+	p isColor ifTrue:[
+	    paint := p := p onDevice:device.
+	    pixelId := p colorId.
+	    pixelId notNil ifTrue:[
+		"
+		 a real (undithered) color
+		"
+		mask notNil ifTrue:[
+		    mask := nil.
+		    device setBitmapMask:nil in:gcId
+		].
+		(p ~~ foreground) ifTrue:[
+		    foreground := paint.
+		    device setForeground:pixelId in:gcId
+		].
+		^ self
+	    ].
+	    "a dithered color"
+	    dither := paint ditherForm.
+	] ifFalse:[
+	    "mhmh - seems to be some kind of form ..."
+	    paint := paint onDevice:device.
+	    dither := paint.
+	].
+	"
+	 a dithered color or image
+	"
+	(ditherDepth := dither depth) == 1 ifTrue:[
+	    "a simple 0/1 bitmap"
+	    map := dither colorMap.
+	    "temporary (kludgy) fix for destroyed paint"
+	    p := paint.
+	    map isNil ifTrue:[
+		fg := Color black.
+		bg := Color white.
+	    ] ifFalse:[
+		fg := map at:2.
+		bg := map at:1.
+	    ].
+	    self foreground:fg background:bg.
+	    paint := p
+	] ifFalse:[
+	    deviceDepth := device depth.
+	    (ditherDepth ~~ deviceDepth) ifTrue:[
+		dither := dither asFormOn:device.
+		ditherDepth := dither depth.
+		(dither isNil or:[ditherDepth ~~ deviceDepth]) ifTrue:[
+		    self error:'bad dither'.
+		    ^ self
+		]
+	    ]
+	].
+	self mask:dither.
+	vOrg := self viewOrigin.
+	self maskOriginX:vOrg x negated y:vOrg y negated.
     ]
 
     "Created: 16.5.1996 / 15:35:51 / cg"
@@ -3908,24 +3903,31 @@
 
 createBitmapFromArray:data width:width height:height
     "create a bitmap from data and set the drawableId"
-    
+
     drawableId := device createBitmapFromArray:data width:width height:height.
+    drawableType := #pixmap.
+    Lobby registerChange:self.
 !
 
 createPixmapWidth:w height:h depth:d
     "create a pixmap and set the drawableId"
-    
+
     drawableId := device createPixmapWidth:w height:h depth:d.
+    drawableType := #pixmap.
+    Lobby registerChange:self.
 !
 
-createRootWindow
-    drawableId := device rootWindowFor:self.
+createRootWindowFor:aView
+    drawableId := device rootWindowFor:aView.
+    drawableType := #window.
 !
 
-createWindowFor:aView type:typeSymbol origin:org extent:ext minExtent:minE maxExtent:maxE borderWidth:bw subViewOf:sv style:styleSymbol inputOnly:inp label:label owner:owner icon:icn iconMask:icnM iconView:icnV 
+createWindowFor:aView type:typeSymbol origin:org extent:ext minExtent:minE maxExtent:maxE borderWidth:bw subViewOf:sv style:styleSymbol inputOnly:inp label:label owner:owner icon:icn iconMask:icnM iconView:icnV
     "create a window and set the drawableId"
-    
-    drawableId := device 
+
+    |container|
+
+    drawableId := device
             createWindowFor:aView
             type:typeSymbol
             origin:org
@@ -3941,6 +3943,11 @@
             icon:icn
             iconMask:icnM
             iconView:icnV.
+
+    drawableType := #window.
+    container := aView container.
+    container notNil ifTrue:[ parentId := container id ].
+    Lobby registerChange:self.
 ! !
 
 !DeviceGraphicsContext methodsFor:'view properties'!
@@ -3950,7 +3957,7 @@
      how may true/false, but also #always, #whenMapped or #never."
 
     drawableId notNil ifTrue:[
-        device setBackingStore:how in:drawableId
+	device setBackingStore:how in:drawableId
     ]
 !
 
@@ -3959,7 +3966,7 @@
      when the view is resized."
 
     drawableId notNil ifTrue:[
-        device setBitGravity:gravity in:drawableId
+	device setBitGravity:gravity in:drawableId
     ]
 !
 
@@ -3968,13 +3975,13 @@
      - used for temporary views (i.e. PopUps and ModalBoxes)"
 
     drawableId notNil ifTrue:[
-        device setSaveUnder:aBoolean in:drawableId
+	device setSaveUnder:aBoolean in:drawableId
     ]
 !
 
 setCursorId:id
     drawableId notNil ifTrue:[
-        device setCursor:id in:drawableId.
+	device setCursor:id in:drawableId.
     ]
 !
 
@@ -3985,7 +3992,7 @@
      Smalltalk is used"
 
     drawableId notNil ifTrue:[
-        device setWindowPid:pid in:drawableId.
+	device setWindowPid:pid in:drawableId.
     ].
 !
 
@@ -3994,7 +4001,7 @@
      when the superView is resized."
 
     drawableId notNil ifTrue:[
-        device setWindowGravity:gravity in:drawableId
+	device setWindowGravity:gravity in:drawableId
     ].
 !
 
@@ -4002,7 +4009,7 @@
     "set the windows border shape"
 
     drawableId notNil ifTrue:[
-        device setWindowBorderShape:(aForm id) in:drawableId
+	device setWindowBorderShape:(aForm id) in:drawableId
     ].
 !
 
@@ -4012,7 +4019,7 @@
      select client specific resources."
 
     drawableId notNil ifTrue:[
-        device setWindowClass:windowClassNameString name:nameString in:drawableId.
+	device setWindowClass:windowClassNameString name:nameString in:drawableId.
     ].
 !
 
@@ -4020,7 +4027,7 @@
     "define the views name in the windows title area."
 
     drawableId notNil ifTrue: [
-        device setWindowName:aString in:drawableId.
+	device setWindowName:aString in:drawableId.
     ]
 !
 
@@ -4030,19 +4037,104 @@
      X shape extension."
 
     drawableId notNil ifTrue:[
-        ^ device setWindowShape:(aForm id) in:drawableId
+	^ device setWindowShape:(aForm id) in:drawableId
     ].
     ^ false.
 ! !
 
+!DeviceGraphicsContext::DevicePixmapGCHandle methodsFor:'accessing'!
+
+parentId
+    "pixmaps do not have a parent"
+
+    ^ nil
+! !
+
+!DeviceGraphicsContext::DevicePixmapGCHandle methodsFor:'finalization'!
+
+finalize
+    "the Form for which I am a handle has been collected - tell it to the x-server"
+
+    |id|
+
+    drawableId notNil ifTrue:[
+	(id := gcId) notNil ifTrue:[
+	    gcId := nil.
+	    device destroyGC:id.
+	].
+	id := drawableId.
+	drawableId := nil.
+	device destroyPixmap:id.
+    ]
+! !
+
+!DeviceGraphicsContext::DeviceWindowGCHandle methodsFor:'accessing'!
+
+parentId
+    ^ parentId
+! !
+
+!DeviceGraphicsContext::DeviceWindowGCHandle methodsFor:'finalization'!
+
+finalize
+    "the view for which I am a handle was collected
+     - release system resources"
+
+    drawableId notNil ifTrue:[
+	[
+	    (device viewIdKnown:drawableId) ifTrue:[
+"/ 'Display [info]: recycled view (' infoPrint. v infoPrint. ') not destroyed: ' infoPrint.
+"/ drawableId displayString infoPrintCR.
+		drawableId := nil.
+	    ] ifFalse:[
+		|id|
+
+		(id := gcId) notNil ifTrue:[
+		    gcId := nil.
+		    device deviceIOErrorSignal handle:[:ex |
+		    ] do:[
+			device destroyGC:id.
+		    ]
+		].
+
+		id := drawableId.
+		drawableId := nil.
+		device deviceIOErrorSignal handle:[:ex |
+		] do:[
+		    device destroyView:nil withId:id.
+		].
+
+		"When a window ist destroyed, all its subwindows are also destroyed.
+		 Unregister all the subwindows, to avoid destroying of reused windoeIds
+		 later."
+		DeviceGraphicsContext cleanupLobbyForChildrenOfViewWithDevice:device id:id.
+	    ]
+	] valueUninterruptably.
+    ].
+
+    "Created: / 25.9.1997 / 10:01:46 / stefan"
+    "Modified: / 15.11.2001 / 14:17:12 / cg"
+! !
+
+!DeviceGraphicsContext::DeviceWindowGCHandle methodsFor:'private-accessing'!
+
+setDevice:aDevice id:aDrawableId gcId:aGCId parentId:parentIdArg
+    "set the handles contents"
+
+    device := aDevice.
+    drawableId := aDrawableId.
+    gcId := aGCId.
+    parentId := parentIdArg.
+! !
+
 !DeviceGraphicsContext class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/DeviceGraphicsContext.st,v 1.132 2014-02-04 15:53:01 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/DeviceGraphicsContext.st,v 1.137.2.1 2014-05-08 08:27:50 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/DeviceGraphicsContext.st,v 1.132 2014-02-04 15:53:01 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/DeviceGraphicsContext.st,v 1.137.2.1 2014-05-08 08:27:50 stefan Exp $'
 ! !
 
 
--- a/DeviceHandle.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/DeviceHandle.st	Thu May 08 10:27:51 2014 +0200
@@ -9,11 +9,10 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
-
 "{ Package: 'stx:libview' }"
 
 Object subclass:#DeviceHandle
-	instanceVariableNames:'device parentId drawableId gcId'
+	instanceVariableNames:'device drawableId gcId'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Graphics-Support'
@@ -66,10 +65,6 @@
     ^ drawableId
 
     "Modified: 20.3.1997 / 16:34:00 / cg"
-!
-
-parentId
-    ^ parentId
 ! !
 
 !DeviceHandle methodsFor:'finalization'!
@@ -92,19 +87,11 @@
     gcId := aGCId
 
     "Modified: 23.4.1996 / 22:10:26 / cg"
-!
-
-setDevice:aDevice id:aDrawableId gcId:aGCId parentId:parentIdArg
-    "set the handles contents"
-
-    device := aDevice.
-    drawableId := aDrawableId.
-    gcId := aGCId.
-    parentId := parentIdArg.
 ! !
 
 !DeviceHandle class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/DeviceHandle.st,v 1.14 2005-12-13 19:07:31 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/DeviceHandle.st,v 1.16.2.1 2014-05-08 08:27:50 stefan Exp $'
 ! !
+
--- a/DisplayRootView.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/DisplayRootView.st	Thu May 08 10:27:51 2014 +0200
@@ -9,6 +9,8 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 17-03-2014 at 20:22:04'                   !
+
 "{ Package: 'stx:libview' }"
 
 DisplaySurface subclass:#DisplayRootView
@@ -171,12 +173,12 @@
 
     |dev|
 
-    dev := self device.
+    self recreate.
+    self createRootWindow.
+    dev := self graphicsDevice.
     width := dev width.
     height := dev height.
-    self createRootWindow.
     realized := true.
-    gcId := nil.
 ! !
 
 !DisplayRootView methodsFor:'queries'!
@@ -207,13 +209,15 @@
      This is done by performing an action (enabling button events of
      root window), which will fail if a window manager is running."
 
-    device platformName = 'WIN32' ifTrue:[^ true].
+    |device|
 
+    device := self graphicsDevice.
+    device isWindowsPlatform ifTrue:[^ true].
     device class deviceErrorSignal handle:[:ex |
         ^ false.
     ] do:[
         self enableButtonEvents.
-        device flush.
+        self flush.
     ].
     ^ true
 
@@ -226,6 +230,6 @@
 !DisplayRootView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/DisplayRootView.st,v 1.37 2014-02-04 15:49:51 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/DisplayRootView.st,v 1.42.2.1 2014-05-08 08:27:50 stefan Exp $'
 ! !
 
--- a/DisplaySurface.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/DisplaySurface.st	Thu May 08 10:27:51 2014 +0200
@@ -9,6 +9,8 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 24-03-2014 at 09:59:12'                   !
+
 "{ Package: 'stx:libview' }"
 
 GraphicsMedium subclass:#DisplaySurface
@@ -19,13 +21,6 @@
 	category:'Graphics-Support'
 !
 
-DeviceHandle subclass:#DeviceViewHandle
-	instanceVariableNames:''
-	classVariableNames:''
-	poolDictionaries:''
-	privateIn:DisplaySurface
-!
-
 !DisplaySurface class methodsFor:'documentation'!
 
 copyright
@@ -111,22 +106,22 @@
      newTop newBottom newLeft newRight|
 
     updateRegion isNil ifTrue:[
-        updateRegion := OrderedCollection with:newRectangle.
-        ^ true
+	updateRegion := OrderedCollection with:newRectangle.
+	^ true
     ].
     (updateRegion contains:[:oldRectangle | (newRectangle isContainedIn:oldRectangle)]) ifTrue:[
-        ^ false.
+	^ false.
     ].
 
     numRect := updateRegion size.
     numRect > 20 ifTrue:[
-        closure := updateRegion
-                        inject:newRectangle
-                        into:[:boundsSoFar :thisRectangle |
-                                boundsSoFar quickMerge:thisRectangle
-                             ].
-        updateRegion := OrderedCollection with:closure.
-        ^ true
+	closure := updateRegion
+			inject:newRectangle
+			into:[:boundsSoFar :thisRectangle |
+				boundsSoFar quickMerge:thisRectangle
+			     ].
+	updateRegion := OrderedCollection with:closure.
+	^ true
     ].
 
     lastRect := updateRegion at:numRect.
@@ -140,24 +135,24 @@
     newRight := newRectangle right.
 
     lastTop = newTop ifTrue:[
-        lastBottom = newBottom ifTrue:[
-            lastLeft <= newLeft ifTrue:[
-                lastRight >= newLeft ifTrue:[
-                    updateRegion at:numRect put:(lastRect copy right:newRight).
-                    ^ false "/ true
-                ]
-            ]
-        ].
+	lastBottom = newBottom ifTrue:[
+	    lastLeft <= newLeft ifTrue:[
+		lastRight >= newLeft ifTrue:[
+		    updateRegion at:numRect put:(lastRect copy right:newRight).
+		    ^ false "/ true
+		]
+	    ]
+	].
     ].
     lastLeft = newLeft ifTrue:[
-        lastRight = newRight ifTrue:[
-            lastTop <= newTop ifTrue:[
-                lastBottom >= newTop ifTrue:[
-                    updateRegion at:numRect put:(lastRect copy bottom:newBottom).
-                    ^ false "/ true
-                ]
-            ]
-        ].
+	lastRight = newRight ifTrue:[
+	    lastTop <= newTop ifTrue:[
+		lastBottom >= newTop ifTrue:[
+		    updateRegion at:numRect put:(lastRect copy bottom:newBottom).
+		    ^ false "/ true
+		]
+	    ]
+	].
     ].
 
     updateRegion add:newRectangle.
@@ -172,7 +167,7 @@
 
     viewBackground ~~ something ifTrue:[
 	viewBackground := something.
-	drawableId notNil ifTrue:[
+	self drawableId notNil ifTrue:[
 	    self setViewBackground
 	]
     ]
@@ -190,7 +185,7 @@
      but support for mixed depth views is being prepared.
      (especially useful on SGI, with 24bit view)"
 
-    ^ device depth
+    ^ self graphicsDevice depth
 !
 
 insideColor:aColor
@@ -205,7 +200,7 @@
      However, subclasses may redefine this, to return their own
      keyboard map (for example a terminalView may want treat CTRL-C as regular key)"
 
-    ^ device keyboardMap
+    ^ self graphicsDevice keyboardMap
 !
 
 renderer
@@ -231,123 +226,123 @@
     |id devBgPixmap bgPixmap w h colorMap
      pixmapDepth deviceDepth defBG|
 
-    drawableId notNil ifTrue:[
-        viewBackground isColor ifTrue:[
-            viewBackground := viewBackground onDevice:device.
-            id := viewBackground colorId.
-            "
-             a real color (i.e. one supported by the device) ?
-            "
-            id notNil ifTrue:[
-                device setWindowBackground:id in:drawableId.
-                ^ self
-            ].
-            "
-             no, a dithered one - must have a dither-pattern
-             (which is ready for the device, since viewBackground
-              is already assigned to the device)
-            "
-            bgPixmap := viewBackground ditherForm.
-        ] ifFalse:[
-            viewBackground notNil ifTrue:[
-                viewBackground isViewBackground ifTrue:[
-                    ^ self.
-                ].
-
-                "
-                 assume, it can convert itself to a form
-                "
-                bgPixmap := viewBackground asFormOn:device.
-                bgPixmap isNil ifTrue:[
-                    "/ assume it knows how to draw itself
-                    ^ self
-                ].
-            ].
-        ].
-
-        "
-         must now have:
-         a dithered color or bitmap or pixmap
-        "
-        bgPixmap isNil ifTrue:[
-            'DisplaySurface [warning]: background not convertable - ignored' errorPrintCR.
-            ^ self
-        ].
-
-        "/ if the device does not support background pixmaps,
-        "/ set the backgroundColor to the default background.
-        "/ this will avoid flicker in win32 systems,
-        "/ since that background is drawn directly in the
-        "/ devices expose event handling.
-        "/ (in contrast, the pixmap filling is done by the
-        "/ window itself in its expose event handler)
-
-        (device supportsViewBackgroundPixmap:bgPixmap) ifFalse:[
-            defBG := View defaultViewBackgroundColor.
-            defBG isColor ifTrue:[
-                defBG := defBG onDevice:device.
-                id := defBG colorId.
-                id notNil ifTrue:[
-                    device setWindowBackground:id in:drawableId.
-                ].
-            ].
-            ^ self
-        ].
-
-        w := bgPixmap width.
-        h := bgPixmap height.
-
-        deviceDepth := device depth.
-        pixmapDepth := bgPixmap depth.
-
-        (pixmapDepth ~~ deviceDepth) ifTrue:[
-            (pixmapDepth ~~ 1) ifTrue:[
-                'DisplaySurface [warning]: Bad dither depth (must be one or devices depth)' errorPrintCR.
-                ^ self
-            ].
-
-            "
-             convert it into a deep form
-            "
-            colorMap := bgPixmap colorMap.
-            devBgPixmap := Form width:w height:h depth:deviceDepth onDevice:device.
-            devBgPixmap isNil ifTrue:[
-                'DisplaySurface [warning]: could not create a device form for viewBackground' infoPrintCR.
-                ^ self
-            ].
-            devBgPixmap paint:(colorMap at:1).
-            devBgPixmap fillRectangleX:0 y:0 width:w height:h.
-            devBgPixmap foreground:(colorMap at:2) background:(colorMap at:1).
-            devBgPixmap copyPlaneFrom:bgPixmap x:0 y:0 toX:0 y:0 width:w height:h.
-            bgPixmap := devBgPixmap.
-        ] ifFalse:[
-            (pixmapDepth == 1) ifTrue:[
-                "
-                 although depth matches,
-                 values in the dither are to be interpreted via the ditherForms
-                 colormap, which is not always the same as blackpixel/whitepixel ...
-                "
-                colorMap := bgPixmap colorMap.
-                (colorMap at:1) colorId == device whitepixel ifTrue:[
-                    (colorMap at:2) colorId == device blackpixel ifTrue:[
-                        "
-                         ok, can use it
-                        "
-                        device setWindowBackgroundPixmap:(bgPixmap id) in:drawableId.
-                        ^ self
-                    ]
-                ].
-
-                "
-                 no, must invert it
-                "
-                devBgPixmap := Form width:w height:h depth:deviceDepth onDevice:device.
-                devBgPixmap paint:(colorMap at:2) on:(colorMap at:1).
-                devBgPixmap copyPlaneFrom:bgPixmap x:0 y:0 toX:0 y:0 width:w height:h.
-                bgPixmap := devBgPixmap.
-            ]
-        ].
-        device setWindowBackgroundPixmap:(bgPixmap id) in:drawableId.
+    self drawableId notNil ifTrue:[
+	viewBackground isColor ifTrue:[
+	    viewBackground := viewBackground onDevice:self graphicsDevice.
+	    id := viewBackground colorId.
+	    "
+	     a real color (i.e. one supported by the device) ?
+	    "
+	    id notNil ifTrue:[
+		self graphicsDevice setWindowBackground:id in:self drawableId.
+		^ self
+	    ].
+	    "
+	     no, a dithered one - must have a dither-pattern
+	     (which is ready for the device, since viewBackground
+	      is already assigned to the device)
+	    "
+	    bgPixmap := viewBackground ditherForm.
+	] ifFalse:[
+	    viewBackground notNil ifTrue:[
+		viewBackground isViewBackground ifTrue:[
+		    ^ self.
+		].
+
+		"
+		 assume, it can convert itself to a form
+		"
+		bgPixmap := viewBackground asFormOn:self graphicsDevice.
+		bgPixmap isNil ifTrue:[
+		    "/ assume it knows how to draw itself
+		    ^ self
+		].
+	    ].
+	].
+
+	"
+	 must now have:
+	 a dithered color or bitmap or pixmap
+	"
+	bgPixmap isNil ifTrue:[
+	    'DisplaySurface [warning]: background not convertable - ignored' errorPrintCR.
+	    ^ self
+	].
+
+	"/ if the device does not support background pixmaps,
+	"/ set the backgroundColor to the default background.
+	"/ this will avoid flicker in win32 systems,
+	"/ since that background is drawn directly in the
+	"/ devices expose event handling.
+	"/ (in contrast, the pixmap filling is done by the
+	"/ window itself in its expose event handler)
+
+	(self graphicsDevice supportsViewBackgroundPixmap:bgPixmap) ifFalse:[
+	    defBG := View defaultViewBackgroundColor.
+	    defBG isColor ifTrue:[
+		defBG := defBG onDevice:self graphicsDevice.
+		id := defBG colorId.
+		id notNil ifTrue:[
+		    self graphicsDevice setWindowBackground:id in:self drawableId.
+		].
+	    ].
+	    ^ self
+	].
+
+	w := bgPixmap width.
+	h := bgPixmap height.
+
+	deviceDepth := self depth.
+	pixmapDepth := bgPixmap depth.
+
+	(pixmapDepth ~~ deviceDepth) ifTrue:[
+	    (pixmapDepth ~~ 1) ifTrue:[
+		'DisplaySurface [warning]: Bad dither depth (must be one or devices depth)' errorPrintCR.
+		^ self
+	    ].
+
+	    "
+	     convert it into a deep form
+	    "
+	    colorMap := bgPixmap colorMap.
+	    devBgPixmap := Form width:w height:h depth:deviceDepth onDevice:self graphicsDevice.
+	    devBgPixmap isNil ifTrue:[
+		'DisplaySurface [warning]: could not create a device form for viewBackground' infoPrintCR.
+		^ self
+	    ].
+	    devBgPixmap paint:(colorMap at:1).
+	    devBgPixmap fillRectangleX:0 y:0 width:w height:h.
+	    devBgPixmap foreground:(colorMap at:2) background:(colorMap at:1).
+	    devBgPixmap copyPlaneFrom:bgPixmap x:0 y:0 toX:0 y:0 width:w height:h.
+	    bgPixmap := devBgPixmap.
+	] ifFalse:[
+	    (pixmapDepth == 1) ifTrue:[
+		"
+		 although depth matches,
+		 values in the dither are to be interpreted via the ditherForms
+		 colormap, which is not always the same as blackpixel/whitepixel ...
+		"
+		colorMap := bgPixmap colorMap.
+		(colorMap at:1) colorId == self graphicsDevice whitepixel ifTrue:[
+		    (colorMap at:2) colorId == self graphicsDevice blackpixel ifTrue:[
+			"
+			 ok, can use it
+			"
+			self graphicsDevice setWindowBackgroundPixmap:(bgPixmap id) in:self drawableId.
+			^ self
+		    ]
+		].
+
+		"
+		 no, must invert it
+		"
+		devBgPixmap := Form width:w height:h depth:deviceDepth onDevice:self graphicsDevice.
+		devBgPixmap paint:(colorMap at:2) on:(colorMap at:1).
+		devBgPixmap copyPlaneFrom:bgPixmap x:0 y:0 toX:0 y:0 width:w height:h.
+		bgPixmap := devBgPixmap.
+	    ]
+	].
+	self graphicsDevice setWindowBackgroundPixmap:(bgPixmap id) in:self drawableId.
     ]
 
     "Modified: / 23-01-2011 / 01:44:38 / cg"
@@ -409,10 +404,18 @@
     ^ self
 !
 
+windowClass:classString name:nameString
+    gc windowClass:classString name:nameString.
+!
+
 windowGroup
     "return nil - I have no windowGroup"
 
     ^ nil
+!
+
+windowName:aString
+    gc windowName:aString.
 ! !
 
 !DisplaySurface methodsFor:'accessing-cursor'!
@@ -456,11 +459,11 @@
     aCursor notNil ifTrue:[
 	(aCursor ~~ cursor) ifTrue:[
 	    cursor := aCursor.
-	    drawableId notNil ifTrue:[
+	    self drawableId notNil ifTrue:[
 		self setCursor.
 		(showImmediately and:[realized]) ifTrue:[
 		    "flush, to make cursor immediately visible"
-		    device flush
+		    self flush
 		]
 	    ]
 	]
@@ -489,16 +492,16 @@
     |id|
 
     cursor isNil ifTrue:[ ^ self].
-    cursor := cursor onDevice:self device.
+    cursor := cursor onDevice:self graphicsDevice.
     cursor isNil ifTrue:[ ^ self].
 
     id := cursor id.
     id isNil ifTrue:[
-        'DisplaySurface [warning]: nil cursorId ignored; shape=' errorPrint.
-        cursor shape errorPrintCR.
-        ^ self.
+	'DisplaySurface [warning]: nil cursorId ignored; shape=' errorPrint.
+	cursor shape errorPrintCR.
+	^ self.
     ].
-    self setCursorId:id .
+    gc setCursorId:id .
 !
 
 withCursor:aCursor do:aBlock
@@ -550,19 +553,19 @@
     |ret|
 
     cursor == aCursor ifTrue:[
-        ^ aBlock value
+	^ aBlock value
     ].
 
-    self 
-        withCursor:aCursor do:[
-            |time|
-
-            time := Time millisecondsToRun:[ ret := aBlock value].
-            time := UserPreferences current waitCursorVisibleTime - time.
-            time > 0 ifTrue:[
-                Delay waitForMilliseconds:time.
-            ].
-        ].
+    self
+	withCursor:aCursor do:[
+	    |time|
+
+	    time := Time millisecondsToRun:[ ret := aBlock value].
+	    time := UserPreferences current waitCursorVisibleTime - time.
+	    time > 0 ifTrue:[
+		Delay waitForMilliseconds:time.
+	    ].
+	].
     ^ ret.
 
     "Modified (comment): / 12-09-2011 / 12:14:29 / cg"
@@ -590,7 +593,8 @@
 !DisplaySurface methodsFor:'accessing-hierarchy'!
 
 delegate
-    "return the delegate - thats the one getting keyboard and button events"
+    "return the delegate - that's the one getting keyboard and button events.
+     See dispatchEvent:... method"
 
     ^ delegate
 !
@@ -598,7 +602,7 @@
 delegate:someOne
     "set the delegate - keyboard- and button events will be forwarded to
      that object if it is interested in them.
-     See the sendEvent... method in WindowEvent."
+     See the dispatchEvent... method."
 
     delegate := someOne
 !
@@ -660,8 +664,8 @@
      how may true/false, but also #always, #whenMapped or #never."
 
     how ~~ backed ifTrue:[
-        backed := how.
-        super backingStore:how.
+	backed := how.
+	super backingStore:how.
     ]
 !
 
@@ -683,7 +687,7 @@
     "tell the Display to assign keyboard focus to the receiver"
 
     self shown ifTrue:[
-	device setInputFocusTo:drawableId.
+	self graphicsDevice setInputFocusTo:self drawableId.
     ].
 
     "Modified: / 15.3.1999 / 08:25:10 / cg"
@@ -730,17 +734,17 @@
      - used for temporary views (i.e. PopUps and ModalBoxes)"
 
     aBoolean ifTrue:[
-        flags := flags bitOr:SaveUnderFlagMask.
+	flags := flags bitOr:SaveUnderFlagMask.
     ] ifFalse:[
-        flags := flags bitClear:SaveUnderFlagMask.
+	flags := flags bitClear:SaveUnderFlagMask.
     ].
-    super saveUnder:aBoolean.
+    gc saveUnder:aBoolean.
 !
 
 setPointerPosition:aRelativePoint
     "set the pointer to aRelativePoint relative to the views origin"
 
-    device setPointerPosition:aRelativePoint in:drawableId.
+    self graphicsDevice setPointerPosition:aRelativePoint in:self drawableId.
 
     "
 	Transcript setPointerPosition:Transcript extent // 2.
@@ -834,15 +838,15 @@
 
 setAttribute:key to:newValue
     newValue isNil ifTrue:[
-        moreAttributes notNil ifTrue:[
-            moreAttributes removeKey:key ifAbsent:[].
-            moreAttributes := moreAttributes asNilIfEmpty
-        ]
+	moreAttributes notNil ifTrue:[
+	    moreAttributes removeKey:key ifAbsent:[].
+	    moreAttributes := moreAttributes asNilIfEmpty
+	]
     ] ifFalse:[
-        moreAttributes isNil ifTrue:[
-            moreAttributes := IdentityDictionary new.
-        ].
-        moreAttributes at:key put:newValue.
+	moreAttributes isNil ifTrue:[
+	    moreAttributes := IdentityDictionary new.
+	].
+	moreAttributes at:key put:newValue.
     ].
 !
 
@@ -852,6 +856,53 @@
     flags := flags bitOr:GotExposeFlagMask.
 ! !
 
+!DisplaySurface methodsFor:'binary storage'!
+
+readBinaryContentsFrom: stream manager: manager
+    "tell the newly restored View to recreate itself.
+     Bug: does not work correctly yet.
+	  (restored view looses its position & wg process)"
+
+    |wasRealized|
+
+    super readBinaryContentsFrom: stream manager: manager.
+
+    wasRealized := realized.
+    realized := false.
+    self recreate.
+    wasRealized ifTrue:[
+	self remap
+    ]
+
+
+    "
+     |s l|
+     s := 'storedLabel.boss' asFilename writeStream binary.
+     l := (Label label:'hello there') realize.
+     Delay waitForSeconds:1.
+     l storeBinaryOn:s.
+     s close.
+    "
+
+    "
+     |s l|
+     s := 'storedLabel.boss' asFilename writeStream binary.
+     (l := Label label:'hello there') open.
+     (Delay forSeconds:10) wait.
+     l storeBinaryOn:s.
+     s close.
+     l destroy.
+    "
+
+    "
+     |s|
+     s := 'storedLabel.boss' asFilename readStream binary.
+     (Object readBinaryFrom:s)
+    "
+
+    "Modified: 3.5.1996 / 23:59:38 / stefan"
+    "Modified: 14.2.1997 / 15:42:55 / cg"
+! !
 
 !DisplaySurface methodsFor:'button menus'!
 
@@ -885,9 +936,9 @@
     |oldMenu|
 
     (oldMenu := self getMiddleButtonMenu) notNil ifTrue:[
-        oldMenu isArray ifFalse:[
-            oldMenu destroy
-        ]
+	oldMenu isArray ifFalse:[
+	    oldMenu destroy
+	]
     ].
     self setMiddleButtonMenu:aMenu
 
@@ -907,7 +958,7 @@
     "return the object selection
      - either the local one, or the displays clipBoard buffer."
 
-    ^ device getClipboardObjectFor:drawableId.
+    ^ self graphicsDevice getClipboardObjectFor:self drawableId.
 
     "Modified: 13.2.1997 / 13:18:50 / cg"
 !
@@ -928,7 +979,7 @@
 
      Return aString or nil if there is no selection"
 
-    ^ device getClipboardText:selectionBufferSymbol for:drawableId.
+    ^ self graphicsDevice getClipboardText:selectionBufferSymbol for:self drawableId.
 !
 
 getSelection
@@ -966,14 +1017,14 @@
     "set the object selection - both the local one, and tell the display
      that we have changed it (i.e. place it into the clipBoard)."
 
-    device setClipboardObject:something ownerView:self.
+    self graphicsDevice setClipboardObject:something ownerView:self.
 !
 
 setClipboardText:something
     "set the text selection - both the local one, and tell the display
      that we have changed it (i.e. place it into the clipBoard)."
 
-    device setClipboardText:something ownerView:self
+    self graphicsDevice setClipboardText:something ownerView:self
 !
 
 setSelection:something
@@ -983,7 +1034,7 @@
     <resource: #obsolete>
 
     self obsoleteMethodWarning:'use setClipboardObject:'.
-    device setClipboardObject:something ownerView:self.
+    self graphicsDevice setClipboardObject:something ownerView:self.
 !
 
 setTextSelection:something
@@ -993,7 +1044,7 @@
     <resource: #obsolete>
 
     self obsoleteMethodWarning:'use setClipboardText:'.
-    device setClipboardText:something ownerView:self
+    self graphicsDevice setClipboardText:something ownerView:self
 ! !
 
 !DisplaySurface methodsFor:'drawing'!
@@ -1003,33 +1054,31 @@
      redefined since GraphicsMedium fills with background
      - not viewBackground as we want here."
 
-    |oldPaint org|
+    |oldPaint|
 
     viewBackground isColor ifFalse:[
-        viewBackground isViewBackground ifTrue:[
-            self paint:background.
-            self fillDeviceRectangleX:x y:y width:w height:h.
-            self paint:paint.
-            viewBackground fillRectangleX:x y:y width:w height:h in:self.
-            ^ self.
-        ].
-
-        gcId notNil ifTrue:[
-            org := self viewOrigin.
-            device setMaskOriginX:org x rounded negated
-                                y:org y rounded negated
-                               in:gcId
-        ].
-        (device supportsMaskedDrawingWith:viewBackground) ifFalse:[
-            self fillDeviceRectangleWithViewBackgroundX:x y:y width:w height:h.
-            ^ self.
-        ]
+	viewBackground isViewBackground ifTrue:[
+	    oldPaint := self paint.
+	    self paint:self background.
+	    self fillDeviceRectangleX:x y:y width:w height:h.
+	    self paint:oldPaint.
+	    viewBackground fillRectangleX:x y:y width:w height:h in:self.
+	    ^ self.
+	].
+
+	gc notNil ifTrue:[
+	    self maskOrigin:self viewOrigin negated.
+	    (gc graphicsDevice supportsMaskedDrawingWith:viewBackground) ifFalse:[
+		gc graphicsDevice fillDeviceRectangleWithViewBackgroundX:x y:y width:w height:h.
+		^ self.
+	    ].
+	].
     ].
 
     "
      fill in device coordinates - not logical coordinates
     "
-    oldPaint := paint.
+    oldPaint := self paint.
     self paint:viewBackground.
     self fillDeviceRectangleX:x y:y width:w height:h "with:viewBackground".
     self paint:oldPaint
@@ -1042,13 +1091,14 @@
      redefined since GraphicsMedium fills with background
      - not viewBackground as we want here."
 
-    |pX pY pW pH|
-
-    transformation notNil ifTrue:[
-	pX := transformation applyToX:x.
-	pY := transformation applyToY:y.
-	pW := transformation applyScaleX:w.
-	pH := transformation applyScaleY:h.
+    |pX pY pW pH currentTransformation|
+
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	pX := currentTransformation applyToX:x.
+	pY := currentTransformation applyToY:y.
+	pW := currentTransformation applyScaleX:w.
+	pH := currentTransformation applyScaleY:h.
     ] ifFalse:[
 	pX := x.
 	pY := y.
@@ -1056,17 +1106,13 @@
 	pH := h.
     ].
 
-    pX := pX rounded.
-    pY := pY rounded.
-    pW := pW rounded.
-    pH := pH rounded.
-
-    ^ self clearDeviceRectangleX:pX y:pY width:pW height:pH.
+    ^ self clearDeviceRectangleX:pX rounded y:pY rounded width:pW rounded height:pH rounded.
 
     "Modified: / 30.10.1998 / 15:00:37 / cg"
 !
 
 fillDeviceRectangleWithPattern:aPixmap x:xIn y:yIn width:wIn height:hIn patternOffset:pattOffs
+    <resource: #obsolete>
     "fill a rectangular area with some pattern.
      A helper for devices which do not support pixmap drawing (i.e. win95).
      This is never invoked with X11 or Win-NT/XP/Vista systems.
@@ -1102,10 +1148,10 @@
     oldClip := self clippingRectangleOrNil.
 
     oldClip notNil ifTrue:[
-        x := x max:oldClip left.
-        y := y max:oldClip top.
-        r := r min:oldClip right.
-        b := b min:oldClip bottom.
+	x := x max:oldClip left.
+	y := y max:oldClip top.
+	r := r min:oldClip right.
+	b := b min:oldClip bottom.
     ].
     w := r-x+1.
     h := b-y+1.
@@ -1121,16 +1167,16 @@
     xR0 >= yE ifTrue:[^ self].
 
     aPixmap depth == 1 ifTrue:[
-        oldFg := foreground.
-        oldBg := background.
-        (clrMap := aPixmap colorMap) notNil ifTrue:[
-            bg := clrMap at:1.
-            fg := clrMap at:2.
-        ] ifFalse:[
-            bg := Color white.
-            fg := Color black.
-        ].
-        self foreground:fg background:bg.
+	oldFg := self foreground.
+	oldBg := self background.
+	(clrMap := aPixmap colorMap) notNil ifTrue:[
+	    bg := clrMap at:1.
+	    fg := clrMap at:2.
+	] ifFalse:[
+	    bg := Color white.
+	    fg := Color black.
+	].
+	self foreground:fg background:bg.
     ].
     self deviceClippingRectangle:(x@y extent:w@h).
 
@@ -1139,24 +1185,24 @@
 
     oY := offsY.
     [yR < yE] whileTrue:[
-        xR := xR0.
-        oX := offsX.
-        [xR < xE] whileTrue:[
-            self
-                copyFrom:aPixmap
-                x:oX y:oY
-                toX:xR y:yR
-                width:(pW - oX) height:(pH - oY)
-                async:true.
-            xR := xR + pW - oX.
-            oX := 0.
-        ].
-        yR := yR + pH - oY.
-        oY := 0.
+	xR := xR0.
+	oX := offsX.
+	[xR < xE] whileTrue:[
+	    self
+		copyFrom:aPixmap
+		x:oX y:oY
+		toX:xR y:yR
+		width:(pW - oX) height:(pH - oY)
+		async:true.
+	    xR := xR + pW - oX.
+	    oX := 0.
+	].
+	yR := yR + pH - oY.
+	oY := 0.
     ].
 
     oldFg notNil ifTrue:[
-        self foreground:oldFg background:oldBg.
+	self foreground:oldFg background:oldBg.
     ].
     self deviceClippingRectangle:oldClip.
 
@@ -1166,46 +1212,46 @@
 !
 
 fillDeviceRectangleWithViewBackgroundX:xIn y:yIn width:wIn height:hIn
+    <resource: #obsolete>
     "fill a rectangular area with the viewBackground.
      A helper for devices which do not support background pixmaps (i.e. win95 screens).
      This is never invoked with X11 or Win-NT/XP/Vista systems.
      Caller must ensure that the viewBackground is really a form"
 
     self
-        fillDeviceRectangleWithPattern:viewBackground
-        x:xIn y:yIn width:wIn height:hIn
-        patternOffset:self viewOrigin
+	fillDeviceRectangleWithPattern:viewBackground
+	x:xIn y:yIn width:wIn height:hIn
+	patternOffset:self viewOrigin
 !
 
 fillRectangleWithPattern:aPixmap x:x y:y width:w height:h patternOffset:pattOffs
+    <resource: #obsolete>
     "fill a rectangular area with aPixmap.
      A helper for devices which do not support pixmap filling (i.e. win95 screens).
      This is never invoked with X11 or Win-NT/XP/Vista systems.
      Caller must ensure that the aPixmap is really a form"
 
-    |pX pY nW nH|
-
-    gcId isNil ifTrue:[
-        self initGC
-    ].
-    transformation notNil ifTrue:[
-        pX := transformation applyToX:x.
-        pY := transformation applyToY:y.
-        nW := transformation applyScaleX:w.
-        nH := transformation applyScaleY:h.
-        nW < 0 ifTrue:[
-              nW := nW abs.
-              pX := pX - nW.
-        ].
-        nH < 0 ifTrue:[
-              nH := nH abs.
-              pY := pY - nH.
-        ].
+    |pX pY nW nH currentTransformation|
+
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	pX := currentTransformation applyToX:x.
+	pY := currentTransformation applyToY:y.
+	nW := currentTransformation applyScaleX:w.
+	nH := currentTransformation applyScaleY:h.
+	nW < 0 ifTrue:[
+	      nW := nW abs.
+	      pX := pX - nW.
+	].
+	nH < 0 ifTrue:[
+	      nH := nH abs.
+	      pY := pY - nH.
+	].
     ] ifFalse:[
-        pX := x.
-        pY := y.
-        nW := w.
-        nH := h.
+	pX := x.
+	pY := y.
+	nW := w.
+	nH := h.
     ].
     pX := pX rounded.
     pY := pY rounded.
@@ -1213,23 +1259,24 @@
     nH := nH rounded.
 
     self
-        fillDeviceRectangleWithPattern:aPixmap
-        x:pX y:pY width:nW height:nH
-        patternOffset:pattOffs
+	fillDeviceRectangleWithPattern:aPixmap
+	x:pX y:pY width:nW height:nH
+	patternOffset:pattOffs
 
     "Modified: 4.6.1996 / 17:58:49 / cg"
 !
 
 fillRectangleWithViewBackgroundX:x y:y width:w height:h
+    <resource: #obsolete>
     "fill a rectangular area with the viewBackground.
      A helper for devices which do not support background pixmaps (i.e. win95 screens).
      This is never invoked with X11 or Win-NT/XP/Vista systems.
      Caller must ensure that the viewBackground is really a form"
 
     self
-        fillRectangleWithPattern:viewBackground
-        x:x y:y width:w height:h
-        patternOffset:self viewOrigin
+	fillRectangleWithPattern:viewBackground
+	x:x y:y width:w height:h
+	patternOffset:self viewOrigin
 !
 
 redraw
@@ -1292,9 +1339,9 @@
      this is a private (internal) method not to be used externally.
      for a list of allowed event symbols see Workstation class"
 
-    eventMask := eventMask bitAnd:(device eventMaskFor:anEventSymbol) bitInvert.
-    drawableId notNil ifTrue:[
-	device setEventMask:eventMask in:drawableId
+    eventMask := eventMask bitAnd:(self graphicsDevice eventMaskFor:anEventSymbol) bitInvert.
+    self drawableId notNil ifTrue:[
+	self graphicsDevice setEventMask:eventMask in:self drawableId
     ]
 !
 
@@ -1353,9 +1400,9 @@
      this is a private (internal) method not to be used externally.
      for a list of allowed event symbols see Workstation class"
 
-    eventMask := (eventMask ? 0) bitOr:(device eventMaskFor:anEventSymbol).
-    drawableId notNil ifTrue:[
-	device setEventMask:eventMask in:drawableId
+    eventMask := (eventMask ? 0) bitOr:(self graphicsDevice eventMaskFor:anEventSymbol).
+    self drawableId notNil ifTrue:[
+	self graphicsDevice setEventMask:eventMask in:self drawableId
     ]
 !
 
@@ -1453,7 +1500,7 @@
 	    y := rect top.
 	    w := rect width.
 	    h := rect height.
-	    transformation notNil ifTrue:[
+	    gc transformation notNil ifTrue:[
 		self deviceExposeX:x y:y width:w height:h
 	    ] ifFalse:[
 		self exposeX:x y:y width:w height:h
@@ -1476,7 +1523,7 @@
 			y := rect top.
 			w := rect width.
 			h := rect height.
-			transformation notNil ifTrue:[
+			gc transformation notNil ifTrue:[
 			    self deviceExposeX:x y:y width:w height:h
 			] ifFalse:[
 			    self exposeX:x y:y width:w height:h
@@ -1589,10 +1636,13 @@
 		    "
 		     mhmh ... have to convert to logical coordinates
 		    "
-		    transformation notNil ifTrue:[
+		    |currentTransformation|
+
+		    currentTransformation := gc transformation.
+		    currentTransformation notNil ifTrue:[
 			argArray size > 2 ifTrue:[
-			    argArray at:2 put:(transformation applyInverseToX:(argArray at:2)).
-			    argArray at:3 put:(transformation applyInverseToY:(argArray at:3)).
+			    argArray at:2 put:(currentTransformation applyInverseToX:(argArray at:2)).
+			    argArray at:3 put:(currentTransformation applyInverseToY:(argArray at:3)).
 			].
 		    ].
 		    argArray isNil ifTrue:[
@@ -1645,7 +1695,7 @@
     "
     selector := type.
 
-    transformation notNil ifTrue:[
+    gc transformation notNil ifTrue:[
 	(isKeyEvent
 	 or:[isButtonEvent
 	 or:[isMouseWheelEvent
@@ -1694,12 +1744,12 @@
     |menu|
 
     (menu := self middleButtonMenu) notNil ifTrue:[
-        menu isArray ifTrue:[
-            "/ a spec array
-            menu := menu decodeAsLiteralArray.
-            menu receiver:self.
-        ].
-        menu showAtPointer
+	menu isArray ifTrue:[
+	    "/ a spec array
+	    menu := menu decodeAsLiteralArray.
+	    menu receiver:self.
+	].
+	menu showAtPointer
     ]
 
     "Created: 1.3.1996 / 13:24:55 / cg"
@@ -1721,9 +1771,9 @@
     "button was pressed - if its middle button and there is a menu, show it."
 
     (button == 2) ifTrue:[
-        UserPreferences current showRightButtonMenuOnRelease ifFalse:[
-            self activateMenu.
-        ].
+	UserPreferences current showRightButtonMenuOnRelease ifFalse:[
+	    self activateMenu.
+	].
     ]
 
     "Modified: 1.3.1996 / 13:25:07 / cg"
@@ -1731,9 +1781,9 @@
 
 buttonRelease:button x:x y:y
     (button == 2) ifTrue:[
-        UserPreferences current showRightButtonMenuOnRelease ifTrue:[
-            self activateMenu.
-        ].
+	UserPreferences current showRightButtonMenuOnRelease ifTrue:[
+	    self activateMenu.
+	].
     ].
 !
 
@@ -1748,7 +1798,7 @@
 
     |wg|
 
-    device scrollsAsynchronous ifFalse:[
+    self graphicsDevice scrollsAsynchronous ifFalse:[
 	self setGotExposeFlag.
 	^ self
     ].
@@ -1786,14 +1836,15 @@
      those which are interested in logical coordinates
      should redefine #buttonMotion:x:y:"
 
-    |lx ly|
+    |lx ly currentTransformation|
 
     lx := x.
     ly := y.
-    transformation notNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
 	lx notNil ifTrue:[
-	    lx := transformation applyInverseToX:lx.
-	    ly := transformation applyInverseToY:ly.
+	    lx := currentTransformation applyInverseToX:lx.
+	    ly := currentTransformation applyInverseToY:ly.
 	].
     ].
     self buttonMotion:state x:lx y:ly
@@ -1813,14 +1864,15 @@
      those which are interested in logical coordinates
      should redefine #buttonMultiPress:x:y:"
 
-    |lx ly|
+    |lx ly currentTransformation|
 
     lx := x.
     ly := y.
-    transformation notNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
 	lx notNil ifTrue:[
-	    lx := transformation applyInverseToX:lx.
-	    ly := transformation applyInverseToY:ly.
+	    lx := currentTransformation applyInverseToX:lx.
+	    ly := currentTransformation applyInverseToY:ly.
 	].
     ].
     self buttonMultiPress:butt x:lx y:ly
@@ -1840,14 +1892,15 @@
      those which are interested in logical coordinates
      should redefine #buttonPress:x:y:"
 
-    |lx ly|
+    |lx ly currentTransformation|
 
     lx := x.
     ly := y.
-    transformation notNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
 	lx notNil ifTrue:[
-	    lx := transformation applyInverseToX:lx.
-	    ly := transformation applyInverseToY:ly.
+	    lx := currentTransformation applyInverseToX:lx.
+	    ly := currentTransformation applyInverseToY:ly.
 	].
     ].
     self buttonPress:butt x:lx y:ly
@@ -1867,14 +1920,15 @@
      those which are interested in logical coordinates
      should redefine #buttonRelease:x:y:"
 
-    |lx ly|
+    |lx ly currentTransformation|
 
     lx := x.
     ly := y.
-    transformation notNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
 	lx notNil ifTrue:[
-	    lx := transformation applyInverseToX:lx.
-	    ly := transformation applyInverseToY:ly.
+	    lx := currentTransformation applyInverseToX:lx.
+	    ly := currentTransformation applyInverseToY:ly.
 	].
     ].
     self buttonRelease:butt x:lx y:ly
@@ -1894,14 +1948,15 @@
      those which are interested in logical coordinates
      should redefine #buttonShiftPress:x:y:"
 
-    |lx ly|
+    |lx ly currentTransformation|
 
     lx := x.
     ly := y.
-    transformation notNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
 	lx notNil ifTrue:[
-	    lx := transformation applyInverseToX:lx.
-	    ly := transformation applyInverseToY:ly.
+	    lx := currentTransformation applyInverseToX:lx.
+	    ly := currentTransformation applyInverseToY:ly.
 	].
     ].
     self buttonShiftPress:butt x:lx y:ly
@@ -1921,17 +1976,18 @@
      those which are interested in logical coordinates
      should redefine #exposeX:x:y:width:height:"
 
-    |lx ly lw lh|
+    |lx ly lw lh currentTransformation|
 
     lx := x.
     ly := y.
     lw := w.
     lh := h.
-    transformation notNil ifTrue:[
-	lx := transformation applyInverseToX:lx.
-	ly := transformation applyInverseToY:ly.
-	lw := transformation applyInverseScaleX:lw.
-	lh := transformation applyInverseScaleY:lh.
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	lx := currentTransformation applyInverseToX:lx.
+	ly := currentTransformation applyInverseToY:ly.
+	lw := currentTransformation applyInverseScaleX:lw.
+	lh := currentTransformation applyInverseScaleY:lh.
     ].
     self exposeX:lx y:ly width:lw height:lh
 
@@ -1950,17 +2006,18 @@
      those which are interested in logical coordinates
      should redefine #graphicsExposeX:x:y:width:height:"
 
-    |lx ly lw lh|
+    |lx ly lw lh currentTransformation|
 
     lx := x.
     ly := y.
     lw := w.
     lh := h.
-    transformation notNil ifTrue:[
-	lx := transformation applyInverseToX:lx.
-	ly := transformation applyInverseToY:ly.
-	lw := transformation applyInverseScaleX:lw.
-	lh := transformation applyInverseScaleY:lh.
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	lx := currentTransformation applyInverseToX:lx.
+	ly := currentTransformation applyInverseToY:ly.
+	lw := currentTransformation applyInverseScaleX:lw.
+	lh := currentTransformation applyInverseScaleY:lh.
     ].
     self graphicsExposeX:lx y:ly width:lw height:lh final:final
 
@@ -1979,14 +2036,15 @@
      those which are interested in logical coordinates
      should redefine #keyPress:x:y:"
 
-    |lx ly|
+    |lx ly currentTransformation|
 
     lx := x.
     ly := y.
-    transformation notNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
 	lx notNil ifTrue:[
-	    lx := transformation applyInverseToX:lx.
-	    ly := transformation applyInverseToY:ly.
+	    lx := currentTransformation applyInverseToX:lx.
+	    ly := currentTransformation applyInverseToY:ly.
 	]
     ].
     self keyPress:key x:lx y:ly
@@ -2006,14 +2064,15 @@
      those which are interested in logical coordinates
      should redefine #keyRelease:x:y:"
 
-    |lx ly|
+    |lx ly currentTransformation|
 
     lx := x.
     ly := y.
-    transformation notNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
 	lx notNil ifTrue:[
-	    lx := transformation applyInverseToX:lx.
-	    ly := transformation applyInverseToY:ly.
+	    lx := currentTransformation applyInverseToX:lx.
+	    ly := currentTransformation applyInverseToY:ly.
 	]
     ].
     self keyRelease:key x:lx y:ly
@@ -2033,14 +2092,15 @@
      those which are interested in logical coordinates
      should redefine #pointerEnter:x:y:"
 
-    |lx ly|
+    |lx ly currentTransformation|
 
     lx := x.
     ly := y.
-    transformation notNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
 	lx notNil ifTrue:[
-	    lx := transformation applyInverseToX:lx.
-	    ly := transformation applyInverseToY:ly.
+	    lx := currentTransformation applyInverseToX:lx.
+	    ly := currentTransformation applyInverseToY:ly.
 	]
     ].
     self pointerEnter:state x:lx y:ly
@@ -2086,20 +2146,20 @@
     |action rest restKey keyCommands|
 
     (keyCommands := self keyCommands) notNil ifTrue:[
-        action := keyCommands at:key ifAbsent:[nil].
-        action value
+	action := keyCommands at:key ifAbsent:[nil].
+	action value
     ].
 
     key isSymbol ifTrue:[
-        (key startsWith:'Basic') ifTrue:[
-            "/ an unhandled BasicFoo key;
-            "/ retry as Foo
-            rest := key withoutPrefix:'Basic'.
-            restKey := rest asSymbolIfInterned.
-            restKey notNil ifTrue:[
-                self keyPress:restKey x:x y:y
-            ]
-        ].
+	(key startsWith:'Basic') ifTrue:[
+	    "/ an unhandled BasicFoo key;
+	    "/ retry as Foo
+	    rest := key withoutPrefix:'Basic'.
+	    restKey := rest asSymbolIfInterned.
+	    restKey notNil ifTrue:[
+		self keyPress:restKey x:x y:y
+	    ]
+	].
     ].
 
     "Modified: 6.11.1996 / 17:51:15 / cg"
@@ -2147,9 +2207,10 @@
 waitForExpose
     "wait until an expose event arrives (to wait for scroll-finish)"
 
-    |wg endPollTime pollDelay|
-
-    device scrollsAsynchronous ifFalse:[
+    |wg endPollTime pollDelay graphicsDevice|
+
+    graphicsDevice := self graphicsDevice.
+    graphicsDevice scrollsAsynchronous ifFalse:[
 	self setGotExposeFlag.
 	^ self
     ].
@@ -2167,7 +2228,7 @@
 	"/ wait by doing a direct dispatch loop until the event arrives.
 	"/ i.e. poll for the event
 	"/
-	device platformName = 'WIN32' ifTrue:[
+	graphicsDevice platformName = 'WIN32' ifTrue:[
 	    pollDelay := 1.
 	] ifFalse:[
 	    pollDelay := 3.
@@ -2176,8 +2237,8 @@
 
 	[self gotExpose] whileFalse:[
 	    realized ifTrue:[
-		(device exposeEventPendingFor:drawableId withSync:true) ifTrue:[
-		    device dispatchExposeEventFor:drawableId.
+		(graphicsDevice exposeEventPendingFor:self drawableId withSync:true) ifTrue:[
+		    graphicsDevice dispatchExposeEventFor:self drawableId.
 		].
 	    ].
 	    realized ifFalse:[
@@ -2206,43 +2267,10 @@
      first destroy menu if there is one and also destroy the GC.
      then the view is physically destroyed."
 
-    |id|
-
-    self middleButtonMenu:nil.
-    self keyCommands:nil.
-    id := gcId.
-    id notNil ifTrue:[
-        gcId := nil.
-        device destroyGC:id.
-    ].
-    self destroyView.
-    Lobby unregister:self.
-
-    "Modified: 8.2.1997 / 15:50:04 / cg"
-!
-
-destroyGC
-    "physically destroy the gc"
-
-    |id|
-
-    id := gcId.
-    id notNil ifTrue:[
-	gcId := nil.
-	device destroyGC:id.
-    ].
-!
-
-destroyView
-    "physically destroy the view."
-
-    |id|
-
-    (id := drawableId) notNil ifTrue:[
-	drawableId := nil.
-	device destroyView:self withId:id.
-	realized := false.
-    ].
+    self
+	middleButtonMenu:nil;
+	keyCommands:nil.
+    super destroy.
 !
 
 destroyed
@@ -2250,9 +2278,9 @@
 
     |id|
 
-    (id := drawableId) notNil ifTrue:[
-	drawableId := nil.
-	device removeKnownView:self withId:id.
+    (id := self drawableId) notNil ifTrue:[
+	self setId:nil.
+	self graphicsDevice removeKnownView:self withId:id.
 	realized := false.
     ].
     self destroy
@@ -2260,22 +2288,6 @@
     "Modified: 22.3.1997 / 14:56:34 / cg"
 !
 
-executor
-    "redefined for faster creation of finalization copies
-     (only device, gcId and drawableId are needed)"
-
-    |aCopy container parentId|
-
-    container := self container.
-    container notNil ifTrue:[ parentId := container id ].
-
-    aCopy := DeviceViewHandle basicNew.
-    aCopy setDevice:device id:drawableId gcId:gcId parentId:parentId.
-    ^ aCopy
-
-    "Created: 3.5.1996 / 15:35:13 / stefan"
-!
-
 initCursor
     "default cursor for all views"
 
@@ -2294,10 +2306,10 @@
     super initialize.
 
     eventMask := 0.
-    device notNil ifTrue:[
-	eventMask := device defaultEventMask.
+    self graphicsDevice notNil ifTrue:[
+	eventMask := self graphicsDevice defaultEventMask.
     ].
-    viewBackground := background.
+    viewBackground := self background.
     backed := false.
     flags := 0.
     self initCursor
@@ -2305,6 +2317,12 @@
     "Modified: 18.1.1997 / 18:09:41 / cg"
 !
 
+prepareForReinit
+    gc notNil ifTrue:[
+	gc prepareForReinit.
+    ].
+!
+
 reAdjustGeometry
     "sent late during snapin processing, nothing done here"
 
@@ -2315,10 +2333,12 @@
     "recreate (i.e. tell X about me) after a snapin or a migration"
 
     viewBackground isColor ifTrue:[
-	viewBackground := viewBackground onDevice:device
+	viewBackground := viewBackground onDevice:self graphicsDevice
     ].
     super recreate.
-    cursor := cursor onDevice:device.
+    cursor notNil ifTrue:[
+	cursor := cursor onDevice:self graphicsDevice.
+    ].
 
     "Modified: 28.3.1997 / 13:48:06 / cg"
 !
@@ -2330,14 +2350,8 @@
 !
 
 releaseDeviceResources
-    self destroyGC.
-    self destroyView.
-    self unregisterFromLobby.
+    super destroy.
     self setDevice:nil id:nil gcId:nil.
-!
-
-unregisterFromLobby
-    Lobby unregister:self.
 ! !
 
 !DisplaySurface methodsFor:'keyboard commands'!
@@ -2375,12 +2389,12 @@
     "return true, if a button motion event is pending.
      Normally, you don't want to use this, since no polling is needed
      (not even for mouse-tracking).
-     Also, don't use it, since it does not honor the windowGroup, 
+     Also, don't use it, since it does not honor the windowGroup,
      but goes directly to the device instead.
      Actually, its a historical leftover"
 
-    device flush.
-    ^ device eventPending:#buttonMotion for:drawableId
+    self graphicsDevice flush.
+    ^ self graphicsDevice eventPending:#buttonMotion for:self drawableId
 !
 
 buttonReleaseEventPending
@@ -2389,8 +2403,8 @@
      goes directly to the device instead.
      Actually, its a historical leftover"
 
-    device flush.
-    ^ device eventPending:#buttonRelease for:drawableId
+    self graphicsDevice flush.
+    ^ self graphicsDevice eventPending:#buttonRelease for:self drawableId
 !
 
 exposeEventPending
@@ -2402,7 +2416,7 @@
     windowGroup notNil ifTrue:[
 	(windowGroup sensor hasExposeEventFor:self) ifTrue:[^ true].
     ].
-    ^ device eventPending:#expose for:drawableId
+    ^ self graphicsDevice eventPending:#expose for:self drawableId
 
     "Modified: / 15.9.1998 / 23:18:16 / cg"
 !
@@ -2504,7 +2518,7 @@
 beep
     "output an audible beep or bell on my screen device"
 
-    device beep; flush
+    self graphicsDevice beep; flush
 
     "Created: 28.5.1996 / 16:16:13 / cg"
     "Modified: 28.5.1996 / 16:58:25 / cg"
@@ -2519,78 +2533,10 @@
     "Modified: 18.5.1996 / 15:44:33 / cg"
 ! !
 
-!DisplaySurface::DeviceViewHandle class methodsFor:'documentation'!
-
-documentation
-"
-    This is used as a finalization handle for views - in previous systems,
-    a shallowCopy of a view was responsible to destroy the underlying
-    devices view. To make the memory requirements smaller and to speed up
-    view creation a bit, this lightweight class is used now, which only
-    keeps the device handle for finalization.
-
-    [see also:]
-	DeviceHandle DisplaySurface
-
-    [author:]
-	Claus Gittinger
-"
-! !
-
-!DisplaySurface::DeviceViewHandle methodsFor:'finalization'!
-
-finalize
-    "the view for which I am a handle was collected
-     - release system resources"
-
-    |id|
-
-    drawableId notNil ifTrue:[
-	[
-	    (device viewIdKnown:drawableId) ifTrue:[
-"/ 'Display [info]: recycled view (' infoPrint. v infoPrint. ') not destroyed: ' infoPrint.
-"/ drawableId displayString infoPrintCR.
-		drawableId := nil.
-	    ] ifFalse:[
-		(id := gcId) notNil ifTrue:[
-		    gcId := nil.
-		    device deviceIOErrorSignal handle:[:ex |
-		    ] do:[
-			device destroyGC:id.
-		    ]
-		].
-
-		"/ care for lost-view trouble:
-		"/ if the windowID is still registered,
-		"/ this may be due to a not-yet-reclaimed
-		"/ subview of a view which has already been destroyed
-		"/ (X recycles window handles.)
-		"/ In this case, we arrive here with a nil-view argument,
-		"/ and a windowId, which is already reused for some other view.
-		"/ The situation is detected by finding a non-nil (and non-zero)
-		"/ view in the devices id<->view table for the given windowId.
-
-"/ 'GC destroy: ' print. drawableId displayString printCR.
-"/ device checkKnownViewId:drawableId.
-		id := drawableId.
-		drawableId := nil.
-		device deviceIOErrorSignal handle:[:ex |
-		] do:[
-		    device destroyView:nil withId:id.
-		].
-		DeviceGraphicsContext cleanupLobbyForChildrenOfViewWithDevice:device id:id.
-	    ]
-	] valueUninterruptably.
-    ].
-
-    "Created: / 25.9.1997 / 10:01:46 / stefan"
-    "Modified: / 15.11.2001 / 14:17:12 / cg"
-! !
-
 !DisplaySurface class methodsFor:'documentation'!
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/DisplaySurface.st,v 1.160 2014-02-05 13:30:29 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/DisplaySurface.st,v 1.162.2.1 2014-05-08 08:27:50 stefan Exp $'
 ! !
 
 
--- a/Form.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/Form.st	Thu May 08 10:27:51 2014 +0200
@@ -9,10 +9,12 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 09-04-2014 at 12:18:10'                   !
+
 "{ Package: 'stx:libview' }"
 
 GraphicsMedium subclass:#Form
-	instanceVariableNames:'depth localColorMap offset data fileName'
+	instanceVariableNames:'depth localColorMap offset data'
 	classVariableNames:'VeryLightGreyForm LightGreyForm GreyForm DarkGreyForm
 		VeryDarkGreyForm AdditionalBitmapDirectoryNames
 		BlackAndWhiteColorMap DitherPatternArray'
@@ -20,13 +22,6 @@
 	category:'Compatibility-ST80-Graphics-Display Objects'
 !
 
-DeviceHandle subclass:#DeviceFormHandle
-	instanceVariableNames:''
-	classVariableNames:''
-	poolDictionaries:''
-	privateIn:Form
-!
-
 Form subclass:#ImageForm
 	instanceVariableNames:''
 	classVariableNames:''
@@ -86,23 +81,6 @@
 
 !Form class methodsFor:'initialization'!
 
-flushDeviceForms
-    "recreate all forms on aDevice; called by Workstation, to
-     have all background bitmaps at hand, when views are restored"
-
-    Lobby do:[:aDrawable |
-	aDrawable isForm ifTrue:[
-	    (aDrawable graphicsDevice notNil) ifTrue:[
-		"now, try to recreate it"
-		aDrawable recreate.
-	    ]
-	]
-    ]
-
-    "Created: 18.6.1996 / 13:04:59 / cg"
-    "Modified: 5.7.1996 / 17:56:02 / cg"
-!
-
 initialize
     "initialize set of dictionaries to look for bitmaps"
 
@@ -118,16 +96,14 @@
 !
 
 reinitializeAllOn:aDevice
-    "recreate all forms on aDevice; called by Workstation, to
+    "recreate all forms on aDevice; called by Workstation after snapIn, to
      have all background bitmaps at hand, when views are restored"
 
-    Lobby do:[:aDrawable |
-	(aDrawable graphicsDevice == aDevice) ifTrue:[
-	    aDrawable isForm ifTrue:[
-		"now, try to recreate it"
-		aDrawable recreate.
-	    ]
-	]
+    Form allSubInstancesDo:[:eachForm |
+        eachForm graphicsDevice == aDevice ifTrue:[
+            "now, try to recreate it"
+            eachForm recreate.
+        ]
     ]
 
     "Modified: 5.7.1996 / 17:55:58 / cg"
@@ -138,28 +114,23 @@
 
     (something == #save) ifTrue:[
         "get all bits from the device into saveable arrays"
-        Lobby do:[:aDrawable |
-            aDrawable isForm ifTrue:[
-                (PrimitiveFailureSignal , DeviceWorkstation drawingOnClosedDeviceSignal) handle:[:ex |
-                    'Form [warning]: cannot fetch form bits from device' errorPrintCR
-                ] do:[
-                    |dev|
+        Form allSubInstancesDo:[:eachForm |
+            (PrimitiveFailureSignal , DeviceWorkstation drawingOnClosedDeviceSignal) handle:[:ex |
+                'Form [warning]: cannot fetch form bits from device' errorPrintCR
+            ] do:[
+                |dev|
 
-                    ((dev := aDrawable device) isNil   
-                    or:[dev isPersistentInSnapshot]) ifTrue:[
-                        aDrawable getBits
-                    ]
+                ((dev := eachForm graphicsDevice) notNil   
+                 and:[dev isPersistentInSnapshot]) ifTrue:[
+                    eachForm getBits
                 ]
             ]
         ]
     ].
     (something == #restarted) ifTrue:[
         "remove all left-over device info"
-        Lobby do:[:aDrawable |
-            aDrawable isForm ifTrue:[
-                aDrawable flushDeviceHandles.
-                Lobby registerChange:aDrawable 
-            ]
+        Form allSubInstancesDo:[:eachForm |
+            eachForm flushDeviceHandles.
         ]
     ]
 
@@ -542,18 +513,6 @@
     "Modified: 19.12.1996 / 13:59:09 / cg"
 !
 
-fromFile:filename on:aDevice
-    "create a new form on device, aDevice and
-     initialize the pixels from the file filename"
-
-    <resource:#obsolete>
-
-    self obsoleteMethodWarning:'please use Image>>fromFile:'.
-    ^ (self onDevice:aDevice) readFromFile:filename
-
-    "Modified: 5.6.1997 / 21:05:59 / cg"
-!
-
 fromFile:filename resolution:dpi
     "create a new form taking the bits from a file on the default device
      the data in the file is assumed to be for dpi resolution;
@@ -586,22 +545,6 @@
     ^ (self onDevice:aDevice) readFromFile:filename resolution:dpi
 
     "Modified: 5.6.1997 / 21:05:54 / cg"
-!
-
-readFrom:fileName
-    "same as Form>>fromFile: - for ST-80 compatibility.
-     WARNING:
-     Please do no longer use this, since it will not work
-     correctly in multi-display applications (creates the form on the
-     default Display).
-     Use #fromFile:on: and pass the device as argument."
-
-    <resource:#obsolete>
-
-    self obsoleteMethodWarning:'please use Image>>fromFile:'.
-    ^ (self onDevice:Screen current) readFromFile:fileName.
-
-    "Modified: 19.12.1996 / 13:59:50 / cg"
 ! !
 
 !Form class methodsFor:'obsolete instance creation'!
@@ -892,26 +835,6 @@
 
 !Form methodsFor:'Compatibility-ST80'!
 
-destroy
-    "destroy my underlying device resource(s)"
-
-    |id|
-
-    (id := gcId) notNil ifTrue:[
-        gcId := nil.
-        device destroyGC:id.
-    ].
-
-    (id := drawableId) notNil ifTrue:[
-        drawableId := nil.
-        device destroyPixmap:id.
-    ].
-
-    Lobby unregister:self.
-
-    "Modified: 2.4.1997 / 19:39:52 / cg"
-!
-
 displayAt:aPoint
     "show the receiver on the current display screen"
 
@@ -999,7 +922,7 @@
 !
 
 magnify:aRectangle by:scale smoothing:smooth
-    ^ ((Image fromSubForm:aRectangle in:self) magnifiedBy:scale) asFormOn:device.
+    ^ ((Image fromSubForm:aRectangle in:self) magnifiedBy:scale) asFormOn:self graphicsDevice.
 ! !
 
 !Form methodsFor:'accessing'!
@@ -1024,10 +947,7 @@
     data notNil ifTrue:[
         ^ data
     ].
-    drawableId isNil ifTrue:[
-        fileName notNil ifTrue:[
-            ^ (self onDevice:Screen current) bits
-        ].
+    self drawableId isNil ifTrue:[
         ^ nil
     ].
 
@@ -1044,7 +964,7 @@
 
     bytesPerLine := (width * spaceBitsPerPixel + 31) // 32 * 4.
     inData := ByteArray uninitializedNew:(bytesPerLine * height).
-    info := device getBitsFromPixmapId:drawableId x:0 y:0 width:width height:height into:inData. 
+    info := self graphicsDevice getBitsFromPixmapId:self drawableId x:0 y:0 width:width height:height into:inData. 
     bytesPerLineIn := (info at:#bytesPerLine).                    "what I got"
     bytesPerLine := (width * depth + 7) // 8.                     "what I want"
     (bytesPerLine ~~ bytesPerLineIn) ifTrue:[
@@ -1146,21 +1066,6 @@
     ^ depth
 !
 
-fileName
-    "return the filename, from which the receiver was created,
-     or nil, if it was not read from a file"
-
-    ^ fileName
-!
-
-filename
-    "return the filename, from which the receiver was created,
-     or nil, if it was not read from a file"
-
-    "/ going to be obsoleted - use #fileName
-    ^ fileName
-!
-
 forgetBits
     "for image, which also keeps the bits - so there is
      no need to hold them again here"
@@ -1237,6 +1142,85 @@
     "Modified: 23.4.1996 / 10:12:48 / cg"
 ! !
 
+!Form methodsFor:'binary storage'!
+
+readBinaryContentsFrom: stream manager: manager
+    "tell the newly restored Form about restoration"
+
+    width := manager nextObject.
+    height := manager nextObject.
+    depth := manager nextObject.
+    offset := manager nextObject.
+    data := manager nextObject.
+
+"/    super readBinaryContentsFrom: stream manager: manager.
+"/    device := nil. "/ Screen current.
+
+    self restored.
+"/    self recreate.
+"/    Lobby register:self.
+
+    "
+     |f|
+
+     f := Form fromFile:'bitmaps/SBrowser.xbm'.
+     f storeBinaryOn:'foo.bos'.
+
+     (Form readBinaryFrom:'foo.bos') inspect
+    "
+!
+
+storeBinaryDefinitionOn: stream manager: manager
+    "store a binary representation of the receiver on stream.
+     This is an internal interface for binary storage mechanism.
+     Redefined to store the actual bits, even if I have been loaded 
+     from a file, and to ommit all device related stuff."
+
+    |bits|
+
+    manager putIdOfClass:(self class) on:stream.
+    manager putIdOf:width on:stream.
+    manager putIdOf:height on:stream.
+    manager putIdOf:depth on:stream.
+    manager putIdOf:offset on:stream.
+    (bits := data) isNil ifTrue:[
+        bits := self bits.
+    ].
+    manager putIdOf:bits on:stream.
+
+"/    savedDevice := device.
+"/    (savedData := data) isNil ifTrue:[
+"/        data := self bits.
+"/    ].
+"/    device := nil.
+"/    super storeBinaryDefinitionOn:stream manager:manager.
+"/    data := savedData.
+"/    device := savedDevice.
+
+    "Modified: 23.4.1996 / 09:30:47 / cg"
+! !
+
+!Form methodsFor:'comanche processing'!
+
+asHtmlElementIn: htmlContainer
+	"answer my HTML representation (String),
+	as I would look like inside htmlContainer"
+
+	^'<IMG SRC="', self comancheUrl, '">'
+!
+
+asHttpResponseTo: request
+	^HttpResponse fromMIMEDocument: self asWebImage
+!
+
+asWebImage
+	"return a MIMEDocument"
+	| aStream |
+	aStream _ (RWBinaryOrTextStream on: '').
+	GIFReadWriter putForm: (self asFormOfDepth: 8) onStream: aStream.
+	aStream reset.
+	^MIMEDocument contentType: MIMEDocument contentTypeGif content: aStream
+! !
 
 !Form methodsFor:'converting'!
 
@@ -1266,20 +1250,15 @@
     "kludge: have to unregister. Otherwise the form will be destroyed when
      we are garbage collected"
 
-    Lobby unregister:self.
-    Lobby registerChange:imageForm.
+    gc finalizationLobby 
+        unregister:gc;
+        registerChange:imageForm graphicsContext.
+
     ^ imageForm.
 ! !
 
 !Form methodsFor:'copying'!
 
-executor
-    "redefined for faster creation of finalization copies
-     (only device, gcId and drawableId are needed)"
-
-    ^ DeviceFormHandle basicNew setDevice:device id:drawableId gcId:gcId.
-!
-
 postCopy
     "redefined to copy the colorMap as well"
 
@@ -1311,7 +1290,7 @@
      and associate it to a device (i.e. download its bits).
      Added for protocol compatibility with Image."
 
-    aDevice == device ifTrue:[
+    aDevice == self graphicsDevice ifTrue:[
         ^ self
     ].
     ^ self onDevice:aDevice
@@ -1323,12 +1302,10 @@
 asMonochromeFormOn:aDevice
     "added for protocol compatiblity with Image"
 
-    aDevice == device ifTrue:[
-        depth == 1 ifTrue:[
+    depth == 1 ifTrue:[
+        aDevice == self graphicsDevice ifTrue:[
             ^ self
         ].
-    ].
-    (depth == 1) ifTrue:[
         ^ self onDevice:aDevice
     ].
     ^ nil
@@ -1377,7 +1354,7 @@
     "associate the receiver to a device (i.e. download its bits);
      return a deviceForm (possibly different from the receiver)."
 
-    aDevice == device ifTrue:[
+    aDevice == self graphicsDevice ifTrue:[
         ^ self
     ].
     aDevice isNil ifTrue:[^ self].
@@ -1388,10 +1365,6 @@
         "/ 'Form [info]: create from data' printCR.
         ^ self class width:width height:height fromArray:data onDevice:aDevice
     ].
-    fileName notNil ifTrue:[
-        "/ 'Form [info]: create from file' printCR.
-        ^ (Image fromFile:fileName) asFormOn:aDevice
-    ].
     'Form [warning]: no bit data in #onDevice: - returning a black form.' infoPrintCR.
     ^ (self class width:width height:height onDevice:aDevice) clear
 
@@ -1475,7 +1448,7 @@
 
     |dstX newForm |
 
-    newForm := (self class onDevice:device)
+    newForm := (self class onDevice:self graphicsDevice)
                                 width:width
                                 height:height
                                 depth:depth.
@@ -1517,7 +1490,7 @@
 
     |dstY newForm |
 
-    newForm := (self class onDevice:device)
+    newForm := (self class onDevice:self graphicsDevice)
                                 width:width
                                 height:height
                                 depth:depth.
@@ -1563,7 +1536,7 @@
      and this operation is slow anyway, use the implementation
      in Image for this."
 
-    ^ ((Image fromForm:self) magnifiedBy:extent) asFormOn:device.
+    ^ ((Image fromForm:self) magnifiedBy:extent) asFormOn:self graphicsDevice.
 
     "
      (Form fromFile:'OutputOn.64') magnifiedBy:0.5@0.5
@@ -1597,7 +1570,7 @@
         ^ self hardMagnifiedBy:ext
     ].
 
-    newForm := (self class onDevice:device)
+    newForm := (self class onDevice:self graphicsDevice)
                                 width:(width * mX)
                                 height:(height * mY)
                                 depth:depth.
@@ -1633,17 +1606,6 @@
 
 !Form methodsFor:'initialization'!
 
-createGC
-    "physically create a device GC.
-     Since we do not need a gc-object for the drawable until something is
-     really drawn, none is created up to the first draw.
-     This method is sent, when the first drawing happens.
-     Redefined here to create a bitmap GC (some devices (i.e. windows) require
-     different GC's for different canvases."
-
-    self createGCForBitmap.
-!
-
 initGC
     "stop server from sending exposure events for Forms -
      (will fill up stream-queue on some stupid (i.e. sco) systems"
@@ -1651,12 +1613,15 @@
     "/ depth-1 forms draw differently ...
 
     depth == 1 ifTrue:[
-	foreground isNil ifTrue:[
-	    foreground := paint := Color colorId:1.
-	].
-	background isNil ifTrue:[
-	    background := bgPaint := Color colorId:0
-	]
+        |fg bg|
+        self foreground isNil ifTrue:[
+            fg := Color colorId:1.
+        ].
+        self background isNil ifTrue:[
+            bg := Color colorId:0
+        ].
+        "nil colors will not be set"
+        self setPaint:fg on:bg.
     ].
     super initGC.
     self setGraphicsExposures:false
@@ -1665,44 +1630,27 @@
 !
 
 initialize
-    foreground := paint := Color colorId:1.
-    background := bgPaint := Color colorId:0.
     depth := 1.
-
     super initialize.
 !
 
 recreate
     "reconstruct the form after a snapin or a migration"
 
-    self device isNil ifTrue:[^ self].
+    self graphicsDevice isNil ifTrue:[^ self].
 
     data notNil ifTrue:[
         "
          create one from data
         "
-        (depth == 1 or:[depth == device depth]) ifTrue:[
-            self createBitmapFromArray:data width:width height:height.
-            Lobby registerChange:self. 
+        (depth == 1 or:[depth == self graphicsDevice depth]) ifTrue:[
+            gc createBitmapFromArray:data width:width height:height.
             self drawableId notNil ifTrue:[
                 ^ self
             ]
         ].
         'FORM: cannot recreate form' errorPrintCR.
     ].
-    fileName notNil ifTrue:[
-        "
-         create one from a file (mhmh - this seems X-specific and will vanish)
-        "
-        self readFromFile:fileName.
-
-"/        drawableId := device createBitmapFromFile:fileName for:self.
-"/        Lobby registerChange:self.
-        self drawableId notNil ifTrue:[
-            ^ self
-        ].
-        'FORM: cannot recreate file form: ' errorPrint. fileName errorPrintCR.
-    ].
 
     ^ self.
 
@@ -1710,11 +1658,10 @@
 "/     create an empty one
 "/    "
 "/    depth == 1 ifTrue:[
-"/        drawableId := device createBitmapWidth:width height:height
+"/        drawableId := self graphicsDevice createBitmapWidth:width height:height
 "/    ] ifFalse:[
-"/        drawableId := device createPixmapWidth:width height:height depth:device depth
+"/        drawableId := self graphicsDevice createPixmapWidth:width height:height depth:self graphicsDevice depth
 "/    ].
-"/    Lobby registerChange:self
 
     "Modified: 15.6.1996 / 16:18:12 / cg"
 !
@@ -1724,9 +1671,17 @@
      The sender has to take care that the Form has been
      unregistered from (Finalization-)Lobby"
 
-    device := drawableId := gcId := nil.
+    self setDevice:nil id:nil gcId:nil
 ! !
 
+!Form methodsFor:'inspecting'!
+
+inspectorClass
+    "redefined to launch an ImageInspector
+     (instead of the default InspectorView)."
+
+    ^ ImageInspectorView
+! !
 
 !Form methodsFor:'printing & storing'!
 
@@ -1749,16 +1704,11 @@
 
 beImmediateForm
     "read the pixels from the device into a local data array. 
-     This makes certain that a fileName form is independent of
-     its fileName.
      To make the image smaller (i.e. not keep all those bitmaps),
      this is NOT done by default."
 
     data isNil ifTrue:[
 	data := self bits.
-	data notNil ifTrue:[
-	    fileName := nil
-	]
     ]
 
     "
@@ -1773,8 +1723,10 @@
 flushDeviceHandles
     "flush device handles (sent after a restart)"
 
-    drawableId := nil.
-    gcId := nil.
+    self setDevice:self graphicsDevice id:nil gcId:nil.
+    gc notNil ifTrue:[
+        gc registerChange.
+    ].
 
     "Created: 15.6.1996 / 15:44:28 / cg"
 !
@@ -1786,90 +1738,11 @@
      an image is saved, or the receiver is storedBinary, since
      the information present in the device is lost after restart/reload"
 
-    (data isNil and:[fileName isNil]) ifTrue:[
+    data isNil ifTrue:[
 	data := self bits
     ]
 !
 
-readFromFile:fn
-    "read a monochrome form from a file (in xbm-format).
-     The fileName argument, fn should be a relative pathname
-     such as bitmaps/foo.xbm and the corresponding file
-     will be searched in the standard places (i.e. along the SEARCHPATH).
-     Notice, when saving an image, only that fileName is kept with the
-     form, and the file is reloaded at image startup time.
-     You should therefore make certain, that the file is present at image
-     reload time. (this is done to make the image smaller ...)
-     If you dont like that behavior (or your application should be able to
-     restart fully standAlone), send #beImmediateForm to all instances of
-     Form - this will set the data instance variable to a ByteArray containing
-     the actual bits and  will therefore no longer depend on the file being present.
-     "
-
-    <resource:#obsolete>
-
-    |pathName|
-
-    "/ this method is a historic leftover; it uses
-    "/ the X-libs bitmap file reading function, which is not
-    "/ available with other windowing systems ...
-    self obsoleteMethodWarning:'use Image fromFile:'.
-
-    pathName := self class findBitmapFile:fn.
-    pathName notNil ifTrue:[
-        drawableId := device createBitmapFromFile:pathName for:self.
-        drawableId isNil ifTrue:[^ nil].
-
-"/        fileName := pathName. "/ keep the actual name (wrong)
-        fileName := fn.         "/ keep the relative name (better - SEARCHPATH may be different at restart)
-
-        offset := 0@0.
-        realized := true.
-        BlackAndWhiteColorMap isNil ifTrue:[
-            BlackAndWhiteColorMap := Array with:(Color white) with:(Color black)
-        ].
-        localColorMap := BlackAndWhiteColorMap.
-        Lobby registerChange:self.
-        ^ self
-    ].
-    ^ nil
-
-    "Modified: 7.2.1996 / 16:04:25 / cg"
-!
-
-readFromFile:filename resolution:dpi
-    "read a monochrome form from a file, which is assumed to have data for a dpi-resolution;
-     if the actual resolution of the device differs, magnify the form.
-     Read the comment in #readFromFile: on what happenes if the file is no longer present
-     after an image reload."
-
-    <resource:#obsolete>
-
-    |dpiH mag dev|
-
-    (self readFromFile:filename) isNil ifTrue:[^ nil].
-
-    "if the device is within +- 50% of dpi, no magnify is needed"
-    dev := self device.
-    dev isNil ifTrue:[
-        "should not happen ..."
-        dev := Screen current
-    ].
-    dpiH := dev isNil ifTrue:[90] ifFalse:[dev horizontalPixelPerInch].
-    ((dpi >= (dpiH * 0.75)) and:[dpi <= (dpiH * 1.5)]) ifTrue:[^ self].
-    mag := (dpiH / dpi) rounded.
-    mag == 0 ifTrue:[
-        ^ self
-    ].
-    ^ self magnifiedBy:(mag @ mag)
-
-    "
-        Form fromFile:'SBrowser.icn' resolution:50
-    "
-
-    "Modified: 7.2.1996 / 16:03:45 / cg"
-!
-
 restored
     "flush device data, when restored (sent after a binaryLoad)"
 
@@ -1900,10 +1773,9 @@
         ].
         localColorMap := BlackAndWhiteColorMap.
     ].
-    device notNil ifTrue:[
-        self createPixmapWidth:w height:h depth:d.
+    self graphicsDevice notNil ifTrue:[
+        gc createPixmapWidth:w height:h depth:d.
         realized := true.
-        Lobby registerChange:self.
     ].
 !
 
@@ -1998,10 +1870,9 @@
     ].
     localColorMap := BlackAndWhiteColorMap.
 
-    device notNil ifTrue:[
-        self createBitmapFromArray:bytes width:w height:h.
+    self graphicsDevice notNil ifTrue:[
+        gc createBitmapFromArray:bytes width:w height:h.
         realized := true.
-        Lobby registerChange:self.
     ].
 !
 
@@ -2036,9 +1907,9 @@
         ^ localColorMap at:(pixel + 1)
     ].
     depth == 1 ifTrue:[
-        pixel == 0 ifTrue:[^ White].
+        pixel == 0 ifTrue:[^ self whiteColor].
     ].
-    ^ Black
+    ^ self blackColor
 
     "Created: 28.6.1996 / 16:10:13 / cg"
     "Modified: 13.1.1997 / 23:06:25 / cg"
@@ -2097,45 +1968,6 @@
     "Modified: 13.5.1996 / 10:26:05 / cg"
 ! !
 
-!Form::DeviceFormHandle class methodsFor:'documentation'!
-
-documentation
-"
-    This is used as a finalization handle for forms - in previous systems,
-    a shallowCopy of a form was responsible to destroy the underlying
-    devices bitmap. To make the memory requirements smaller and to speed up
-    bitmap creation a bit, this lightweight class is used now, which only
-    keeps the device handle for finalization.
-
-    [see also:]
-        DeviceHandle Form
-
-    [author:]
-        Claus Gittinger
-
-"
-! !
-
-!Form::DeviceFormHandle methodsFor:'finalization'!
-
-finalize
-    "the Form for which I am a handle has been collected - tell it to the x-server"
-
-    |id|
-
-    drawableId notNil ifTrue:[
-        (id := gcId) notNil ifTrue:[
-            gcId := nil.
-            device destroyGC:id.
-        ].
-        id := drawableId.
-        drawableId := nil.
-        device destroyPixmap:id.
-    ]
-
-    "Created: 25.9.1997 / 10:03:05 / stefan"
-! !
-
 !Form::ImageForm class methodsFor:'documentation'!
 
 documentation
@@ -2174,7 +2006,7 @@
 !Form class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/Form.st,v 1.149 2014-02-04 15:49:43 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/Form.st,v 1.150.2.1 2014-05-08 08:27:50 stefan Exp $'
 ! !
 
 
--- a/GraphicsContext.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/GraphicsContext.st	Thu May 08 10:27:51 2014 +0200
@@ -9,6 +9,8 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 25-03-2014 at 11:57:17'                   !
+
 "{ Package: 'stx:libview' }"
 
 Object subclass:#GraphicsContext
@@ -350,19 +352,19 @@
     White isNil ifTrue:[
         Color initialize.
 
-        White := Color white.
-        Black := Color black.
-
         Display notNil ifTrue:[
-            White := White onDevice:Display.
-            Black := Black onDevice:Display.
+            White := Display whiteColor.
+            Black := Display blackColor.
+        ] ifFalse:[
+            White := Color white.
+            Black := Color black.
         ].
 
         Font initialize.
         DefaultFont := Font family:'courier' face:'medium' style:'roman' size:12.
         Display notNil ifTrue:[
-	    DefaultFont := DefaultFont onDevice:Display
-	]
+            DefaultFont := DefaultFont onDevice:Display
+        ]
     ]
 
     "Modified: / 29.1.1998 / 12:56:18 / cg"
@@ -695,6 +697,10 @@
     "Modified: 12.5.1996 / 22:25:17 / cg"
 !
 
+blackColor
+    ^ device blackColor
+!
+
 capStyle
     "return the current cap-style for line-drawing.
      possible styles are: #notLast, #butt, #round, #projecting"
@@ -785,6 +791,9 @@
         ].
         ^ rect
     ].
+    transformation notNil ifTrue:[
+        ^ transformation applyInverseTo:clipRect.
+    ].
     ^ clipRect
 
     "Modified: 28.5.1996 / 14:05:15 / cg"
@@ -794,15 +803,25 @@
     "set the clipping rectangle for drawing (in logical coordinates);
      a nil argument turn off clipping (i.e. whole view is drawable)"
 
-    clipRect := aRectangleOrNil
+    (aRectangleOrNil notNil and:[transformation notNil]) ifTrue:[
+        clipRect := transformation applyTo:aRectangleOrNil.
+    ] ifFalse:[
+        clipRect := aRectangleOrNil
+    ].
 
     "Modified: 22.5.1996 / 13:12:07 / cg"
     "Created: 28.5.1996 / 14:09:27 / cg"
 !
 
 clippingBoundsOrNil
-    "return the clipping bounds (a Rectangle) for drawing, nil if there is none."
-
+    "return the clipping bounds (a Rectangle) for drawing in logical coordinates, nil if there is none."
+
+    clipRect isNil ifTrue:[
+        ^ nil
+    ].
+    transformation notNil ifTrue:[
+        ^ transformation applyInverseTo:clipRect.
+    ].
     ^ clipRect
 
     "Created: 10.4.1996 / 14:32:02 / cg"
@@ -830,6 +849,13 @@
     "Modified: 28.5.1996 / 14:08:19 / cg"
 !
 
+createFontOnDevice
+    "make sure, that the font is a device font"
+
+    font := font onDevice:device.
+    ^ font.
+!
+
 dashStyle:aDashList offset:dashOffset
     "define dashes. Each element of the dashList specifies the length
      of a corresponding dash. For example, setting it to [4 4]
@@ -1031,6 +1057,10 @@
     "return the drawables visible origin (for scrolling)"
 
     ^ 0@0
+!
+
+whiteColor
+    ^ device whiteColor
 ! !
 
 !GraphicsContext methodsFor:'accessing-transformation'!
@@ -1276,6 +1306,12 @@
     ^ self subclassResponsibility
 !
 
+displayOpaqueString:aString from:index1 to:index2 x:x y:y maxWitdh:maxWidth
+    "draw part of a string with both fg and bg at x/y in current font"
+
+    ^ self subclassResponsibility
+!
+
 displayPolygon:aPolygon
     "draw a polygon
      - this could be recoded to draw using displayLine"
@@ -1476,17 +1512,20 @@
     |fg bg f noColor|
 
     aFormOrImage depth > 1 ifTrue:[
-	self displayOpaqueForm:aFormOrImage x:x y:y.
-	^ self.
+        self displayOpaqueForm:aFormOrImage x:x y:y.
+        ^ self.
     ].
+"/    aFormOrImage mask notNil ifTrue:[
+"/self halt.
+"/    ].
 
     fg := paint.
     bg := bgPaint.
     f := function.
 
     f ~~ #copy ifTrue:[
-	self error:'function not supported'.
-	^ self
+        self error:'function not supported'.
+        ^ self
     ].
 
     noColor := Color noColor.
@@ -1754,7 +1793,7 @@
     "/ (if you change anything under Unix, make it X-platform specific.
     "/ (there seem to be drawing incompatibilities between Win- and XWorkstation)
 
-    isWin32 := device platformName = 'WIN32'.
+    isWin32 := device isWindowsPlatform.
 
     right := left + width-1.
     bottom := top + height-1.
@@ -1814,6 +1853,12 @@
     self displayString:aString x:aPoint x y:aPoint y
 !
 
+displayString:aString centeredAt:aPoint
+    "draw a string - drawing fg only"
+
+    self displayString:aString centeredAtX:aPoint x y:aPoint y
+!
+
 displayString:aString centeredAtX:x y:y
     "draw a string - drawing fg only"
 
@@ -2094,7 +2139,7 @@
     "draw 3D edges into a rectangle"
     self 
         drawEdgesForX:x y:y width:w height:h level:l 
-        shadow:Black light:White
+        shadow:self blackColor light:self whiteColor
         halfShadow:nil halfLight:nil 
         style:nil 
 !
@@ -2388,7 +2433,7 @@
     wHalf := wC / 2.
     hHalf := hC / 2.
 
-    device platformName = #WIN32 ifTrue:[
+    device isWindowsPlatform ifTrue:[
         "/ bug workaround
         "top left arc"
         self fillArcX:left y:top width:wC height:hC from:90 angle:90.
@@ -2468,6 +2513,12 @@
     device flush
 
     "Modified: 28.5.1996 / 20:22:26 / cg"
+!
+
+sync
+    "send all buffered drawing to the device and wait until the device responds"
+
+    device sync
 ! !
 
 !GraphicsContext methodsFor:'printing & storing'!
@@ -2491,11 +2542,11 @@
 !GraphicsContext class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/GraphicsContext.st,v 1.131 2014-02-04 10:04:37 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/GraphicsContext.st,v 1.136.2.1 2014-05-08 08:27:50 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/GraphicsContext.st,v 1.131 2014-02-04 10:04:37 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/GraphicsContext.st,v 1.136.2.1 2014-05-08 08:27:50 stefan Exp $'
 ! !
 
 
--- a/GraphicsMedium.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/GraphicsMedium.st	Thu May 08 10:27:51 2014 +0200
@@ -9,9 +9,11 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 26-03-2014 at 14:24:09'                   !
+
 "{ Package: 'stx:libview' }"
 
-DeviceGraphicsContext subclass:#GraphicsMedium
+Object subclass:#GraphicsMedium
 	instanceVariableNames:'gc width height realized'
 	classVariableNames:''
 	poolDictionaries:''
@@ -50,6 +52,273 @@
 "
 ! !
 
+!GraphicsMedium class methodsFor:'instance creation'!
+
+new
+    "create a new drawable - take the current display as
+     its device (for now, this may be changed until the view is
+     physically created)"
+
+"
+    'Warning: DeviceGraphicsContext (' print. self name print. ') should not be created with new' printNL.
+"
+    ^ self onDevice:Screen current.
+!
+
+on:aDevice
+    "create a new drawable on aDevice"
+
+    <resource:#obsolete>
+
+    "/ send out a warning: #on: is typically used to create a view
+    "/ operating on a model.
+    "/ Please use #onDevice: to avoid confusion.
+
+    self obsoleteMethodWarning:'use #onDevice:'.
+    ^ self onDevice:aDevice
+
+    "Modified: 5.6.1997 / 21:04:16 / cg"
+!
+
+onDevice:aDevice
+    "create a new drawable on aDevice"
+
+    ^ self basicNew initializeForDevice:aDevice.
+! !
+
+!GraphicsMedium class methodsFor:'Signal constants'!
+
+drawingOnClosedDrawableSignal
+    "return the signal which is raised, if drawing is attempted
+     on a closed drawable.
+     This is especially useful, if a forked thread animates
+     a view in the background, and is not properly synchronized
+     with the window thread - i.e. the window gets closed by the user,
+     and the background process continues to draw.
+     In this case, the background thread should handle this signal
+     and terminate itself in the handler."
+
+    ^ GraphicsContext drawingOnClosedDrawableSignal
+
+    "demonstration1: (error if closed by the windowManager):
+
+     |v|
+
+     v := StandardSystemView new openAndWait.
+     [
+	[true] whileTrue:[
+	    |x y|
+
+	    x := Random nextIntegerBetween:0 and:(v width).
+	    y := Random nextIntegerBetween:0 and:(v height).
+	    v displayString:'hello' x:x y:y.
+	    Delay waitForSeconds:0.5.
+	]
+     ] fork.
+    "
+    "demonstration2: (no error if closed by the windowManager):
+
+     |v|
+
+     v := StandardSystemView new openAndWait.
+     [
+	v class drawingOnClosedDrawableSignal handle:[:ex |
+	    ex return
+	] do:[
+	    [true] whileTrue:[
+		|x y|
+
+		x := Random nextIntegerBetween:0 and:(v width).
+		y := Random nextIntegerBetween:0 and:(v height).
+		v displayString:'hello' x:x y:y.
+		Delay waitForSeconds:0.5.
+	    ]
+	]
+     ] fork.
+    "
+
+    "Created: / 29.1.1998 / 13:10:41 / cg"
+    "Modified: / 29.1.1998 / 13:11:14 / cg"
+! !
+
+!GraphicsMedium class methodsFor:'accessing-defaults'!
+
+defaultFont
+    "get the default font used for drawing"
+
+    ^ GraphicsContext defaultFont
+!
+
+defaultFont:aFont
+    "set the default font used for drawing"
+
+    GraphicsContext defaultFont:aFont
+! !
+
+!GraphicsMedium methodsFor:'Compatibility-ST80'!
+
+displayArc:origin radius:radius from:startAngle angle:angle
+    "draw an arc around a point"
+
+    self
+	displayArcX:(origin x - radius)
+		  y:(origin y - radius)
+	      width:(radius * 2)
+	     height:(radius * 2)
+	       from:startAngle
+	      angle:angle
+
+    "Modified: 8.5.1996 / 08:34:43 / cg"
+!
+
+displayArcBoundedBy:boundingBox startAngle:startAngle sweepAngle:sweepAngle
+   "draw an arc/circle/ellipse - ST-80 compatibility"
+
+   ^ self displayArcX:(boundingBox left)
+		    y:(boundingBox top)
+		width:(boundingBox width)
+	       height:(boundingBox height)
+		 from:startAngle
+		angle:sweepAngle
+
+    "Created: / 14.11.1997 / 21:04:19 / cg"
+!
+
+displayArcBoundedBy:boundingBox startAngle:startAngle sweepAngle:sweepAngle at:origin
+   "draw an arc/circle/ellipse - ST-80 compatibility"
+
+   ^ self displayArcX:(boundingBox left + origin x)
+		    y:(boundingBox top + origin y)
+		width:(boundingBox width)
+	       height:(boundingBox height)
+		 from:startAngle
+		angle:sweepAngle
+!
+
+displayLineFrom:startPoint to:endPoint translateBy:anOffset
+    "draw a line - ST-80 compatibility"
+
+    self displayLineFrom:(startPoint + anOffset)
+		      to:(endPoint + anOffset)
+!
+
+displayPolyline:aPolygon
+    "draw a polygon - ST-80 compatibility"
+
+    ^ self displayPolygon:aPolygon
+!
+
+displayRectangularBorder:aRectangle
+    "draw a rectangle - ST-80 compatibility"
+
+    self displayRectangle:aRectangle
+!
+
+displayRectangularBorder:aRectangle at:aPoint
+    "draw a rectangle - ST-80 compatibility"
+
+    self displayRectangle:(aRectangle translateBy:aPoint)
+!
+
+displayWedgeBoundedBy:boundingBox startAngle:startAngle sweepAngle:sweepAngle
+   "fill an arc/circle/ellipse - ST-80 compatibility"
+
+   ^ self fillArcX:(boundingBox left)
+		 y:(boundingBox top)
+	     width:(boundingBox width)
+	    height:(boundingBox height)
+	      from:startAngle
+	     angle:sweepAngle
+
+    "Created: 27.1.1997 / 15:50:14 / cg"
+!
+
+displayWedgeBoundedBy:boundingBox startAngle:startAngle sweepAngle:sweepAngle at:origin
+   "fill an arc/circle/ellipse - ST-80 compatibility"
+
+   ^ self fillArcX:(boundingBox left + origin x)
+		 y:(boundingBox top + origin y)
+	     width:(boundingBox width)
+	    height:(boundingBox height)
+	      from:startAngle
+	     angle:sweepAngle
+!
+
+findFont:aFontDescription
+    "given a fontDescription, return a device font for it
+     on my device."
+
+    ^ aFontDescription onDevice:self device
+
+    "Modified: 28.5.1996 / 20:22:29 / cg"
+!
+
+key
+    ^ self id
+!
+
+phase
+    "return the origin within the mask (used to draw with patterns).
+     This is an alias for ST/X's #maskOrigin"
+
+    ^ self maskOrigin
+!
+
+phase:aPoint
+    "set the origin within the mask (used to draw with patterns).
+     This is an alias for ST/X's #maskOrigin:"
+
+    ^ self maskOrigin:aPoint
+!
+
+setDevicePattern:aColorOrMask
+    "ST/X can paint in any color or image"
+
+    self paint:aColorOrMask
+!
+
+tilePhase
+    "return the origin within the mask (used to draw with patterns).
+     This is an alias for ST/X's #maskOrigin"
+
+    ^ self maskOrigin
+
+    "Created: 4.6.1996 / 15:26:39 / cg"
+!
+
+tilePhase:aPoint
+    "set the origin within the mask (used to draw with patterns).
+     This is an alias for ST/X's #maskOrigin"
+
+    ^ self maskOrigin:aPoint
+
+    "Created: 4.6.1996 / 15:26:49 / cg"
+!
+
+widthOfString:aString
+    "given a string, return its width in pixels if
+     drawn on the receivers device."
+
+    gc == self ifTrue:[
+        ^ super widthOfString:aString.
+    ].
+    ^ gc widthOfString:aString.
+
+    "Modified: 28.5.1996 / 20:22:22 / cg"
+!
+
+widthOfString:aString from:start to:stop
+    "given a string, return the width in pixels if
+     a substring is drawn on the receivers device."
+
+    gc == self ifTrue:[
+        ^ super widthOfString:aString from:start to:stop.
+    ].
+    ^ gc widthOfString:aString from:start to:stop.
+
+    "Modified: 28.5.1996 / 20:22:18 / cg"
+! !
+
 !GraphicsMedium methodsFor:'Compatibility-Squeak'!
 
 copyBits:aRectangle from:aForm at:srcOrigin clippingBox:clippingBox rule:rule fillColor:fillColor
@@ -57,24 +326,55 @@
 
     (f := rule) isInteger ifTrue:[
 	"/ ST-80 compatibility: numeric rule
-	f := #(#clear #and #andReverse  #copy #andInverted #noop #xor #or #nor #equiv #invert #orInverted #copyInverted
-	       #orReverse #nand #set) at:(rule + 1).
+	f := #(clear and andReverse  copy andInverted noop xor or nor equiv invert orInverted copyInverted
+	       orReverse nand set) at:(rule + 1).
     ].
 
-    oldFunction := function.
-    oldClip := clipRect.
-"/
-    self clippingRectangle:clippingBox.
-    self function:f.
-
-    self
+    oldFunction := gc function.
+    oldClip := gc clippingRectangleOrNil.
+
+    gc clippingRectangle:clippingBox.
+    gc function:f.
+
+    gc
 	copyFrom:aForm
 	x:srcOrigin x y:srcOrigin y
 	toX:aRectangle left y:aRectangle top
 	width:aRectangle width height:aRectangle height.
 
-    self clippingRectangle:oldClip.
-    self function:oldFunction.
+    gc clippingRectangle:oldClip.
+    gc function:oldFunction.
+
+    "
+      |dst src|
+
+      dst := Form width:8 height:8 fromArray:#[
+					      2r00000000
+					      2r00000000
+					      2r00000000
+					      2r00000000
+					      2r11111111
+					      2r11111111
+					      2r11111111
+					      2r11111111
+					     ].
+      src := Form width:8 height:8 fromArray:#[
+					      2r00001111
+					      2r00001111
+					      2r00001111
+					      2r00001111
+					      2r00001111
+					      2r00001111
+					      2r00001111
+					      2r00001111
+					     ].
+
+    dst copyBits:(0@0 corner:8@8) from:src at:0@0 clippingBox:(0@0 corner:8@8) rule:15 fillColor:Color black.
+    dst inspect
+
+    "
+
+    "Modified: / 23.10.2000 / 16:50:44 / martin"
 
     "
       |dst src|
@@ -111,18 +411,17 @@
 fill:aRectangle fillColor:aColor
     "fill the rectangular area specified by aRectangle with the black color"
 
-    |oldPaint|
-
-    oldPaint := paint.
-    gc paint:aColor.
-    gc fillRectangleX:aRectangle left y:aRectangle top width:aRectangle width height:aRectangle height.
-    gc paint:oldPaint
+    gc == self ifTrue:[
+	super fill:aRectangle fillColor:aColor.
+	^ self.
+    ].
+    gc fill:aRectangle fillColor:aColor
 !
 
 fillBlack:aRectangle
     "fill the rectangular area specified by aRectangle with the black color"
 
-    self fill:aRectangle fillColor:Black
+    self fill:aRectangle fillColor:Color black
 !
 
 fillColor:something
@@ -132,14 +431,154 @@
     self fill:something
 !
 
+fillRectangle:aRectangle color:aColor
+    "fill a rectangle with the given paint color"
+
+    gc == self ifTrue:[
+	super fillRectangle:aRectangle color:aColor.
+	^ self.
+    ].
+    gc fillRectangle:aRectangle color:aColor
+!
+
+fillWhite
+    "fill all of the receiver with the white color"
+
+    self fill:Color white
+!
+
 fillWhite:aRectangle
     "fill the rectangular area specified by aRectangle with the white color"
 
-    self fill:aRectangle fillColor:White
+    self fill:aRectangle fillColor:Color white
+! !
+
+!GraphicsMedium methodsFor:'Compatibility-VW'!
+
+displayBackgroundIfNeededOn: aGraphicsContext
+    aGraphicsContext clearView.
+!
+
+inactiveForegroundColor
+    "a dummy method to support VW widgets"
+
+    ^ self foregroundColor
+!
+
+selectionBackgroundColor
+    "a dummy method to support VW widgets"
+
+    ^ self foregroundColor
+!
+
+selectionForegroundColor
+    "a dummy method to support VW widgets"
+
+    ^ self backgroundColor
+!
+
+separatorColor
+    "a dummy method to support VW widgets"
+
+    ^ self foregroundColor
 ! !
 
 !GraphicsMedium methodsFor:'accessing'!
 
+at:aPoint
+    "return the pixel at the coordinate given by aPoint"
+
+    ^ self atX:aPoint x y:aPoint y
+
+    "Modified: / 29.1.2000 / 12:17:42 / cg"
+!
+
+at:aPoint put:aPixelColor
+    "set a pixel"
+
+    ^ self atX:aPoint x y:aPoint y put:aPixelColor
+
+    "
+     Display rootView at:(0@0) put:(Color red).
+     Display rootView at:(1@1) put:(Color red).
+     Display rootView at:(2@2) put:(Color red).
+     Display rootView at:(3@3) put:(Color red).
+     Display rootView at:(4@4) put:(Color red).
+     Display rootView at:(5@5) put:(Color red).
+    "
+!
+
+atX:x y:y
+    "return the pixel at the coordinate given by x/y"
+
+    gc == self ifTrue:[
+	^ super atX:x y:y
+    ].
+    ^ gc atX:x y:y
+!
+
+atX:x y:y put:aPixelColor
+    "set a pixel"
+
+    gc == self ifTrue:[
+	super atX:x y:y put:aPixelColor.
+	^ self.
+    ].
+    gc atX:x y:y put:aPixelColor.
+!
+
+backgroundPaint
+    "return the background paint color.
+     (used for opaqueForms and opaqueStrings)"
+
+    gc == self ifTrue:[
+	^ super backgroundPaint.
+    ].
+    ^ gc backgroundPaint
+!
+
+backgroundPaint:aColor
+    "set the background-paint color; this is used in opaque-draw
+     operations"
+
+    gc == self ifTrue:[
+	super backgroundPaint:aColor.
+	^ self.
+    ].
+    gc backgroundPaint:aColor
+!
+
+basicFont
+    "return the font for drawing"
+
+    gc == self ifTrue:[
+	^ super basicFont.
+    ].
+    ^ gc basicFont
+!
+
+basicFont:aFont
+    "set the font for drawing if it has changed.
+     This is a low level entry, which is not to be redefined
+     (i.e. it must not imply a redraw operation)"
+
+    gc == self ifTrue:[
+	super basicFont:aFont.
+	^ self.
+    ].
+    gc basicFont:aFont
+!
+
+blackColor
+    gc isNil ifTrue:[
+        ^ Color black.
+    ].
+    gc == self ifTrue:[
+        ^ super device blackColor.
+    ].
+    ^ gc device blackColor
+!
+
 bottomCenter
     "return the topCenter point"
 
@@ -159,23 +598,184 @@
 
 !
 
+capStyle
+    "return the current cap-style for line-drawing.
+     possible styles are: #notLast, #butt, #round, #projecting"
+
+    gc == self ifTrue:[
+	^ super capStyle.
+    ].
+    ^ gc capStyle
+!
+
+capStyle:aStyleSymbol
+    "set the cap-style for line-drawing;
+     possible styles are: #notLast, #butt, #round, #projecting"
+
+    gc == self ifTrue:[
+	super capStyle:aStyleSymbol.
+	^ self.
+    ].
+    gc capStyle:aStyleSymbol
+
+    "Modified: 12.5.1996 / 22:24:30 / cg"
+!
+
 center
     "return the point at the center of the receiver"
 
     ^ (self left + (width // 2)) @ (self top + (height // 2))
 !
 
+characterEncoding
+    "returns a symbol describing how the contents is encoded internally.
+     For now, this should be the same encoding as my fonts encoding (otherwise, mappings would
+     occur when drawing).
+     This is (currently) only passed down from the fileBrowser,
+     and required when japanese/chinese/korean text is edited.
+     (encoding is something like #'iso8859-5' #euc, #sjis, #jis7, #gb, #big5 or #ksc)"
+
+    gc == self ifTrue:[
+	^ super characterEncoding.
+    ].
+    ^ gc characterEncoding
+!
+
+characterEncoding:encodingArg
+    "define how the contents is encoded internally.
+     This should normally never be required, as ST/X now assumes
+     unicode (of which iso8859-1 is a subset) encoding.
+     The possibility to change the characterEncoding is provided as
+     a backward compatibility hook for programs which want to use
+     another encoding internally. One such view is the CharacterSetView,
+     which wants to show character as they are actually present in a font."
+
+    gc == self ifTrue:[
+	super characterEncoding:encodingArg.
+	^ self.
+    ].
+    gc characterEncoding:encodingArg
+!
+
+clipByChildren
+    "drawing shall be done into my view only (default)"
+
+    <resource:#obsolete>
+
+    self obsoleteMethodWarning:'use #clippedByChildren:true'.
+    ^ self clippedByChildren:true
+
+    "Created: 17.7.1996 / 13:25:55 / cg"
+!
+
+clipRect
+    "return the clip-rectangle for drawing.
+     If there is currently no active clip, return the underlying
+     displaySurfaces (i.e. views) bounds. Added for ST-80 compatibility."
+
+    <resource:#obsolete>
+
+    self obsoleteMethodWarning:'use #clippingBounds'.
+    ^ self clippingBounds.
+
+    "Modified: 28.5.1996 / 14:14:53 / cg"
+!
+
+clipRect:aRectangle
+    "set the drawing clip-rectangle"
+
+    <resource:#obsolete>
+
+    self obsoleteMethodWarning:'use #deviceClippingBounds:'.
+    ^ gc deviceClippingBounds:aRectangle
+
+    "Modified: 28.5.1996 / 14:13:09 / cg"
+!
+
+clippedByChildren:aBoolean
+    "turn on/off drawing over children.
+     If on, a superview may draw 'over' its children.
+     If off (the default), drawing is 'under' its children.
+     Only useful for the rootView, to draw over any visible views.
+     (for example, when dragging a rubber-line)"
+
+    gc == self ifTrue:[
+        super clippedByChildren:aBoolean.
+        ^ self.
+    ].
+    gc clippedByChildren:aBoolean.
+
+    "Created: 17.7.1996 / 13:25:16 / cg"
+    "Modified: 29.4.1997 / 15:33:55 / dq"
+!
+
 clippingBounds
-    "return the clipping rectangle for drawing (in logical coordinates). 
-     If there is currently no clippingBounds, a dummy is created."
-
-    clipRect notNil ifTrue:[
-        ^ clipRect.
-    ] ifFalse:[
-        ^ Rectangle
-            origin: 0 @ 0
-            corner: width @ height
+    "return the clipping rectangle for drawing, nil if there is none."
+
+    gc == self ifTrue:[
+        ^ super clippingBounds.
+    ].
+    ^ gc clippingBounds
+!
+
+clippingBounds:aRectangleOrNil
+    "set the clipping rectangle for drawing (in logical coordinates);
+     a nil argument turn off clipping (i.e. whole view is drawable)"
+
+    gc == self ifTrue:[
+        super clippingBounds:aRectangleOrNil.
+        ^ self.
+    ].
+    gc clippingBounds:aRectangleOrNil
+!
+
+clippingBoundsOrNil
+    "return the clipping rectangle for drawing, nil if there is none."
+
+    gc == self ifTrue:[
+        ^ super clippingBoundsOrNil.
     ].
+    ^ gc clippingBoundsOrNil
+!
+
+clippingRectangle:aRectangleOrNil
+    "set the clipping rectangle for drawing (in logical coordinates);
+     a nil argument turn off clipping (i.e. whole view is drawable)"
+
+    <resource: #obsolete>
+
+    self clippingBounds:aRectangleOrNil
+!
+
+clippingRectangleOrNil
+    "return the clipping rectangle for drawing, nil if there is none."
+
+    <resource: #obsolete>
+
+    ^ self clippingBoundsOrNil
+!
+
+colorAt:aPoint
+    "return the color of the pixel at the coordinate given by x@y"
+
+    ^ self colorAtX:(aPoint x) y:(aPoint y)
+
+    "Modified: 1.8.1997 / 20:01:58 / cg"
+!
+
+colorAtX:x y:y
+    "return the color of the pixel at the coordinate given by aPoint"
+
+    gc == self ifTrue:[
+	^ super colorAtX:x y:y.
+    ].
+    ^ gc colorAtX:x y:y
+!
+
+container
+    "return my container - for protocol compatibility"
+
+    ^ nil
 !
 
 corner
@@ -193,6 +793,74 @@
 		(aPoint y - self top + 1)
 !
 
+dashStyle:aDashList offset:dashOffset
+    "define dashes. Each element of the dashList specifies the length
+     of a corresponding dash. For example, setting it to [4 4]
+     defines 4on-4off dashing;
+     Setting it to [1 2 4 2] defines 1on-2off-4on-2off dashes.
+     The dashOffset specifies where in the dashList the dashing starts.
+     Ignored here - this may not be supported by all graphics devices."
+
+    gc == self ifTrue:[
+	^ super dashStyle:aDashList offset:dashOffset.
+    ].
+    ^ gc dashStyle:aDashList offset:dashOffset
+!
+
+device
+    "return the device, the receiver is associated with"
+
+    gc == self ifTrue:[
+        ^ super device.
+    ].
+    gc isNil ifTrue:[
+        ^ nil.
+    ].
+    ^ gc device
+!
+
+device:aDevice
+    "set the device"
+
+    aDevice isNil ifTrue:[
+        ^ self.
+    ].
+
+    gc isNil ifTrue:[
+        gc := aDevice newGraphicsContextFor:self.
+        ^ self.
+    ].
+
+    gc == self ifTrue:[
+        super device:aDevice.
+    ] ifFalse:[
+        gc device:aDevice
+    ].
+!
+
+deviceClippingRectangle:aRectangleOrNil
+    "set the clipping rectangle for drawing (in device coordinates);
+     a nil argument turns off clipping (i.e. whole view is drawable - incl. margins)"
+
+    gc == self ifTrue:[
+	super deviceClippingRectangle:aRectangleOrNil.
+	^ self.
+    ].
+    gc deviceClippingRectangle:aRectangleOrNil
+!
+
+drawableId
+    "return the id of the drawable on the device"
+
+    gc == self ifTrue:[
+        ^ super drawableId.
+    ].
+    gc isNil ifTrue:[
+        ^ nil.
+    ].
+    ^ gc drawableId
+!
+
 extent
     "return the extent i.e. a point with width as x, height as y
      coordinate"
@@ -207,6 +875,77 @@
     height := extent y
 !
 
+font
+    "return the current drawing font"
+
+    gc == self ifTrue:[
+	^ super font.
+    ].
+    ^ gc font
+!
+
+font:aFont
+    "set the font for drawing if it has changed.
+     This should be redefined in some widget to perform an automatic
+     redraw. See also: #basicFont:"
+
+    gc == self ifTrue:[
+        super font:aFont.
+    ] ifFalse:[
+        gc font:aFont.
+    ].
+    self changed:#font.
+!
+
+function
+    "return the current drawing function"
+
+    gc == self ifTrue:[
+	^ super function.
+    ].
+    ^ gc function
+!
+
+function:aSymbol
+    "set the drawing function if it has changed"
+
+    gc == self ifTrue:[
+	super function:aSymbol.
+	^ self.
+    ].
+    gc function:aSymbol
+!
+
+gcId
+    "return the receivers graphic context id on the device"
+
+    gc == self ifTrue:[
+        ^ super gcId.
+    ].
+    gc isNil ifTrue:[
+        ^ nil.
+    ].
+    ^ gc gcId.
+!
+
+graphicsContext
+    "for ST-80 compatibility"
+
+    ^ gc
+!
+
+graphicsDevice
+    "same as #device, for ST-80 compatibility"
+
+    gc == self ifTrue:[
+        ^ super graphicsDevice.
+    ].
+    gc isNil ifTrue:[
+        ^ nil.
+    ].
+    ^ gc graphicsDevice
+!
+
 height
     "return the height of the receiver"
 
@@ -219,6 +958,33 @@
     height := anInteger
 !
 
+id
+    "return the id of the drawable on the device"
+
+    ^ self drawableId
+!
+
+joinStyle
+    "return the current join-style for polygon-drawing.
+     possible styles are: #miter, #bevel, #round"
+
+    gc == self ifTrue:[
+	^ super joinStyle.
+    ].
+    ^ gc joinStyle
+!
+
+joinStyle:aStyleSymbol
+    "set the join-style of lines in polygon-drawing;
+     possible styles are: #miter, #bevel, #round"
+
+    gc == self ifTrue:[
+	super joinStyle:aStyleSymbol.
+	^ self.
+    ].
+    gc joinStyle:aStyleSymbol
+!
+
 left
     "return the left i.e. x-coordinate of top-left of the receiver"
 
@@ -231,29 +997,177 @@
     ^ (self left) @ (self top + (height // 2) - 1)
 !
 
+lineStyle
+    "return the current line-drawing-style.
+     possible styles are: #solid, #dashed, #doubleDashed,
+     #dotted, #dashDot or #dashDotDot."
+
+    gc == self ifTrue:[
+	^ super lineStyle.
+    ].
+    ^ gc lineStyle
+!
+
+lineStyle:aStyleSymbol
+    "set the line-drawing-style;
+     possible styles are: #solid, #dashed, #doubleDashed,
+     #dotted, #dashDot or #dashDotDot."
+
+    gc == self ifTrue:[
+	super lineStyle:aStyleSymbol.
+	^ self.
+    ].
+    gc lineStyle:aStyleSymbol
+!
+
+lineWidth
+    "return the current drawing linewidth"
+
+    gc == self ifTrue:[
+	^ super lineWidth.
+    ].
+    ^ gc lineWidth
+!
+
+lineWidth:aNumber
+    "set the line drawing width in pixels"
+
+    gc == self ifTrue:[
+	super lineWidth:aNumber.
+	^ self.
+    ].
+    gc lineWidth:aNumber
+!
+
+mask
+    "return the current drawing mask"
+
+    gc == self ifTrue:[
+	^ super mask.
+    ].
+    ^ gc mask
+!
+
+mask:aForm
+    "set the drawing mask"
+
+    gc == self ifTrue:[
+	super mask:aForm.
+	^ self.
+    ].
+    gc mask:aForm
+!
+
+maskOrigin
+    "return the origin within the mask (used to draw with patterns).
+     Should be redefined in classes which support it.
+     This is an alias for ST-80's #phase"
+
+    gc == self ifTrue:[
+	^ super maskOrigin.
+    ].
+    ^ gc maskOrigin
+!
+
+maskOrigin:aPoint
+    "set the origin within the mask (used to draw with patterns).
+     Should be redefined in classes which support it.
+     This is an alias for ST-80's #phase:"
+
+    gc == self ifTrue:[
+	super maskOrigin:aPoint.
+	^ self.
+    ].
+    gc maskOrigin:aPoint
+!
+
+maskOriginX:x y:y
+    "set the origin within the mask (used to draw with patterns).
+     Should be redefined in classes which support it.
+     This is an alias for ST-80's #phase:"
+
+    self maskOrigin:(x @ y)
+!
+
+medium
+    "return the destination medium i.e. the underlying graphics device"
+
+    gc == self ifTrue:[
+        ^ super graphicsDevice.
+    ].
+    ^ gc graphicsDevice
+!
+
+noClipByChildren
+    "drawing shall also be done into subviews"
+
+    <resource:#obsolete>
+
+    self obsoleteMethodWarning:'use #clippedByChildren:false'.
+    ^ self clippedByChildren:false
+
+    "Created: 17.7.1996 / 14:15:54 / cg"
+!
+
 origin
     "return the origin i.e. coordinate of top-left of the receiver"
 
     ^ 0 @ 0
 !
 
+paint
+    "return the current paint drawing color"
+
+    gc == self ifTrue:[
+	^ super paint.
+    ].
+    ^ gc paint
+!
+
+paint:aColor
+    "set the drawing painting color, aColor can be a dithered one"
+
+    gc == self ifTrue:[
+	super paint:aColor.
+	^ self.
+    ].
+    gc paint:aColor
+!
+
+paint:fgColor on:bgColor
+    "set the paint and backgroundPaint, used for text and bitmaps.
+     Both colors may be dithered colors"
+
+    gc == self ifTrue:[
+	super paint:fgColor on:bgColor.
+	^ self.
+    ].
+    gc paint:fgColor on:bgColor
+!
+
+paint:fgColor on:bgColor function:f
+    "set paint, background-paint and function"
+
+    self paint:fgColor on:bgColor.
+    self function:f
+
+    "Modified: 16.5.1996 / 15:36:35 / cg"
+!
+
 realized
     "return true, if the receiver is realized.
-     Realized means that it has been mapped (i.e. made visible) on
-     the display (as opposed to being only created and possibly invisible).
-     The receiver may still be actually still unmapped (invisible), if the container is not
-     yet realized.
+     The receiver may still be unmapped, if the container is unrealized.
      Use reallyRealized to make certain that I am really mapped."
 
     ^ realized
 !
 
 reallyRealized
-    "return true, if the receiver is realized and all containers are realized. 
-     Realized means that it has been mapped (i.e. made visible) on
-     the display (as opposed to being only created and possibly invisible)"
+    "return true, if the receiver is realized and all containers
+     are realized."
 
     ^ self realized
+
 !
 
 rightCenter
@@ -262,6 +1176,45 @@
     ^ (self left + width - 1) @ (self top + (height // 2) - 1)
 !
 
+setClippingBounds:aRectangleOrNil
+    gc == self ifTrue:[
+        super setClippingBounds:aRectangleOrNil.
+        ^ self.
+    ].
+    gc setClippingBounds:aRectangleOrNil
+!
+
+setGraphicsExposures:aBoolean
+    "want to if aBoolean is true - or don't want to be notified
+     of graphics exposures"
+
+    gc == self ifTrue:[
+	super setGraphicsExposures:aBoolean.
+	^ self.
+    ].
+    gc setGraphicsExposures:aBoolean
+!
+
+setMaskOrigin:aPoint
+    <resource: #obsolete>
+    "set the origin within the mask (used to draw with patterns).
+     OBSOLETE: use #maskOrigin: or #phase:"
+
+    self obsoleteMethodWarning:'use #maskOrigin:'.
+    ^ self maskOriginX:aPoint x y:aPoint y
+
+    "Modified: / 26.1.1998 / 18:54:14 / cg"
+!
+
+setMaskOriginX:x y:y
+    <resource: #obsolete>
+    "set the origin within the mask (used to draw with patterns).
+     OBSOLETE: use #maskOriginX:y: or #phase:"
+
+    self obsoleteMethodWarning:'use #maskOriginX:y:'.
+    ^ self maskOriginX:x y:y
+!
+
 setWidth:w height:h
     "set both width and height - not to be redefined"
 
@@ -290,7 +1243,23 @@
 viewBackground
     "for protocol compatibility with view; return my background paint color here"
 
-    ^ bgPaint
+    ^ self backgroundPaint
+!
+
+viewOrigin
+    "return the drawables visible origin (for scrolling)"
+
+    ^ 0@0
+!
+
+whiteColor
+    gc isNil ifTrue:[
+        ^ Color white.
+    ].
+    gc == self ifTrue:[
+        ^ super graphicsDevice whiteColor.
+    ].
+    ^ gc graphicsDevice whiteColor
 !
 
 width
@@ -312,6 +1281,431 @@
     height := h
 ! !
 
+!GraphicsMedium methodsFor:'accessing-internals'!
+
+background
+    <resource: #obsolete>
+    "return the current background drawing color.
+     OBSOLETE: use #paint: / #backgroundPaint: / #paint:on:"
+
+    gc == self ifTrue:[
+	^ super background.
+    ].
+    ^ gc background
+
+    "Modified: 12.5.1996 / 22:28:09 / cg"
+!
+
+background:aColor
+    <resource: #obsolete>
+    "set the internal background color for drawing - aColor must be a real color.
+     OBSOLETE: this method will vanish; use #paint: / #backgroundPaint: / #paint:on:"
+
+    gc == self ifTrue:[
+	super background:aColor.
+	^ self.
+    ].
+    gc background:aColor
+!
+
+foreground
+    <resource: #obsolete>
+    "return the current foreground drawing color.
+     OBSOLETE: use #paint: / #paint:on:"
+
+    gc == self ifTrue:[
+	^ super foreground.
+    ].
+    ^ gc foreground
+!
+
+foreground:aColor
+    <resource: #obsolete>
+    "set the internal foreground color for drawing - aColor must be a real color.
+     OBSOLETE: this method will vanish; use #paint: / #paint:on:"
+
+    gc == self ifTrue:[
+	super foreground:aColor.
+	^ self.
+    ].
+    gc foreground:aColor
+!
+
+foreground:fgColor background:bgColor
+    <resource: #obsolete>
+    "set both internal foreground and internal background colors
+     - these must be real colors.
+     OBSOLETE: this method will vanish; use #paint: / #paint:on:"
+
+    gc == self ifTrue:[
+	super foreground:fgColor background:bgColor.
+	^ self.
+    ].
+    gc foreground:fgColor background:bgColor
+!
+
+foreground:fgColor background:bgColor function:fun
+    <resource: #obsolete>
+    "set foreground, background colors and function.
+     OBSOLETE: this method will vanish; use #paint: / #paint:on:"
+
+    self foreground:fgColor background:bgColor.
+    self function:fun
+
+    "Modified: 12.5.1996 / 22:28:34 / cg"
+!
+
+foreground:aColor function:fun
+    <resource: #obsolete>
+    "set the foreground color and function for drawing.
+     OBSOLETE: this method will vanish; use #paint: / #paint:on:"
+
+    gc == self ifTrue:[
+	super foreground:aColor function:fun.
+	^ self.
+    ].
+    gc foreground:aColor function:fun
+!
+
+setRealized:aBoolean
+    "low level special interface to manipulate the realized state.
+     Non-public interface, only to be used by experts.
+     (use to pretend a view has been realized - for example with alien views)"
+
+    realized := aBoolean
+! !
+
+!GraphicsMedium methodsFor:'accessing-transformation'!
+
+scale
+    "return the scale factor (as point) of the transformation"
+
+    gc == self ifTrue:[
+        ^ super scale.
+    ].
+    ^ gc scale
+!
+
+scale:aPoint
+    "set the scale factor of the transformation"
+
+    gc == self ifTrue:[
+        super scale:aPoint.
+        ^ self.
+    ].
+    ^ gc scale:aPoint
+!
+
+transformation 
+    "return the transformation"
+
+    gc == self ifTrue:[
+        ^ super transformation.
+    ].
+    ^ gc transformation
+!
+
+transformation:aTransformation 
+    "set the transformation"
+
+    gc == self ifTrue:[
+        super transformation:aTransformation.
+        ^ self.
+    ].
+    ^ gc transformation:aTransformation
+!
+
+translateBy:aPoint
+    "add to the translation offset of the transformation"
+
+    gc == self ifTrue:[
+        super translateBy:aPoint.
+        ^ self.
+    ].
+    ^ gc translateBy:aPoint
+!
+
+translation
+    "return the translation factor (as point) of the transformation"
+
+    gc == self ifTrue:[
+        ^ super translation.
+    ].
+    ^ gc translation
+!
+
+translation:aPoint
+    "set the translation offset of the transformation"
+
+    gc == self ifTrue:[
+        super translation:aPoint.
+        ^ self.
+    ].
+    ^ gc translation:aPoint
+! !
+
+!GraphicsMedium methodsFor:'basic drawing'!
+
+displayArcX:x y:y width:width height:height from:startAngle angle:angle
+    "draw an arc in a box
+     - this could be recoded to draw using displayLine"
+
+    gc == self ifTrue:[
+	super displayArcX:x y:y width:width height:height from:startAngle angle:angle.
+	^ self.
+    ].
+    gc displayArcX:x y:y width:width height:height from:startAngle angle:angle
+!
+
+displayDottedRectangleX:x y:y width:w height:h
+    "draw a dotted-line rectangle
+     A general implementation is found here; deviceGC's
+     may reimplement this if directly supported by the device"
+
+    gc == self ifTrue:[
+	super displayDottedRectangleX:x y:y width:w height:h.
+	^ self.
+    ].
+    gc displayDottedRectangleX:x y:y width:w height:h
+!
+
+displayHorizontalWavelineFromX:x0 y:y0 toX:x1
+    "draw a horizontal wave-line from x0/y0 to x1/y0"
+
+    gc == self ifTrue:[
+	super displayHorizontalWavelineFromX:x0 y:y0 toX:x1.
+	^ self.
+    ].
+    gc displayHorizontalWavelineFromX:x0 y:y0 toX:x1
+!
+
+displayLineFromX:x0 y:y0 toX:x1 y:y1
+    "draw a line from x0/y0 to x1/y1"
+
+    gc == self ifTrue:[
+	super displayLineFromX:x0 y:y0 toX:x1 y:y1.
+	^ self.
+    ].
+    gc displayLineFromX:x0 y:y0 toX:x1 y:y1
+!
+
+displayOpaqueForm:aForm x:x y:y
+    "draw a form at x/y; if the form has depth 1, 1's in the form are
+     drawn in current fg, 0's in current bg color.
+     If the form has depth ~~ 1, it is copied as is onto the receiver"
+
+    gc == self ifTrue:[
+	super displayOpaqueForm:aForm x:x y:y.
+	^ self.
+    ].
+    gc displayOpaqueForm:aForm x:x y:y
+!
+
+displayOpaqueString:aString from:index1 to:index2 x:x y:y
+    "draw part of a string with both fg and bg at x/y in current font"
+
+    gc == self ifTrue:[
+        super displayString:aString from:index1 to:index2 x:x y:y opaque:true maxWidth:self width.
+        ^ self.
+    ].
+    gc displayString:aString from:index1 to:index2 x:x y:y opaque:true maxWidth:self width
+!
+
+displayPolygon:aPolygon
+    "draw a polygon
+     - this could be recoded to draw using displayLine"
+
+    gc == self ifTrue:[
+	super displayPolygon:aPolygon.
+	^ self.
+    ].
+    gc displayPolygon:aPolygon
+!
+
+displayRectangleX:x y:y width:w height:h
+    "draw a rectangle
+     - this could be recoded to draw using displayLine"
+
+    gc == self ifTrue:[
+	super displayRectangleX:x y:y width:w height:h.
+	^ self.
+    ].
+    gc displayRectangleX:x y:y width:w height:h
+!
+
+displayString:aString from:index1 to:index2 x:x y:y
+    "draw part of a string with fg at x/y in current font"
+
+    gc displayString:aString from:index1 to:index2 x:x y:y opaque:false maxWidth:self width
+!
+
+displayString:aString from:index1 to:index2 x:x y:y opaque:opaque
+    "draw part of a string with both fg and bg at x/y in current font"
+
+    self displayString:aString from:index1 to:index2 x:x y:y opaque:opaque maxWidth:self width.
+!
+
+displayString:aString from:index1 to:index2 x:x y:y opaque:opaque maxWidth:maxWidth
+    "draw part of a string with both fg and bg at x/y in current font"
+
+    gc == self ifTrue:[
+        super displayString:aString from:index1 to:index2 x:x y:y opaque:opaque maxWidth:maxWidth.
+        ^ self.
+    ].
+    gc displayString:aString from:index1 to:index2 x:x y:y opaque:opaque maxWidth:maxWidth
+! !
+
+!GraphicsMedium methodsFor:'basic filling'!
+
+fillArcX:x y:y width:w height:h from:start angle:angle
+    "fill an arc with current paint color"
+
+    gc == self ifTrue:[
+	super fillArcX:x y:y width:w height:h from:start angle:angle.
+	^ self.
+    ].
+    gc fillArcX:x y:y width:w height:h from:start angle:angle
+!
+
+fillPolygon:points
+    "fill a polygon with current paint color"
+
+    gc == self ifTrue:[
+	super fillPolygon:points.
+	^ self.
+    ].
+    gc fillPolygon:points
+!
+
+fillRectangleX:x y:y width:w height:h
+    "fill a rectangle with current paint color"
+
+    gc == self ifTrue:[
+	super fillRectangleX:x y:y width:w height:h.
+	^ self.
+    ].
+    gc fillRectangleX:x y:y width:w height:h
+!
+
+fillRectangleX:x y:y width:w height:h color:aColor
+    "fill a rectangle with given color"
+
+    gc == self ifTrue:[
+	super fillRectangleX:x y:y width:w height:h color:aColor.
+	^ self.
+    ].
+    gc fillRectangleX:x y:y width:w height:h color:aColor
+! !
+
+!GraphicsMedium methodsFor:'bit blitting'!
+
+copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth padding:pad width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY
+    "copy bits from a smalltalk byteArray.
+     The bits found there are supposed to be in the devices native format (i.e.
+     translated to allocated color indices on pseudoColor devices and padded as required.
+     The byteOrder is MSB and will be converted as appropriate by the underlying devices
+     method to whatever the device needs."
+
+    gc == self ifTrue:[
+	super copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth padding:pad width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY.
+	^ self.
+    ].
+    gc copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth padding:pad width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY
+!
+
+copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY
+    "copy bits from a smalltalk byteArray.
+     The bits found there are supposed to be in the devices native format (i.e.
+     translated to allocated color indices on pseudoColor devices and padded as required.
+     The byteOrder is MSB and will be converted as appropriate by the underlying devices
+     method to whatever the device needs.
+     Assumes the source bits are in ST/X's natural padding (i.e. 8-bit padded)"
+
+    gc == self ifTrue:[
+	super copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY.
+	^ self.
+    ].
+    gc copyBitsFrom:aByteArray bitsPerPixel:bpp depth:depth width:srcW height:srcH x:srcX y:srcY toX:dstX y:dstY
+!
+
+copyFrom:aGC toX:dstX y:dstY
+    "copy from a drawable - maybe self"
+
+    gc == self ifTrue:[
+	super copyFrom:aGC toX:dstX y:dstY.
+	^ self.
+    ].
+    gc copyFrom:aGC toX:dstX y:dstY
+!
+
+copyFrom:aGC x:srcX y:srcY toX:dstX y:dstY width:w height:h
+    "copy from a drawable - maybe self"
+
+    gc == self ifTrue:[
+	super copyFrom:aGC x:srcX y:srcY toX:dstX y:dstY width:w height:h.
+	^ self.
+    ].
+    gc copyFrom:aGC x:srcX y:srcY toX:dstX y:dstY width:w height:h
+!
+
+copyFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h async:async
+    "copy from aDrawable into the receiver;
+     the source may be the receiver as well - in this case its a scroll.
+     All coordinates are in device coordinates.
+     If the receiver is a view AND async is true, the call returns immediately
+     - otherwise, it returns when the scroll operation is finished.
+     (not all devices care for this).
+     If the receiver is a pixmap, the call always returns immediately."
+
+    |myDevice deviceDrawable asy|
+
+    myDevice := gc graphicsDevice.
+
+    ((aDrawable graphicsDevice ~~ myDevice)
+     or:[aDrawable isImage]) ifTrue:[
+        deviceDrawable := aDrawable asFormOn:myDevice.
+    ] ifFalse:[
+        deviceDrawable := aDrawable
+    ].
+    asy := async or:[self isView not].
+    asy ifFalse:[
+        self catchExpose
+    ].
+    gc == self ifTrue:[
+        super copyFrom:deviceDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h async:async.
+    ] ifFalse:[
+        gc copyFrom:deviceDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h async:async.
+    ].
+    asy ifFalse:[
+        myDevice flush.
+        self waitForExpose
+    ]
+!
+
+copyFrom:aGC x:dstX y:dstY width:w height:h
+    "copy from a drawable - maybe self"
+
+    gc == self ifTrue:[
+	super copyFrom:aGC x:dstX y:dstY width:w height:h.
+	^ self.
+    ].
+    gc copyFrom:aGC x:dstX y:dstY width:w height:h
+!
+
+copyPlaneFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h
+    "copy one plane from aDrawable into the receiver. 0's are drawn in
+     background, while 1's are drawn with foreground color.
+     The depth of aDrawable must (should) be 1.
+     The drawable must have been allocated on the same device.
+     All coordinates are in device coordinates."
+
+    gc == self ifTrue:[
+	super copyPlaneFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h.
+	^ self.
+    ].
+    gc copyPlaneFrom:aDrawable x:srcX y:srcY toX:dstX y:dstY width:w height:h
+! !
+
 !GraphicsMedium methodsFor:'copying'!
 
 postCopy
@@ -326,12 +1720,1037 @@
     realized := false.
 ! !
 
+!GraphicsMedium methodsFor:'drawing'!
+
+display:someObject at:aPoint
+    "draw someObject - this must understand the #displayOn:at: message"
+
+    someObject displayOn:self at:aPoint
+
+    "Created: 28.5.1996 / 14:22:57 / cg"
+!
+
+displayArcIn:aRectangle from:startAngle angle:angle
+    "draw an arc in a box"
+
+    self
+	displayArcX:(aRectangle left)
+		  y:(aRectangle top)
+	      width:(aRectangle width)
+	     height:(aRectangle height)
+	       from:startAngle
+	      angle:angle
+!
+
+displayArcOrigin:origin corner:corner from:startAngle angle:angle
+    "draw an arc in a box"
+
+    |left top right bot|
+
+    left := origin x.
+    top := origin y.
+    right := corner x.
+    bot := corner y.
+    self
+	displayArcX:left
+		  y:top
+	      width:(right - left + 1)
+	     height:(bot - top + 1)
+	       from:startAngle
+	      angle:angle
+
+    "Modified: 8.5.1996 / 08:35:25 / cg"
+!
+
+displayArcX:x y:y w:w h:h from:startAngle angle:angle
+    "draw an arc; apply transformation if nonNil"
+
+    <resource:#obsolete>
+
+    self obsoleteMethodWarning:'use #displayArcX:y:width:height:from:angle:'.
+    self displayArcX:x y:y width:w height:h from:startAngle angle:angle
+
+    "Modified: 8.5.1996 / 08:46:56 / cg"
+!
+
+displayCircle:aPoint radius:r
+    "draw a circle around a center point"
+
+    gc == self ifTrue:[
+	super displayCircleX:(aPoint x) y:(aPoint y) radius:r.
+	^ self.
+    ].
+    gc displayCircleX:(aPoint x) y:(aPoint y) radius:r
+!
+
+displayCircleIn:aRectangle
+    "draw a circle in a box"
+
+    self
+	displayArcX:(aRectangle left)
+		  y:(aRectangle top)
+	      width:(aRectangle width)
+	     height:(aRectangle height)
+	       from:0
+	      angle:360
+
+    "Modified: 8.5.1996 / 08:35:40 / cg"
+!
+
+displayCircleX:x y:y radius:r
+    "draw a circle around a center point"
+
+    |d|
+    d := 2 * r.
+    self
+	displayArcX:(x - r)
+		  y:(y - r)
+	      width:d
+	     height:d
+	       from:0
+	      angle:360
+
+    "Modified: 8.5.1996 / 08:36:03 / cg"
+!
+
+displayForm:aFormOrImage
+    "draw a form (or image) at the origin"
+
+    gc == self ifTrue:[
+	super displayForm:aFormOrImage x:0 y:0.
+	^ self.
+    ].
+    gc displayForm:aFormOrImage x:0 y:0
+
+    "Modified: / 24.4.1997 / 16:00:11 / cg"
+    "Created: / 9.11.1997 / 00:50:52 / cg"
+!
+
+displayForm:aFormOrImage at:aPoint
+    "draw a form (or image)"
+
+    gc == self ifTrue:[
+	super displayForm:aFormOrImage x:(aPoint x) y:(aPoint y).
+	^ self.
+    ].
+    gc displayForm:aFormOrImage x:(aPoint x) y:(aPoint y)
+
+    "Modified: 24.4.1997 / 16:00:11 / cg"
+!
+
+displayForm:formToDraw x:x y:y
+    "draw a form or image non opaque;
+     if its a 1-plane bitmap, 1-bits are drawn in the
+     current paint-color, leaving pixels with 0-bits unchanged
+     (i.e. only 1-bits are drawn from the form).
+     If its a deep form (i.e. a pixmap) the current paint
+     settings are ignored and the form is drawn as-is.
+     Care must be taken, that the paint color is correctly allocated
+     (by sending #on: to the color) before doing so.
+     Using functions other than #copy only makes sense if you are
+     certain, that the colors are real colors (actually, only for
+     noColor or allColor)."
+
+    gc == self ifTrue:[
+	super displayForm:formToDraw x:x y:y.
+	^ self.
+    ].
+    gc displayForm:formToDraw x:x y:y
+!
+
+displayForm:aFormOrImage x:x y:y opaque:opaque
+    "draw a form (or image) at x/y;
+     if the form has depth 1, 1's in the form are
+     drawn in current paint color, 0's are ignored.
+     If the form has depth ~~ 1, the current fg color setting is ignored."
+
+    opaque ifTrue:[
+	self displayOpaqueForm:aFormOrImage x:x y:y
+    ] ifFalse:[
+	self displayForm:aFormOrImage x:x y:y
+    ].
+!
+
+displayImage:aFormOrImage
+    "draw an image (or form).
+     Provided for ST-80 compatibilty;
+     in ST/X, images are also handled by #displayForm:"
+
+    gc == self ifTrue:[
+	super displayForm:aFormOrImage x:0 y:0.
+	^ self.
+    ].
+    gc displayForm:aFormOrImage x:0 y:0
+!
+
+displayImage:aFormOrImage at:aPoint
+    "draw an image (or form).
+     Provided for ST-80 compatibilty;
+     in ST/X, images are also handled by #displayForm:"
+
+    gc == self ifTrue:[
+	super displayForm:aFormOrImage x:(aPoint x) y:(aPoint y).
+	^ self.
+    ].
+    gc displayForm:aFormOrImage x:(aPoint x) y:(aPoint y)
+
+    "Modified: 24.4.1997 / 16:02:43 / cg"
+!
+
+displayImage:aFormOrImage x:x y:y
+    "draw an image (or form).
+     Provided for ST-80 compatibilty;
+     in ST/X, images are also handled by #displayForm:"
+
+    gc == self ifTrue:[
+	super displayForm:aFormOrImage x:x y:y.
+	^ self.
+    ].
+    gc displayForm:aFormOrImage x:x y:y
+
+    "Created: 24.4.1997 / 16:03:03 / cg"
+!
+
+displayLineFrom:point1 to:point2
+    "draw a line"
+
+    gc == self ifTrue:[
+	super displayLineFromX:(point1 x) y:(point1 y)
+		      toX:(point2 x) y:(point2 y).
+	^ self.
+    ].
+    gc displayLineFromX:(point1 x) y:(point1 y)
+		      toX:(point2 x) y:(point2 y)
+!
+
+displayLineFromX:xStart y:yStart toX:xEnd y:yEnd brush:aForm
+    "draw a line using a brush.
+     Here, a slow fallback is used, drawing into a
+     temporary bitmap first, which is then displayed"
+
+    |deltaX deltaY dx dy px py destX destY p tempForm
+     xMin xMax yMin yMax x1 x2 y1 y2|
+
+    xStart < xEnd ifTrue:[
+        xMin := xStart.
+        xMax := xEnd.
+    ] ifFalse:[
+        xMin := xEnd.
+        xMax := xStart
+    ].
+    yStart < yEnd ifTrue:[
+        yMin := yStart.
+        yMax := yEnd.
+    ] ifFalse:[
+        yMin := yEnd.
+        yMax := yStart
+    ].
+
+    tempForm := Form width:(xMax-xMin+1+aForm width)
+                     height:(yMax-yMin+1+aForm height)
+                     depth:aForm depth
+                     onDevice:self graphicsDevice.
+    tempForm clear.
+    tempForm paint:(Color colorId:1) on:(Color colorId:0).
+    tempForm function:#or.
+
+    ((yStart = yEnd and:[xStart < xEnd])
+    or: [yStart < yEnd]) ifTrue:[
+        x1 := xStart. y1 := yStart.
+        x2 := xEnd. y2 := yEnd.
+    ] ifFalse:[
+        x1 := xEnd. y1 := yEnd.
+        x2 := xStart. y2 := yStart.
+    ].
+
+    x1 := x1 - xMin.  x2 := x2 - xMin.
+    y1 := y1 - yMin.  y2 := y2 - yMin.
+
+    destX := x1.
+    destY := y1.
+
+    "/ bresenham ...
+
+    deltaX := x2 - x1.
+    deltaY := y2 - y1.
+
+    dx := deltaX sign.
+    dy := deltaY sign.
+    px := deltaY abs.
+    py := deltaX abs.
+
+    tempForm displayForm:aForm x:destX y:destY.
+
+    py > px ifTrue:[
+        "horizontal"
+        p := py // 2.
+        py timesRepeat:[
+            destX := destX + dx.
+            (p := p - px) < 0 ifTrue:[
+                destY := destY + dy.
+                p := p + py
+            ].
+            tempForm displayForm:aForm x:destX y:destY.
+        ]
+    ] ifFalse:[
+        "vertical"
+        p := px // 2.
+        px timesRepeat:[
+            destY := destY + dy.
+            (p := p - py) < 0 ifTrue:[
+                destX := destX + dx.
+                p := p + px
+            ].
+            tempForm displayForm:aForm x:destX y:destY
+        ]
+    ].
+    self displayForm:tempForm
+                   x:xMin-aForm offset x
+                   y:yMin-aForm offset y.
+    tempForm close
+
+    "Modified: 1.4.1997 / 21:29:06 / cg"
+!
+
+displayOpaqueString:aString at:aPoint
+    "draw a string with both fg and bg"
+
+    gc == self ifTrue:[
+	super displayOpaqueString:aString x:(aPoint x) y:(aPoint y).
+	^ self.
+    ].
+    gc displayOpaqueString:aString x:(aPoint x) y:(aPoint y)
+!
+
+displayOpaqueString:aString from:start to:stop at:aPoint
+    "draw part of a string - drawing both fg and bg"
+
+    gc displayString:aString from:start to:stop x:aPoint x y:aPoint x opaque:true maxWidth:self width.
+!
+
+displayOpaqueString:aString x:x y:y
+    "draw a string at the coordinate x/y - draw foreground pixels in paint-color,
+     background pixels in bgPaint color. If the transformation involves scaling,
+     the fonts point-size is scaled as appropriate.
+     Assuming that device can only draw in device colors, we have to handle
+     the case where paint and/or bgPaint are dithered colors or images."
+
+    gc == self ifTrue:[
+	super displayOpaqueString:aString x:x y:y.
+	^ self.
+    ].
+    gc displayOpaqueString:aString x:x y:y
+!
+
+displayOpaqueString:aString x:x y:y angle:drawAngle
+    "draw a string along a (possibly non-horizontal) line,
+     drawing both fg and bg pixels.
+     The angle is in degrees, clock-wise, starting with 0 for
+     a horizontal draw.
+     Drawing is done by first drawing the string into a temporary bitmap,
+     which is rotated and finally drawn as usual.
+     NOTICE: due to the rotation of the temporary bitmap, this is a slow
+	     operation - not to be used with cillions of strings ..."
+
+    gc == self ifTrue:[
+	super displayString:aString x:x y:y angle:drawAngle opaque:true.
+	^ self.
+    ].
+    gc displayString:aString x:x y:y angle:drawAngle opaque:true
+
+    "
+     |v|
+
+     v := View new.
+     v extent:300@200.
+     v openAndWait.
+     0 to:360 by:45 do:[:a |
+	 v paint:Color black on:Color red.
+	 v displayOpaqueString:'hello world' x:100 y:100 angle:a.
+     ].
+    "
+
+    "in contrast to non-opaque draw:
+     |v|
+
+     v := View new.
+     v extent:300@200.
+     v openAndWait.
+     0 to:360 by:45 do:[:a |
+	 v paint:Color black on:Color red.
+	 v displayString:'hello world' x:100 y:100 angle:a.
+     ].
+    "
+
+    "Modified: 23.4.1997 / 17:50:23 / cg"
+!
+
+displayPoint:aPoint
+    "draw a pixel"
+
+    gc == self ifTrue:[
+	super displayPointX:(aPoint x) y:(aPoint y).
+	^ self.
+    ].
+    gc displayPointX:(aPoint x) y:(aPoint y)
+!
+
+displayPointX:x y:y
+    "draw a point (with current paint-color); apply transformation if nonNil"
+
+    gc == self ifTrue:[
+	super displayPointX:x y:y.
+	^ self.
+    ].
+    gc displayPointX:x y:y
+!
+
+displayRectangle:aRectangle
+    "draw a rectangle"
+
+    self displayRectangleX:(aRectangle left)
+			 y:(aRectangle top)
+		     width:(aRectangle width)
+		    height:(aRectangle height)
+!
+
+displayRectangleOrigin:origin corner:corner
+    "draw a rectangle"
+
+    |top left|
+
+    left := origin x.
+    top := origin y.
+    self displayRectangleX:left y:top
+		     width:(corner x - left)
+		    height:(corner y - top)
+!
+
+displayRectangleOrigin:origin extent:extent
+    "draw a rectangle"
+
+    self displayRectangleX:(origin x) y:(origin y)
+		     width:(extent x)
+		    height:(extent y)
+!
+
+displayRoundRectangleX:left y:top width:width height:height wCorner:wCorn hCorner:hCorn
+    |right bottom wC hC wHalf hHalf isWin32|
+
+    "/ BIG KLUDGE WARNING HERE: the code below looks "good" on windows displays;
+    "/ (if you change anything under Unix, make it X-platform specific.
+    "/ (there seem to be drawing incompatibilities between Win- and XWorkstation)
+
+    isWin32 := self device platformName = 'WIN32'.
+
+    right := left + width-1.
+    bottom := top + height-1.
+
+    wC := wCorn.
+    hC := hCorn.
+
+    self scale = 1 ifTrue:[
+	wHalf := wC // 2.
+	hHalf := hC // 2.
+    ] ifFalse:[
+	wHalf := wC / 2.
+	hHalf := hC / 2.
+    ].
+
+    "top left arc"
+    self displayArcX:left y:top width:wC height:hC from:90 angle:90.
+
+    "top right arc"
+    self displayArcX:(right - wC) y:top width:wC height:hC from:0 angle:90.
+
+    "bottom right arc"
+    (isWin32 and:[self scale = 1]) ifTrue:[
+	self displayArcX:(right - wC+1) y:(bottom - hC+1) width:wC height:hC from:270 angle:90.
+    ] ifFalse:[
+	self displayArcX:(right - wC) y:(bottom - hC) width:wC height:hC from:270 angle:90.
+    ].
+
+    "bottom left arc"
+    self displayArcX:left y:(bottom - hC) width:wC height:hC from:180 angle:90.
+
+    "top line"
+    self displayLineFromX:(left + wHalf) y:top toX:(right - wHalf-1) y:top.
+
+    "left line"
+    self displayLineFromX:left y:(top + hHalf - 1) toX:left y:(bottom - hHalf - 2).
+
+    "bottom line"
+    self displayLineFromX:(left + wHalf-1) y:bottom
+		      toX:(right - wHalf ) y:bottom.
+
+    "right line"
+    self displayLineFromX:right y:(top + hHalf) toX:right y:(bottom - hHalf).
+
+
+    "
+     |v|
+
+     (v := View new) extent:200@200; openAndWait.
+     v displayRoundRectangleX:10 y:10 width:100 height:100 wCorner:20 hCorner:20
+    "
+!
+
+displayString:aString at:aPoint
+    "draw a string - drawing fg only"
+
+    self displayString:aString x:aPoint x y:aPoint y
+!
+
+displayString:aString centeredAtX:x y:y
+    "draw a string - drawing fg only"
+
+    |w h|
+
+    w := aString widthOn:self.
+    h := aString heightOn:self.
+    self displayString:aString x:x-(w/2) y:y-(h/2)
+!
+
+displayString:aString from:start to:stop at:aPoint
+    "draw part of a string - drawing fg only"
+
+    ^ self displayString:aString from:start to:stop x:aPoint x y:aPoint y
+!
+
+displayString:aString x:x y:y
+    "draw a string at the coordinate x/y -
+     draw foreground-pixels only (in current paint-color),
+     leaving background as-is. If the transformation involves scaling,
+     the fonts point-size is scaled as appropriate."
+
+    self displayString:aString from:1 to:aString size x:x y:y opaque:false maxWidth:self width.
+!
+
+displayString:aString x:x y:y angle:drawAngle
+    "draw a string along a (possibly non-horizontal) line - drawing fg only.
+     The angle is in degrees, clock-wise, starting with 0 for
+     a horizontal draw.
+     Drawing is done by first drawing the string into a temporary bitmap,
+     which is rotated and finally drawn as usual.
+     NOTICE: due to the rotation of the temporary bitmap, this is a slow
+	     operation - not to be used with cillions of strings ..."
+
+    self
+	displayString:aString x:x y:y angle:drawAngle opaque:false
+
+    "
+     |v|
+
+     v := View new.
+     v extent:300@200.
+     v openAndWait.
+     0 to:360 by:90 do:[:a |
+	 v paint:Color black.
+	 v displayString:'hello world' x:100 y:100 angle:a.
+     ].
+    "
+    "
+     |v|
+
+     v := View new.
+     v extent:400@400.
+     v openAndWait.
+     0 to:360 by:5 do:[:a |
+	 v paint:Color black.
+	 v displayString:'.........hello' x:200 y:200 angle:a.
+     ].
+    "
+    "
+     |v|
+
+     v := View new.
+     v extent:200@100.
+     v openAndWait.
+     v displayString:' hello' x:90 y:50 angle:0.
+     v displayString:' hello' x:90 y:50 angle:45.
+     v displayString:' hello' x:90 y:50 angle:90.
+     v displayString:' hello' x:90 y:50 angle:180.
+     v displayString:' hello' x:90 y:50 angle:270.
+    "
+    "
+     |v|
+
+     v := View new.
+     v extent:200@100.
+     v openAndWait.
+     v displayString:'hello' x:50 y:50 angle:0.
+     v displayString:'hello' x:50 y:50 angle:45.
+     v displayString:'hello' x:50 y:50 angle:90.
+     v displayString:'hello' x:50 y:50 angle:135.
+     v displayString:'hello' x:50 y:50 angle:180.
+     v displayString:'hello' x:50 y:50 angle:225.
+     v displayString:'hello' x:50 y:50 angle:270.
+     v displayString:'hello' x:50 y:50 angle:315.
+    "
+
+    "Modified: 24.4.1997 / 12:51:25 / cg"
+!
+
+displayString:aString x:x y:y angle:drawAngle opaque:opaque
+    "common code to draw a string along a (possibly non-horizontal) line.
+     The angle is in degrees, clock-wise, starting with 0 for
+     a horizontal draw.
+     Drawing is done by first drawing the string into a temporary bitmap,
+     which is rotated and finally drawn as usual.
+     NOTICE: due to the rotation of the temporary bitmap, this is a slow
+	     operation - not to be used with cillions of strings ...
+     CAVEAT: if the string is not a real string (i.e. a LabelAndIcon),
+	     this can (currently) only be done opaque"
+
+    gc == self ifTrue:[
+	super displayString:aString x:x y:y angle:drawAngle opaque:opaque.
+	^ self.
+    ].
+    gc displayString:aString x:x y:y angle:drawAngle opaque:opaque
+!
+
+displayUnscaledForm:formToDraw x:x y:y
+    "draw a form or image non opaque and unscaled;
+     if its a 1-plane bitmap, 1-bits are drawn in the
+     current paint-color, leaving pixels with 0-bits unchanged
+     (i.e. only 1-bits are drawn from the form).
+     If its a deep form (i.e. a pixmap) the current paint
+     settings are ignored and the form is drawn as-is.
+     Care must be taken, that the paint color is correctly allocated
+     (by sending #on: to the color) before doing so.
+     Using functions other than #copy only makes sense if you are
+     certain, that the colors are real colors (actually, only for
+     noColor or allColor).
+     The origins coordinate is transformed, but the image itself is unscaled."
+
+    gc == self ifTrue:[
+	super displayUnscaledForm:formToDraw x:x y:y.
+	^ self.
+    ].
+    gc displayUnscaledForm:formToDraw x:x y:y
+!
+
+displayUnscaledOpaqueForm:formToDraw x:x y:y
+    "draw a form or image opaque and unscaled;
+     if its a 1-plane bitmap, 1-bits are drawn in the
+     current paint-color, 0 bits in background color.
+     If its a deep form (i.e. a pixmap) the current paint
+     settings are ignored and the form is drawn as-is (opaque).
+     The origins coordinate is transformed, but the image itself is unscaled."
+
+    gc == self ifTrue:[
+	super displayUnscaledOpaqueForm:formToDraw x:x y:y.
+	^ self.
+    ].
+    gc displayUnscaledOpaqueForm:formToDraw x:x y:y
+!
+
+displayUnscaledOpaqueString:aString from:index1 to:index2 x:x y:y
+    "draw a substring at the transformed coordinate x/y but do not scale the font.
+     Draw foreground pixels in paint-color, background pixels in bgPaint color."
+
+    gc == self ifTrue:[
+	super displayUnscaledOpaqueString:aString from:index1 to:index2 x:x y:y.
+	^ self.
+    ].
+    gc displayUnscaledOpaqueString:aString from:index1 to:index2 x:x y:y
+!
+
+displayUnscaledOpaqueString:aString x:x y:y
+    "draw a string at the transformed coordinate x/y but do not scale the font.
+     Draw foreground pixels in paint-color, background pixels in bgPaint color."
+
+    gc == self ifTrue:[
+	super displayUnscaledOpaqueString:aString x:x y:y.
+	^ self.
+    ].
+    gc displayUnscaledOpaqueString:aString x:x y:y
+!
+
+displayUnscaledString:aString from:index1 to:index2 x:x y:y
+    "draw a substring at the transformed coordinate x/y but do not scale the font.
+     draw foreground-pixels only (in current paint-color), leaving background as-is."
+
+    gc == self ifTrue:[
+	super displayUnscaledString:aString from:index1 to:index2 x:x y:y.
+	^ self.
+    ].
+    gc displayUnscaledString:aString from:index1 to:index2 x:x y:y
+!
+
+displayUnscaledString:aString x:x y:y
+    "draw a string at the transformed coordinate x/y but do not scale the font.
+     draw foreground-pixels only (in current paint-color), leaving background as-is."
+
+    gc == self ifTrue:[
+	super displayUnscaledString:aString x:x y:y.
+	^ self.
+    ].
+    gc displayUnscaledString:aString x:x y:y
+! !
+
+!GraphicsMedium methodsFor:'drawing in device coordinates'!
+
+displayDeviceForm:aForm x:x y:y
+    "draw a form or image non opaque (i.e. only foreground color is drawn);
+     If its a 1-plane bitmap, 1-bits are drawn in the
+     current paint-color, leaving pixels with 0-bits unchanged
+     (i.e. only 1-bits are drawn from the form).
+     If its a deep form (i.e. a pixmap) the current paint
+     settings are ignored and the form is drawn as-is;
+     however, the mask is applied if present.
+
+     The form should must have been allocated on the same device,
+     otherwise its converted here, which slows down the draw.
+     No transformation or scaling is done.
+     Care must be taken, that the paint color is correctly allocated
+     (by sending #on: to the color) before doing so.
+     Using functions other than #copy only makes sense if you are
+     certain, that the colors are real colors (actually, only for
+     noColor or allColor)."
+
+    gc == self ifTrue:[
+	super displayDeviceForm:aForm x:x y:y.
+	^ self.
+    ].
+    gc displayDeviceForm:aForm x:x y:y
+!
+
+displayDeviceLineFromX:x1 y:y1 toX:x2 y:y2
+    "draw a line in device coordinates"
+
+    gc == self ifTrue:[
+	super displayDeviceLineFromX:x1 y:y1 toX:x2 y:y2.
+	^ self.
+    ].
+    gc displayDeviceLineFromX:x1 y:y1 toX:x2 y:y2
+!
+
+displayDeviceOpaqueForm:aForm x:x y:y
+    "draw a form or image opaque (i.e. both fg and bg is drawn);
+     If its a 1-plane bitmap, 1-bits are drawn in the
+     current paint-color and 0-bits in the bgPaint color.
+     If its a deep form (i.e. a pixmap) the current paint/bgPaint
+     settings are ignored and the form drawn as-is.
+     Any mask is ignored.
+     In the 1-plane case, special care must be taken if paint and/or bgPaint
+     dithered colors or patterns, since are that the colors are correctly allocated (by sending #on:
+     to the colors) before doing so.
+     The form should have been allocated on the same device; otherwise,
+     its converted here, which slows down the draw.
+     Drawing is in device coordinates; no scaling is done."
+
+    gc == self ifTrue:[
+	super displayDeviceOpaqueForm:aForm x:x y:y.
+	^ self.
+    ].
+    gc displayDeviceOpaqueForm:aForm x:x y:y
+!
+
+displayDeviceOpaqueString:aString from:index1 to:index2 in:font x:x y:y
+    "draw a substring at the coordinate x/y - draw foreground pixels in
+     paint-color and background pixels in bgPaint-color.
+     Assuming that device can only draw in device colors, we have to handle
+     the case where paint and/or bgPaint are dithered colors.
+     No translation or scaling is done."
+
+    gc == self ifTrue:[
+	super displayDeviceOpaqueString:aString from:index1 to:index2 in:font x:x y:y.
+	^ self.
+    ].
+    gc displayDeviceOpaqueString:aString from:index1 to:index2 in:font x:x y:y
+!
+
+displayDeviceOpaqueString:aString from:index1 to:index2 x:x y:y
+    "draw a substring at the coordinate x/y - draw foreground pixels in
+     paint-color and background pixels in bgPaint-color.
+     Assuming that device can only draw in device colors, we have to handle
+     the case where paint and/or bgPaint are dithered colors.
+     No translation or scaling is done."
+
+    self displayDeviceOpaqueString:aString from:index1 to:index2 in:self font x:x y:y
+!
+
+displayDeviceOpaqueString:aString x:x y:y
+    "draw a string at the coordinate x/y - draw foreground pixels in
+     paint-color and background pixels in bgPaint-color.
+     No translation or scaling is done"
+
+    self displayDeviceOpaqueString:aString from:1 to:(aString size) in:self font x:x y:y
+!
+
+displayDeviceRectangleX:x y:y width:w height:h
+    "draw a rectangle in device coordinates"
+
+    gc == self ifTrue:[
+	super displayDeviceRectangleX:x y:y width:w height:h.
+	^ self.
+    ].
+    gc displayDeviceRectangleX:x y:y width:w height:h
+!
+
+displayDeviceString:aString from:index1 to:index2 in:font x:x y:y
+    "draw a substring at the coordinate x/y -
+     draw foreground-pixels only (in current paint-color), leaving background as-is.
+     No translation or scaling is done"
+
+    gc == self ifTrue:[
+        super displayDeviceString:aString from:index1 to:index2 in:font x:x y:y.
+        ^ self.
+    ].
+    gc displayDeviceString:aString from:index1 to:index2 in:font x:x y:y
+!
+
+displayDeviceString:aString from:index1 to:index2 x:x y:y
+    "draw a substring at the coordinate x/y -
+     draw foreground-pixels only (in current paint-color), leaving background as-is.
+     No translation or scaling is done"
+
+    self displayDeviceString:aString from:index1 to:index2 in:self font x:x y:y
+!
+
+displayDeviceString:aString x:x y:y
+    "draw a string at the coordinate x/y -
+     draw foreground-pixels only (in current paint-color), leaving background as-is.
+     No translation or scaling is done"
+
+    self displayDeviceString:aString from:1 to:(aString size) in:self font x:x y:y
+!
+
+fillDeviceRectangleX:x y:y width:w height:h
+    "fill a rectangle with current paint color (device coordinates)"
+
+    gc == self ifTrue:[
+	super fillDeviceRectangleX:x y:y width:w height:h.
+	^ self.
+    ].
+    gc fillDeviceRectangleX:x y:y width:w height:h
+! !
+
+!GraphicsMedium methodsFor:'edge drawing'!
+
+drawEdgesForX:x y:y width:w height:h level:l
+    "draw 3D edges into a rectangle"
+    self
+        drawEdgesForX:x y:y width:w height:h level:l
+        shadow:self blackColor light:self whiteColor
+        halfShadow:nil halfLight:nil
+        style:nil
+!
+
+drawEdgesForX:x y:y width:w height:h level:l
+                shadow:shadowColor light:lightColor
+                halfShadow:halfShadowColor halfLight:halfLightColor
+                style:edgeStyle
+
+    "draw 3D edges into a rectangle"
+
+    |topLeftFg botRightFg topLeftHalfFg botRightHalfFg
+     count "{ Class: SmallInteger }"
+     r
+     b
+     xi    "{ Class: SmallInteger }"
+     yi    "{ Class: SmallInteger }"
+     run paint|
+
+    count := l.
+    (count < 0) ifTrue:[
+        topLeftFg := shadowColor.
+        botRightFg := lightColor.
+        topLeftHalfFg := halfShadowColor.
+        botRightHalfFg := halfLightColor.
+        count := count negated
+    ] ifFalse:[
+        topLeftFg := lightColor.
+        botRightFg := shadowColor.
+        topLeftHalfFg := halfLightColor.
+        botRightHalfFg := halfShadowColor.
+    ].
+    topLeftHalfFg isNil ifTrue:[
+        topLeftHalfFg := topLeftFg
+    ].
+    botRightHalfFg isNil ifTrue:[
+        botRightHalfFg := botRightFg
+    ].
+
+    r := x + w - 1. "right"
+    b := y + h - 1. "bottom"
+
+    self lineWidth:0.
+
+    "top and left edges"
+    ((edgeStyle == #soft or:[edgeStyle == #softWin95]) and:["l" count > 0]) ifTrue:[
+        paint := topLeftHalfFg
+    ] ifFalse:[
+        paint := topLeftFg
+    ].
+    self paint:paint.
+
+    0 to:(count - 1) do:[:i |
+        run := y + i.
+        run < b ifTrue:[
+            self displayDeviceLineFromX:x y:run toX:r y:run. "top"
+        ].
+        run := x + i.
+        self displayDeviceLineFromX:run y:y toX:run y:b  "left"
+    ].
+    (edgeStyle == #soft or:[edgeStyle == #softWin95]) ifTrue:[
+"
+        self paint:topLeftFg.
+        self displayDeviceLineFromX:x y:y toX:r y:y.
+        self displayDeviceLineFromX:x y:y toX:x y:b
+"
+        (l > 1) ifTrue:[
+            edgeStyle == #softWin95 ifTrue:[
+                self paint:(Color veryLightGrey).
+            ] ifFalse:[
+                (l > 2 and:[edgeStyle == #soft]) ifTrue:[
+                    self paint:(self device blackColor).
+                ] ifFalse:[
+                    self paint:halfLightColor.
+                ]
+            ].
+            self displayDeviceLineFromX:x y:y toX:r y:y.
+            self displayDeviceLineFromX:x y:y toX:x y:b.
+        ]
+    ].
+
+    xi := x + 1.
+    yi := y + 1.
+
+"/ does not look good
+"/ style == #st80 iftrue:[
+"/  yi := yi + 1
+"/ ].
+
+    "bottom and right edges"
+    ((edgeStyle == #soft or:[edgeStyle == #softWin95])
+    "new:" and:[count > 1]) ifTrue:[
+        paint := botRightHalfFg
+    ] ifFalse:[
+        paint := botRightFg
+    ].
+
+    self paint:paint.
+    0 to:(count - 1) do:[:i |
+        run := b - i.
+        run > y ifTrue:[
+            self displayDeviceLineFromX:xi-1 y:run toX:r y:run. "bottom"
+        ].
+        run := r - i.
+        self displayDeviceLineFromX:run y:yi-1 toX:run y:b.  "right"
+        xi := xi + 1.
+        yi := yi + 1
+    ].
+    ((edgeStyle == #soft or:[edgeStyle == #softWin95])
+    and:[l > 1]) ifTrue:[
+        self paint:(self device blackColor) "shadowColor".
+        self displayDeviceLineFromX:x y:b toX:r y:b.
+        self displayDeviceLineFromX:r y:y toX:r y:b
+    ].
+
+    self edgeDrawn:#all
+
+    "Modified: / 24.8.1998 / 18:23:02 / cg"
+!
+
+edgeDrawn:whichOne
+    "a redefinable hook for views which like to draw
+     over their edges (some checkToggles do).
+     Nothing done here."
+
+    "Created: 7.3.1997 / 17:59:07 / cg"
+! !
+
+!GraphicsMedium methodsFor:'evaluating in another context'!
+
+reverseDo:aBlock
+    "evaluate aBlock with foreground and background interchanged.
+     This can be reimplemented here in a faster way."
+
+    gc == self ifTrue:[
+	super reverseDo:aBlock.
+	^ self.
+    ].
+    gc reverseDo:aBlock
+!
+
+withBackground:fgColor do:aBlock
+    "evaluate aBlock with changed background."
+
+    gc == self ifTrue:[
+	super withBackground:fgColor do:aBlock.
+	^ self.
+    ].
+    gc withBackground:fgColor do:aBlock
+!
+
+withForeground:fgColor background:bgColor do:aBlock
+    "evaluate aBlock with changed foreground and background."
+
+    gc == self ifTrue:[
+	super withForeground:fgColor background:bgColor do:aBlock.
+	^ self.
+    ].
+    gc withForeground:fgColor background:bgColor do:aBlock
+!
+
+withForeground:fgColor background:bgColor function:aFunction do:aBlock
+    "evaluate aBlock with foreground, background and function"
+
+    gc == self ifTrue:[
+	super withForeground:fgColor background:bgColor function:aFunction do:aBlock.
+	^ self.
+    ].
+    gc withForeground:fgColor background:bgColor function:aFunction do:aBlock
+!
+
+withForeground:fgColor background:bgColor mask:aMask do:aBlock
+    "evaluate aBlock with foreground, background and mask"
+
+    gc == self ifTrue:[
+	super withForeground:fgColor background:bgColor mask:aMask do:aBlock.
+	^ self.
+    ].
+    gc withForeground:fgColor background:bgColor mask:aMask do:aBlock
+!
+
+withForeground:fgColor do:aBlock
+    "evaluate aBlock with changed foreground."
+
+    gc == self ifTrue:[
+	super withForeground:fgColor do:aBlock.
+	^ self.
+    ].
+    gc withForeground:fgColor do:aBlock
+!
+
+withForeground:fgColor function:aFunction do:aBlock
+    "evaluate aBlock with changed foreground and function."
+
+    gc == self ifTrue:[
+	super withForeground:fgColor function:aFunction do:aBlock.
+	^ self.
+    ].
+    gc withForeground:fgColor function:aFunction do:aBlock
+!
+
+xoring:aBlock
+    "evaluate aBlock with function xoring"
+
+    gc == self ifTrue:[
+	super xoring:aBlock.
+	^ self.
+    ].
+    gc xoring:aBlock
+! !
+
 !GraphicsMedium methodsFor:'filling'!
 
 black
     "fill the receiver with black"
 
-    self fill:Black
+    self fill:self blackColor
 !
 
 clear
@@ -340,6 +2759,18 @@
     self clearView.
 !
 
+clearDeviceRectangleX:x y:y width:w height:h
+    "clear a rectangular area to viewBackground -
+     redefined since GraphicsMedium fills with background
+     - not viewBackground as we want here."
+
+    gc == self ifTrue:[
+	super clearDeviceRectangleX:x y:y width:w height:h.
+	^ self.
+    ].
+    gc clearDeviceRectangleX:x y:y width:w height:h.
+!
+
 clearInside
     "clear the receiver with background - ST-80 compatibility"
 
@@ -360,8 +2791,8 @@
 
     |oldPaint|
 
-    oldPaint := paint.
-    gc paint:bgPaint.
+    oldPaint := gc paint.
+    gc paint:gc backgroundPaint.
     gc fillRectangleX:left y:top width:w height:h.
     gc paint:oldPaint
 
@@ -372,7 +2803,7 @@
     "clear the receiver with background"
 
     "currently need this kludge for form ..."
-    transformation isNil ifTrue:[
+    gc transformation isNil ifTrue:[
 	self clearRectangleX:0 y:0 width:width height:height
     ] ifFalse:[
 	self clearDeviceRectangleX:0 y:0 width:width height:height
@@ -385,60 +2816,501 @@
 
     |oldPaint|
 
-    oldPaint := paint.
-    gc paint:something.
-    gc fillRectangleX:0 y:0 width:width height:height.
-    gc paint:oldPaint
+    oldPaint := self paint.
+    self paint:something.
+    self fillRectangleX:0 y:0 width:width height:height.
+    self paint:oldPaint
 
     "Modified: 28.5.1996 / 20:13:29 / cg"
 !
 
+fillArc:origin radius:r from:startAngle angle:angle
+    "draw a filled arc around a point"
+
+    |d|
+    d := 2 * r.
+    self
+	fillArcX:(origin x - r)
+	       y:(origin y - r)
+	   width:d
+	  height:d
+	    from:startAngle
+	   angle:angle
+
+    "Modified: 8.5.1996 / 08:41:54 / cg"
+!
+
+fillArcIn:aRectangle from:startAngle angle:angle
+    "draw a filled arc in a box"
+
+    self
+	fillArcX:(aRectangle left)
+	       y:(aRectangle top)
+	   width:(aRectangle width)
+	  height:(aRectangle height)
+	    from:startAngle
+	   angle:angle
+
+    "Created: 13.4.1996 / 20:56:03 / cg"
+    "Modified: 8.5.1996 / 08:42:13 / cg"
+!
+
+fillArcOrigin:origin corner:corner from:startAngle angle:angle
+    "draw a filled arc in a box"
+
+    |left top right bot|
+
+    left := origin x.
+    top := origin y.
+    right := corner x.
+    bot := corner y.
+    self
+	fillArcX:left
+	y:top
+	width:(right - left + 1)
+	height:(bot - top + 1)
+	from:startAngle
+	angle:angle
+
+    "Created: 13.4.1996 / 20:56:56 / cg"
+    "Modified: 8.5.1996 / 08:42:23 / cg"
+!
+
+fillArcX:x y:y w:w h:h from:startAngle angle:angle
+    "draw a filled arc; apply transformation if nonNil"
+
+    <resource:#obsolete>
+
+    self obsoleteMethodWarning:'use #fillArcX:y:width:height:from:angle:'.
+    self fillArcX:x y:y width:w height:h from:startAngle angle:angle
+
+    "Modified: 8.5.1996 / 08:47:52 / cg"
+!
+
+fillArcX:x y:y width:w height:h from:startAngle to:endAngle
+    "draw a filled arc in a box, given startAngle and endAngle."
+
+    self
+	fillArcX:x
+	       y:y
+	   width:w
+	  height:h
+	    from:startAngle
+	   angle:(endAngle - startAngle)
+
+    "Created: 8.5.1996 / 08:52:41 / cg"
+!
+
+fillCircle:aPoint radius:aNumber
+    "draw a filled circle around aPoint"
+
+    self fillCircleX:(aPoint x) y:(aPoint y) radius:aNumber
+!
+
+fillCircleIn:aRectangle
+    "draw a filled circle in a box"
+
+    self
+	fillArcX:(aRectangle left)
+	       y:(aRectangle top)
+	   width:(aRectangle width)
+	  height:(aRectangle height)
+	    from:0
+	   angle:360
+
+    "Created: 13.4.1996 / 20:57:41 / cg"
+    "Modified: 8.5.1996 / 08:42:38 / cg"
+!
+
+fillCircleX:x y:y radius:r
+    "draw a filled circle around x@y"
+
+    |d|
+
+    d := 2 * r.
+    self
+	fillArcX:(x - r)
+	y:(y - r)
+	width:d
+	height:d
+	from:0
+	angle:360
+
+    "Modified: 8.5.1996 / 08:43:02 / cg"
+!
+
+fillRectangle:aRectangle
+    "fill a rectangle with current paint color"
+
+    self fillRectangleX:(aRectangle left)
+		      y:(aRectangle top)
+		  width:(aRectangle width)
+		 height:(aRectangle height)
+!
+
+fillRectangleLeft:left top:top right:cornerX bottom:cornerY
+    "draw a filled rectangle.
+     Notice: the cornerPoint itself is NOT included"
+
+    self fillRectangleX:left y:top width:(cornerX - left) height:(cornerY - top)
+!
+
+fillRectangleOrigin:origin corner:corner
+    "draw a filled rectangle.
+     Notice: the cornerPoint itself is NOT included"
+
+    |top left|
+
+    left := origin x.
+    top := origin y.
+    self fillRectangleX:left y:top width:(corner x - left) height:(corner y - top)
+
+    "Created: 13.4.1996 / 20:58:16 / cg"
+!
+
+fillRectangleOrigin:origin extent:extent
+    "draw a filled rectangle.
+     Notice: the cornerPoint itself is NOT included"
+
+    self fillRectangleX:(origin x) y:(origin y) width:(extent x) height:(extent y)
+!
+
+fillRoundRectangleX:left y:top width:width height:height wCorner:wCorn hCorner:hCorn
+    |right bottom wC hC wHalf hHalf|
+
+    right := left + width.
+    bottom := top + height.
+
+    wC := wCorn.
+    hC := hCorn.
+
+    wHalf := wC / 2.
+    hHalf := hC / 2.
+
+    self device platformName = #WIN32 ifTrue:[
+        "/ bug workaround
+        "top left arc"
+        self fillArcX:left y:top width:wC height:hC from:90 angle:90.
+        "top right arc"
+        self fillArcX:(right - wC - 1) y:top width:wC height:hC from:0 angle:90.
+        "bottom right arc"
+        self fillArcX:(right - wC - 1) y:(bottom - hC - 1) width:wC height:hC from:270 angle:90.
+        "bottom left arc"
+        self fillArcX:left y:(bottom - hC) width:wC height:hC-1 from:180 angle:90.
+
+        "center rectangle"
+        self fillRectangleX:(left + wHalf) y:top width:(width - wHalf - wHalf+1) height:height-1.
+        "left partial rectangle"
+        self fillRectangleX:left y:top+hHalf width:wHalf height:(height-hHalf-hHalf).
+        "right partial rectangle"
+        self fillRectangleX:right-wHalf y:top+hHalf width:wHalf-1 height:(height-hHalf-hHalf).
+    ] ifFalse:[
+        "top left arc"
+        self fillArcX:left y:top width:wC height:hC from:90 angle:90.
+        "top right arc"
+        self fillArcX:(right - wC) y:top width:wC height:hC from:0 angle:90.
+        "bottom right arc"
+        self fillArcX:(right - wC - 1) y:(bottom - hC) width:wC height:hC from:270 angle:90.
+        "bottom left arc"
+        self fillArcX:left y:(bottom - hC) width:wC height:hC from:180 angle:90.
+
+        "center rectangle"
+        self fillRectangleX:(left + wHalf) y:top width:(width - wHalf - wHalf+1) height:height.
+        "left partial rectangle"
+        self fillRectangleX:left y:top+hHalf width:wHalf height:(height-hHalf-hHalf).
+        "right partial rectangle"
+        self fillRectangleX:right-wHalf y:top+hHalf width:wHalf height:(height-hHalf-hHalf).
+    ].
+
+
+    "
+     |v|
+
+     (v := View new) extent:200@200; openAndWait.
+     v fillRoundRectangleX:10 y:10 width:100 height:100 wCorner:20 hCorner:20
+    "
+!
+
 invertRectangle:aRectangle
     "invert a rectangle in the receiver"
 
-    gc xoring:[
-        gc fillRectangle:aRectangle
+    self xoring:[
+	self fillRectangle:aRectangle
     ]
 !
 
 white
     "fill the receiver with white"
 
-    gc fill:White
+    self fill:Color white
 ! !
 
-!GraphicsMedium methodsFor:'initialization'!
+!GraphicsMedium methodsFor:'initialization & release'!
+
+close
+    "same as destroy - for ST-80 compatibility"
+
+    self destroy
+
+    "Created: 2.4.1997 / 19:31:27 / cg"
+!
+
+destroy
+    "destroy a medium - here the fc is completely destroyed"
+
+    gc notNil ifTrue:[
+        gc destroy.
+    ].
+    realized := false.
+!
+
+initGC
+    "since we do not need a gc-object for the drawable until something is
+     really drawn, none is created.
+     This method is sent, when the first drawing happens"
+
+    gc == self ifTrue:[
+	super initGC.
+	^ self.
+    ].
+    gc initGC
+!
 
 initialize
-    "set up some useful default values"
-
     super initialize.
 
     width := 0.
     height := 0.
     realized := false.
-
-    "/ in the future, gc will be set to some object which really does
-    "/ all the graphics work, and the drawXXX drawing operation methods 
-    "/ will be changed to forward to it. Then, GraphicsMedium will no longer inherit
-    "/ from DeviceGraphicsContext.
-    "/ In the meantime (the intermediate migration phase), gc is set to alias self,
-    "/ so we are backward compatible.
-    "/ During the migration, all self drawXXX operations should be changed to gc drawXXX
-    gc := self.
+!
+
+initializeForDevice:aDevice
+    "allocate a GraphicsContext for a device"
+
+    aDevice notNil ifTrue:[
+        gc := aDevice newGraphicsContextFor:self.
+    ] ifFalse:[
+        "should not be reached"
+        GraphicsMedium superclass == DeviceGraphicsContext ifTrue:[
+            gc := self. 
+            super device:aDevice.
+        ].
+    ].
+
+    self initialize.
+!
+
+recreate
+    "reacreate a medium after snapIn"
+
+    gc notNil ifTrue:[
+        gc recreate.
+    ].
+!
+
+releaseGC
+    "destroy the associated device GC resource - can be done to be nice to the
+     display if you know that you are done with a drawable."
+
+    gc == self ifTrue:[
+        super releaseGC.
+        ^ self.
+    ].
+    gc notNil ifTrue:[
+        gc releaseGC.
+    ].
+! !
+
+!GraphicsMedium methodsFor:'misc'!
+
+clippedTo:aRectangle do:aBlock
+    |oldClip|
+
+    oldClip := gc deviceClippingBoundsOrNil.
+    gc clippingBounds:aRectangle.
+
+    aBlock
+        ensure:[
+            gc deviceClippingBounds:oldClip
+        ]
+!
+
+flush
+    "send all buffered drawing to the device."
+
+    gc == self ifTrue:[
+	super flush.
+	^ self.
+    ].
+    gc flush
+!
+
+setDevice:aDevice id:aDrawbleId gcId:aGCId
+    "private"
+
+    gc == self ifTrue:[
+        super setDevice:aDevice id:aDrawbleId gcId:aGCId.
+        ^ self.
+    ].
+    gc notNil ifTrue:[
+        gc setDevice:aDevice id:aDrawbleId gcId:aGCId
+    ].
+!
+
+setId:aDrawableId
+    "private"
+
+    gc == self ifTrue:[
+        super setId:aDrawableId.
+        ^ self.
+    ].
+    gc setId:aDrawableId
+!
+
+setPaint:fgColor on:bgColor
+    "set the paint and background-paint color. 
+     The bg-paint is used in opaque-draw operations.
+     Only set the variables, but do not send it to the device,
+     Used on initialization."
+
+    gc == self ifTrue:[
+        super setPaint:fgColor on:bgColor.
+        ^ self.
+    ].
+    gc setPaint:fgColor on:bgColor
 !
 
-setRealized:aBoolean
-    "low level special interface to manipulate the realized state.
-     Non-public interface, only to be used by experts.
-     (use to pretend a view has been realized - for example with alien views)"
-
-    realized := aBoolean
+sync
+    "send all buffered drawing to the device and wait until the device responds"
+
+    gc == self ifTrue:[
+        super sync.
+        ^ self.
+    ].
+    gc sync
+! !
+
+!GraphicsMedium methodsFor:'printing & storing'!
+
+storeOn:aStream
+    "blocked: ascii storeString not possible (recursive - view - subviews - container)"
+
+    self shouldNotImplement.
+    "if proceeded from exception..."
+    self printOn:aStream.
 ! !
 
-!GraphicsMedium class methodsFor:'documentation'!
-
-version
-    ^ '$Header: /cvs/stx/stx/libview/GraphicsMedium.st,v 1.22 2014-02-06 11:50:14 cg Exp $'
+!GraphicsMedium methodsFor:'queries'!
+
+fontAscent
+    "answer the ascent of the current font on the current device"
+
+    gc == self ifTrue:[
+	^ super fontAscent.
+    ].
+    ^ gc fontAscent
+!
+
+horizontalIntegerPixelPerMillimeter
+    "return the (rounded) number of pixels per millimeter"
+
+    ^ self horizontalPixelPerMillimeter asInteger
+!
+
+horizontalPixelPerInch
+    "return the number of horizontal pixels per inch of the display"
+
+    ^ self horizontalPixelPerMillimeter * 25.4
+!
+
+horizontalPixelPerMillimeter
+    "return the number of pixels per millimeter (not rounded)"
+
+    gc == self ifTrue:[
+	^ super horizontalPixelPerMillimeter.
+    ].
+    ^ gc horizontalPixelPerMillimeter
+!
+
+horizontalPixelPerMillimeter:millis
+    "return the number of pixels (not rounded) for millis millimeter"
+
+    ^ self horizontalPixelPerMillimeter * millis
+!
+
+resolution
+    "return a point consisting of pixel-per-inch horizontally and vertically."
+
+    gc == self ifTrue:[
+	^ super resolution.
+    ].
+    ^ gc resolution
+!
+
+verticalIntegerPixelPerMillimeter
+    "return the (rounded) number of pixels per millimeter"
+
+    ^ self verticalPixelPerMillimeter rounded
+!
+
+verticalPixelPerInch
+    "return the number of vertical pixels per inch of the display"
+
+    ^ self verticalPixelPerMillimeter * 25.4
+!
+
+verticalPixelPerMillimeter
+    "return the number of pixels per millimeter (not rounded)"
+
+    gc == self ifTrue:[
+	^ super verticalPixelPerMillimeter.
+    ].
+    ^ gc verticalPixelPerMillimeter
+!
+
+verticalPixelPerMillimeter:millis
+    "return the number of pixels (not rounded) for millis millimeter"
+
+    ^ self verticalPixelPerMillimeter * millis
 ! !
 
+!GraphicsMedium methodsFor:'view creation'!
+
+createBitmapFromArray:data width:width height:height
+    "create a bitmap from data and set the drawableId"
+
+    gc == self ifTrue:[
+        super createBitmapFromArray:data width:width height:height.
+        ^ self.
+    ].
+    gc createBitmapFromArray:data width:width height:height
+!
+
+createPixmapWidth:w height:h depth:d
+    "create a pixmap and set the drawableId"
+    
+    gc == self ifTrue:[
+        super createPixmapWidth:w height:h depth:d.
+        ^ self.
+    ].
+    gc createPixmapWidth:w height:h depth:d
+!
+
+createRootWindow
+    gc == self ifTrue:[
+        super createRootWindowFor:self.
+        ^ self.
+    ].
+    gc createRootWindowFor:self
+!
+
+createWindowFor:aView type:typeSymbol origin:org extent:ext minExtent:minE maxExtent:maxE borderWidth:bw subViewOf:sv style:styleSymbol inputOnly:inp label:label owner:owner icon:icn iconMask:icnM iconView:icnV 
+    "create a window and set the drawableId"
+    
+    gc == self ifTrue:[
+        super createWindowFor:aView type:typeSymbol origin:org extent:ext minExtent:minE maxExtent:maxE borderWidth:bw subViewOf:sv style:styleSymbol inputOnly:inp label:label owner:owner icon:icn iconMask:icnM iconView:icnV.
+        ^ self.
+    ].
+    gc createWindowFor:aView type:typeSymbol origin:org extent:ext minExtent:minE maxExtent:maxE borderWidth:bw subViewOf:sv style:styleSymbol inputOnly:inp label:label owner:owner icon:icn iconMask:icnM iconView:icnV 
+! !
+
--- a/SimpleView.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/SimpleView.st	Thu May 08 10:27:51 2014 +0200
@@ -9,6 +9,8 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 26-03-2014 at 14:24:19'                   !
+
 "{ Package: 'stx:libview' }"
 
 DisplaySurface subclass:#SimpleView
@@ -838,12 +840,11 @@
 
     newView := self basicNew.
     aView notNil ifTrue:[
-	newView device:(aView graphicsDevice).
+        newView initializeForDevice:(aView graphicsDevice).
 "/      newView container:aView.
     ] ifFalse:[
-	newView device:Screen current
-    ].
-    newView initialize.
+        newView initializeForDevice:Screen current
+    ].
     aView notNil ifTrue:[aView addSubView:newView].
     ^ newView
 
@@ -918,7 +919,7 @@
 	newView initialize.
 	aView addSubView:newView.
     ] ifFalse:[
-	newView := self onDevice:Screen current
+	newView := self new. "/ onDevice:Screen current
     ].
     bw notNil ifTrue:[newView borderWidth:bw].
     anOrigin notNil ifTrue:[newView origin:anOrigin].
@@ -967,7 +968,7 @@
 	newView initialize.
 	aView addSubView:newView.
     ] ifFalse:[
-	newView := self onDevice:Screen current
+	newView := self new. "/ onDevice:Screen current
     ].
     bw notNil ifTrue:[newView borderWidth:bw].
     anExtent notNil ifTrue:[newView extent:anExtent].
@@ -1016,7 +1017,7 @@
 		minExtent:minExtent maxExtent:maxExtent
     |newView|
 
-    newView := self onDevice:Screen current.
+    newView := self new. "/ onDevice:Screen current.
     anOrigin notNil ifTrue:[newView origin:anOrigin].
     anExtent notNil ifTrue:[newView extent:anExtent].
     aLabel notNil ifTrue:[newView label:aLabel].
@@ -1089,20 +1090,18 @@
 
     DefaultFont notNil ifTrue:[^ DefaultFont].
 
-    DefaultFont isNil ifTrue:[
-	self == SimpleView ifFalse:[
-	    f := self superclass defaultFont.
-	] ifTrue:[
-	    f := super defaultFont
-	].
+    self == SimpleView ifTrue:[
+        f := super defaultFont
+    ] ifFalse:[
+        f := self superclass defaultFont.
     ].
 
     f notNil ifTrue:[
-	DefaultFont := f.
-	f := f onDevice:(Screen current).
-	f notNil ifTrue:[
-	    DefaultFont := f.
-	]
+        DefaultFont := f.
+        f := f onDevice:Screen current.
+        f notNil ifTrue:[
+            DefaultFont := f.
+        ]
     ].
     ^ DefaultFont
 
@@ -1116,10 +1115,10 @@
 
     DefaultFont := aFont.
     aFont notNil ifTrue:[
-	f := aFont onDevice:(Screen current).
-	f notNil ifTrue:[
-	    DefaultFont := f.
-	]
+        f := aFont onDevice:(Screen current).
+        f notNil ifTrue:[
+            DefaultFont := f.
+        ]
     ]
 
     "Modified: 18.3.1996 / 12:56:20 / cg"
@@ -1139,18 +1138,18 @@
     "set the view style for new views"
 
     DefaultStyle := aStyle.
-    "/ no need to read the stylesheet always here 
+    "/ no need to read the stylesheet always here
     "/ done later if the system is not already up and running
     "/ (which is the case, if there is already a styleSheet)
     "/ this will make startup of expecco and similar applications
-    "/ faster, because often, they find that another instance is already 
+    "/ faster, because often, they find that another instance is already
     "/ running and they simply forward the request to that one.
     "/ no need to read the stylesheet, then.
     "/ used to be unconditional, before.
     StyleSheet notNil ifTrue:[
-        (Screen notNil and:[Screen current notNil]) ifTrue:[
-            self readStyleSheetAndUpdateAllStyleCaches.
-        ].
+	(Screen notNil and:[Screen current notNil]) ifTrue:[
+	    self readStyleSheetAndUpdateAllStyleCaches.
+	].
     ].
 
     "
@@ -1244,23 +1243,23 @@
 !
 
 setDefaultStyle
-    |defStyle|
+    |defStyle sysInfo|
 
     DefaultStyle isNil ifTrue:[
-        defStyle := OperatingSystem getEnvironment:'STX_VIEWSTYLE'.
-        defStyle notNil ifTrue:[
-            DefaultStyle := defStyle asSymbol.
-        ] ifFalse:[
-            "/ use XP for both linux and older windows systems;
-            DefaultStyle := ViewStyle msWindowsXP.
-
-            OperatingSystem isMSWINDOWSlike ifTrue:[
-                "/ use Vista for vista systems;
-                OperatingSystem isVistaLike ifTrue:[
-                    DefaultStyle := ViewStyle msWindowsVista
-                ].
-            ].
-        ].
+	defStyle := OperatingSystem getEnvironment:'STX_VIEWSTYLE'.
+	defStyle notNil ifTrue:[
+	    DefaultStyle := defStyle asSymbol.
+	] ifFalse:[
+	    "/ use XP for both linux and older windows systems;
+	    DefaultStyle := ViewStyle msWindowsXP.
+
+	    OperatingSystem isMSWINDOWSlike ifTrue:[
+		"/ use Vista for vista systems;
+		OperatingSystem isVistaLike ifTrue:[
+		    DefaultStyle := ViewStyle msWindowsVista
+		].
+	    ].
+	].
     ].
 
     "Modified: / 03-02-2011 / 21:41:35 / cg"
@@ -1302,28 +1301,28 @@
     self changed:#style.
     SimpleView updateStyleCache.
     SimpleView allSubclassesDo:[:aClass |
-        "JV@2010-12-02: Removed to avoid lost of preferred fonts on image restart"
-        "/ cg: no, this is required!!!!!!
-        "/ otherwise, we get ugly courier fonts on windows
-        "/ updateStyleCache MUST clear any previously
-        "/ cached font values, otherwise you cannot load a style's font.
-        "/ if you want to keep your fonts, do it elsewhere (keep some userFontPrefs and restore from there)
-
-        "/ JV: Font preferences ARE already saved in user's setting.rc/setting.stx, but they
-        "/     are not reloaded on snapshot restart (which is correct, I think).
-        "/     This just discard such fonts. I would say calling this upon snapshot restart
-        "/     is a bad idea. Workaround it only for me is not a solution as all other
-        "/     Linux users are ... off. Let's workaround it:
-        (Smalltalk isInitialized not and:
-            [OperatingSystem getOSType == #linux and:
-                [UserPreferences current linuxFontWorkaround]])
-                    ifFalse:[
-                        aClass defaultFont:nil.
-                    ].
-
-        (aClass class includesSelector:#updateStyleCache) ifTrue:[
-            aClass updateStyleCache
-        ].
+	"JV@2010-12-02: Removed to avoid lost of preferred fonts on image restart"
+	"/ cg: no, this is required!!!!!!
+	"/ otherwise, we get ugly courier fonts on windows
+	"/ updateStyleCache MUST clear any previously
+	"/ cached font values, otherwise you cannot load a style's font.
+	"/ if you want to keep your fonts, do it elsewhere (keep some userFontPrefs and restore from there)
+
+	"/ JV: Font preferences ARE already saved in user's setting.rc/setting.stx, but they
+	"/     are not reloaded on snapshot restart (which is correct, I think).
+	"/     This just discard such fonts. I would say calling this upon snapshot restart
+	"/     is a bad idea. Workaround it only for me is not a solution as all other
+	"/     Linux users are ... off. Let's workaround it:
+	(Smalltalk isInitialized not and:
+	    [OperatingSystem getOSType == #linux and:
+		[UserPreferences current linuxFontWorkaround]])
+		    ifFalse:[
+			aClass defaultFont:nil.
+		    ].
+
+	(aClass class includesSelector:#updateStyleCache) ifTrue:[
+	    aClass updateStyleCache
+	].
     ]
 
     "
@@ -1367,12 +1366,12 @@
     Grey := Grey onDevice:currentScreen.
 
     StyleSheet fileReadFailed ifTrue:[
-	bgGrey := White
+	bgGrey := Color white
     ] ifFalse:[
 	currentScreen hasGrayscales ifTrue:[
 	    bgGrey := Grey
 	] ifFalse:[
-	    bgGrey := White
+	    bgGrey := Color white.
 	]
     ].
     bgGrey := bgGrey onDevice:currentScreen.
@@ -1389,11 +1388,9 @@
 
     StyleSheet fileReadFailed ifTrue:[
 	DefaultBorderWidth := 1.
-	DefaultShadowColor := Black.
-	DefaultLightColor :=  White.
-	DefaultFocusColor := Black.
+	DefaultFocusColor := DefaultShadowColor := Color black.
+	DefaultViewBackgroundColor := DefaultLightColor :=  Color white.
 	DefaultFocusBorderWidth := 1.
-	DefaultViewBackgroundColor := White.
     ] ifFalse:[
 	DefaultBorderWidth := StyleSheet at:#borderWidth default:0.
 	DefaultViewBackgroundColor := StyleSheet colorAt:#viewBackground default:bgGrey.
@@ -1415,7 +1412,7 @@
 
     DefaultViewBackgroundColor isNil ifTrue:[
 	'SimpleView [warning]: bad viewBackground in style - using white' errorPrintCR.
-	DefaultViewBackgroundColor := White
+	DefaultViewBackgroundColor := Color white
     ].
 
     "Modified: / 29-04-1997 / 11:16:52 / dq"
@@ -1970,16 +1967,16 @@
 
     aForm isNil ifTrue:[
 	viewShape := nil.
-	drawableId notNil ifTrue:[
-	    device setWindowBorderShape:nil in:drawableId
+	self drawableId notNil ifTrue:[
+	    self graphicsDevice setWindowBorderShape:nil in:self drawableId
 	]
     ] ifFalse:[
 	viewShape isNil ifTrue:[
 	    viewShape := ArbitraryViewShape new
 	].
 	viewShape borderShapeForm:aForm.
-	drawableId notNil ifTrue:[
-	    device setWindowBorderShape:(aForm id) in:drawableId
+	self drawableId notNil ifTrue:[
+	    self graphicsDevice setWindowBorderShape:(aForm id) in:self drawableId
 	]
     ]
 
@@ -2194,7 +2191,7 @@
     self assert:(something notNil) message:'invalid viewBackground argument'.
 
     something isColor ifTrue:[
-	device hasGrayscales ifTrue:[
+	self graphicsDevice hasGrayscales ifTrue:[
 	    avgColor := something averageColorIn:(0@0 corner:7@7).
 	    shadowColor := avgColor darkened "on:device".
 	    lightColor := avgColor lightened "on:device".
@@ -2210,8 +2207,8 @@
 
     aForm isNil ifTrue:[
 	viewShape := nil.
-	drawableId notNil ifTrue:[
-	    device setWindowShape:nil in:drawableId
+	self drawableId notNil ifTrue:[
+	    self graphicsDevice setWindowShape:nil in:self drawableId
 	]
     ] ifFalse:[
 	viewShape isNil ifTrue:[
@@ -2219,8 +2216,8 @@
 	].
 
 	viewShape viewShapeForm:aForm.
-	drawableId notNil ifTrue:[
-	    device setWindowShape:(aForm id) in:drawableId
+	self drawableId notNil ifTrue:[
+	    self graphicsDevice setWindowShape:(aForm id) in:self drawableId
 	]
     ]
 
@@ -2584,7 +2581,7 @@
 
     corner isBlock ifTrue:[
 	cornerRule := corner.
-	drawableId notNil ifTrue:[
+	self drawableId notNil ifTrue:[
 	    pixelCorner := corner value
 	] ifFalse:[
 	    self extentChangedFlag:true
@@ -2641,7 +2638,7 @@
 
     extent isBlock ifTrue:[
 	extentRule := extent.
-	drawableId notNil ifTrue:[
+	self drawableId notNil ifTrue:[
 	    pixelExtent := extent value
 	] ifFalse:[
 	    self extentChangedFlag:true
@@ -2847,7 +2844,16 @@
      Currently, this is almost nowhere used but views will be
      incrementally changed to use this new geometry management."
 
-    layout := aLayoutObject.
+    layout = aLayoutObject ifFalse:[
+        layout := aLayoutObject.
+        self layoutChanged.
+    ].
+
+    "Modified: 19.9.1995 / 16:17:25 / claus"
+    "Modified: 19.7.1996 / 17:30:27 / cg"
+!
+
+layoutChanged
     superView isNil ifTrue:[
 	self originChangedFlag:true extentChangedFlag:true cornerChangedFlag:true.
     ] ifFalse:[
@@ -2922,69 +2928,69 @@
     origin := left@top.
     corner := (left + width)@(top + height).
 
-    originVisible := device pointIsVisible:origin.
-    cornerVisible := device pointIsVisible:corner.
-
-    (device pointsAreOnSameMonitor:origin and:corner) ifTrue:[
-        referencePoint := origin.
+    originVisible := self graphicsDevice pointIsVisible:origin.
+    cornerVisible := self graphicsDevice pointIsVisible:corner.
+
+    (self graphicsDevice pointsAreOnSameMonitor:origin and:corner) ifTrue:[
+	referencePoint := origin.
     ] ifFalse:[
-        originVisible ifTrue:[
-            "origin is visible"
-            referencePoint := origin.
-        ] ifFalse:[
-            cornerVisible notNil ifTrue:[
-                "corner is visible"
-                referencePoint := corner.
-            ] ifFalse:[
-                referencePoint := 1@1.
-            ].
-        ].
-    ].
-    deviceBounds := device monitorBoundsAt:referencePoint.
+	originVisible ifTrue:[
+	    "origin is visible"
+	    referencePoint := origin.
+	] ifFalse:[
+	    cornerVisible notNil ifTrue:[
+		"corner is visible"
+		referencePoint := corner.
+	    ] ifFalse:[
+		referencePoint := 1@1.
+	    ].
+	].
+    ].
+    deviceBounds := self graphicsDevice monitorBoundsAt:referencePoint.
 
     deviceLeft := deviceBounds left.
     deviceRight := deviceBounds right.
     deviceTop := deviceBounds top.
     deviceBottom := deviceBounds bottom.
 
-    originVisible ifTrue:[ deviceBottom := deviceBottom min:(device usableHeightAt:origin) ].
-    cornerVisible ifTrue:[ deviceBottom := deviceBottom min:(device usableHeightAt:corner) ].
+    originVisible ifTrue:[ deviceBottom := deviceBottom min:(self graphicsDevice usableHeightAt:origin) ].
+    cornerVisible ifTrue:[ deviceBottom := deviceBottom min:(self graphicsDevice usableHeightAt:corner) ].
 
     corner y > deviceBottom ifTrue:[
-        cornerVisible := false.
+	cornerVisible := false.
     ].
 
     UserPreferences current forceWindowsIntoMonitorBounds ifFalse:[
-        (originVisible and:[cornerVisible]) ifTrue:[^ self].
+	(originVisible and:[cornerVisible]) ifTrue:[^ self].
     ].
 
     "/ deviceRight := deviceRight min:device usableWidth.
     originVisible ifFalse:[
-        cornerVisible ifFalse:[
-            newTop := deviceBottom - height.
-            newLeft := deviceRight - width.
-            newLeft := newLeft max:deviceLeft.
-            newTop := newTop max:deviceTop.
-        ] ifTrue:[
-            "/ origin is not; corner is in
-            newLeft := (deviceLeft max:newLeft).
-            newTop := (deviceTop max:newTop).
-        ].
+	cornerVisible ifFalse:[
+	    newTop := deviceBottom - height.
+	    newLeft := deviceRight - width.
+	    newLeft := newLeft max:deviceLeft.
+	    newTop := newTop max:deviceTop.
+	] ifTrue:[
+	    "/ origin is not; corner is in
+	    newLeft := (deviceLeft max:newLeft).
+	    newTop := (deviceTop max:newTop).
+	].
     ] ifTrue:[
-        "/ notice, the position-dependent query: if there is a higher secondary screen,
-        "/ this makes a difference in where a popUpMenu is allowed...
-        (corner y > deviceBottom) ifTrue:[
-            newTop := deviceBottom - height
-        ].
-        (corner x > deviceRight) ifTrue:[
-            newLeft := deviceRight - width
-        ].
-        newLeft := newLeft max:deviceLeft.
-        newTop := newTop max:deviceTop.
+	"/ notice, the position-dependent query: if there is a higher secondary screen,
+	"/ this makes a difference in where a popUpMenu is allowed...
+	(corner y > deviceBottom) ifTrue:[
+	    newTop := deviceBottom - height
+	].
+	(corner x > deviceRight) ifTrue:[
+	    newLeft := deviceRight - width
+	].
+	newLeft := newLeft max:deviceLeft.
+	newTop := newTop max:deviceTop.
     ].
 
     ((newTop ~~ top) or:[newLeft ~~ left]) ifTrue:[
-        self origin:newLeft @ newTop
+	self origin:newLeft @ newTop
     ].
 
     "Modified: / 27-10-2012 / 13:15:58 / cg"
@@ -3002,13 +3008,13 @@
     "setup my window for a round shaped view;
      this is not supported by all devices"
 
-    |extent shapeForm borderForm w h f|
-
-    device supportsRoundShapedViews ifTrue:[
+    |extent shapeForm borderForm w h f lw|
+
+    self graphicsDevice supportsRoundShapedViews ifTrue:[
 	"/ TODO: add code for round shaped view (mswin)
     ].
 
-    device supportsArbitraryShapedViews ifTrue:[
+    self graphicsDevice supportsArbitraryShapedViews ifTrue:[
 	extent := self extent.
 	w := extent x.
 	h := extent y.
@@ -3029,7 +3035,7 @@
 	    shapeForm foreground:(Color colorId:1).
 	].
 
-	f fillArcX:lineWidth y:lineWidth
+	f fillArcX:(lw := gc lineWidth) y:lw
 		width:w - (bw * 2)
 	       height:h - (bw * 2)
 		 from:0
@@ -3083,11 +3089,11 @@
 
     |extent shapeForm borderForm w h f|
 
-"/    device supportsPolygonShapedViews ifTrue:[
+"/    self graphicsDevice supportsPolygonShapedViews ifTrue:[
 "/        "/ TODO: add code for mswin
 "/    ].
 
-    device supportsArbitraryShapedViews ifTrue:[
+    self graphicsDevice supportsArbitraryShapedViews ifTrue:[
 	extent := self extent.
 	w := extent x.
 	h := extent y.
@@ -3111,7 +3117,6 @@
 	self viewShape:shapeForm.
 	^ self.
     ]
-
 !
 
 minExtent
@@ -3140,7 +3145,7 @@
 
     origin isBlock ifTrue:[
 	originRule := origin.
-	drawableId notNil ifTrue:[
+	self drawableId notNil ifTrue:[
 	    pixelOrigin := origin value
 	] ifFalse:[
 	    self originChangedFlag:true
@@ -3256,7 +3261,7 @@
 	sumY := sumY + (currentView top) + bw.
 	currentView := currentView superView
     ].
-    (aView isNil or:[aView == device rootView]) ifTrue:[
+    (aView isNil or:[aView == self graphicsDevice rootView]) ifTrue:[
 	"return relative to screen ..."
 	^ (sumX @ sumY)
     ].
@@ -3605,7 +3610,7 @@
 	^ self.
     ].
 
-    (drawableId notNil) ifTrue:[
+    (self drawableId notNil) ifTrue:[
 	"/ actually, this is worth an exception
 	"/ ('View [error]: ' , self printString , ' already realized - cannot change container') errorPrintCR.
 	self error:'already realized - cannot change container' mayProceed:true.
@@ -3671,8 +3676,8 @@
 lower
     "bring to back"
 
-    drawableId isNil ifTrue:[self create].
-    device lowerWindow:drawableId
+    self drawableId isNil ifTrue:[self create].
+    self graphicsDevice lowerWindow:self drawableId
 
     "
      Transcript topView lower
@@ -3688,8 +3693,8 @@
      Use #setForegroundWindow to raise above the currently active window,
      or mark as #beScreenDialog before opening"
 
-    drawableId isNil ifTrue:[self create].
-    device raiseWindowToTop:drawableId
+    self drawableId isNil ifTrue:[self create].
+    self graphicsDevice raiseWindowToTop:self drawableId
 
     "
      Transcript topView raise
@@ -3848,7 +3853,7 @@
 
     sym numArgs > 0 ifTrue:[
 	"/ squeak compatibility (with args): create the empty menu here, let model add items
-	^ menuHolder perform:sym withOptionalArgument:(Menu new) and:(device shiftDown).
+	^ menuHolder perform:sym withOptionalArgument:(Menu new) and:(self graphicsDevice shiftDown).
     ].
 
     "
@@ -3871,70 +3876,69 @@
      when the view is resized."
 
     bitGravity ~~ gravity ifTrue:[
-        bitGravity := gravity.
-        super bitGravity:gravity.
+	bitGravity := gravity.
+	gc bitGravity:gravity.
     ]
 !
 
-clippingBounds:aRectangle
+clippingBounds:aRectangleOrNil
     "set the clipping rectangle for drawing (in logical coordinates);
      a nil argument turns off clipping (i.e. whole view is drawable).
      Redefined to care for any margin."
 
-    |x y w h|
-
-    aRectangle isNil ifTrue:[
-        clipRect isNil ifTrue:[^ self].
-        gcId notNil ifTrue:[
-            device noClipIn:drawableId gc:gcId
-        ]
-    ] ifFalse:[
-        clipRect notNil ifTrue:[
-            (clipRect = aRectangle) ifTrue:[^ self]
+    |x y w h currentClippingBounds newBounds|
+
+    currentClippingBounds := gc clippingBoundsOrNil.
+    (currentClippingBounds = aRectangleOrNil) ifTrue:[
+        ^ self
+    ].
+    newBounds := aRectangleOrNil.
+
+    aRectangleOrNil notNil ifTrue:[
+        |currentTransformation|
+
+        x := aRectangleOrNil left.
+        y := aRectangleOrNil top.
+        w := aRectangleOrNil width.
+        h := aRectangleOrNil height.
+        currentTransformation := gc transformation.
+        currentTransformation notNil ifTrue:[
+            x := currentTransformation applyToX:x.
+            y := currentTransformation applyToY:y.
+            w := currentTransformation applyScaleX:w.
+            h := currentTransformation applyScaleY:h.
+        ].
+        (x isMemberOf:SmallInteger) ifFalse:[
+            w := w + (x - x truncated).
+            x := x truncated
         ].
-        gcId notNil ifTrue:[
-            x := aRectangle left.
-            y := aRectangle top.
-            w := aRectangle width.
-            h := aRectangle height.
-            transformation notNil ifTrue:[
-                x := transformation applyToX:x.
-                y := transformation applyToY:y.
-                w := transformation applyScaleX:w.
-                h := transformation applyScaleY:h.
-            ].
-            (x isMemberOf:SmallInteger) ifFalse:[
-                w := w + (x - x truncated).
-                x := x truncated
-            ].
-            (y isMemberOf:SmallInteger) ifFalse:[
-                h := h + (y - y truncated).
-                y := y truncated
-            ].
-            (w isMemberOf:SmallInteger) ifFalse:[
-                w := w truncated + 1
-            ].
-            (h isMemberOf:SmallInteger) ifFalse:[
-                h := h truncated + 1
-            ].
-            x < margin ifTrue:[
-                x := margin.
-            ].
-            y < margin ifTrue:[
-                y := margin.
-            ].
-            x + w - 1 >= (width-margin) ifTrue:[
-                w := width - margin - x
-            ].
-            y + h - 1 >= (height-margin) ifTrue:[
-                h := height - margin - y
-            ].
-            w := w max:0.
-            h := h max:0.
-            device setClipX:x y:y width:w height:h in:drawableId gc:gcId
-        ]
-    ].
-    clipRect := aRectangle
+        (y isMemberOf:SmallInteger) ifFalse:[
+            h := h + (y - y truncated).
+            y := y truncated
+        ].
+        (w isMemberOf:SmallInteger) ifFalse:[
+            w := w truncated + 1
+        ].
+        (h isMemberOf:SmallInteger) ifFalse:[
+            h := h truncated + 1
+        ].
+        x < margin ifTrue:[
+            x := margin.
+        ].
+        y < margin ifTrue:[
+            y := margin.
+        ].
+        x + w - 1 >= (width-margin) ifTrue:[
+            w := width - margin - x
+        ].
+        y + h - 1 >= (height-margin) ifTrue:[
+            h := height - margin - y
+        ].
+        w := w max:0.
+        h := h max:0.
+        newBounds := Rectangle left:x top:y width:w height:h.
+    ].
+    gc deviceClippingBounds:newBounds
 
     "Created: 28.5.1996 / 19:50:03 / cg"
     "Modified: 28.5.1996 / 22:32:15 / cg"
@@ -4010,8 +4014,8 @@
      when the superView is resized."
 
     viewGravity ~~ gravity ifTrue:[
-        viewGravity := gravity.
-        super viewGravity:gravity.
+	viewGravity := gravity.
+	gc viewGravity:gravity.
     ]
 ! !
 
@@ -4167,16 +4171,18 @@
 setViewOrigin:aPoint
     "set the viewOrigin - i.e. virtually scroll without redrawing"
 
-    |p|
-
-    p := aPoint negated.
-    transformation isNil ifTrue:[
-	transformation := WindowingTransformation scale:1 translation:p
+    |currentTransformation|
+
+    currentTransformation := gc transformation.
+    currentTransformation isNil ifTrue:[
+        (aPoint x ~~ 0 or:[aPoint y ~~ 0]) ifTrue:[
+            gc transformation:(WindowingTransformation scale:1 translation:aPoint negated).
+        ].
     ] ifFalse:[
-	transformation translation:p
-    ].
-    clipRect notNil ifTrue:[
-	self setInnerClip.
+        currentTransformation translation:aPoint negated.
+    ].
+    self clippingBoundsOrNil notNil ifTrue:[
+        self setInnerClip.
     ].
 !
 
@@ -4185,10 +4191,13 @@
      which is shown topLeft in the view
      (i.e. the origin of the visible part of the contents)."
 
-    transformation isNil ifTrue:[
+    |currentTransformation|
+
+    currentTransformation := gc transformation.
+    currentTransformation isNil ifTrue:[
 	^ 0@0
     ].
-    ^ transformation translation negated
+    ^ currentTransformation translation negated
 !
 
 visibleArea
@@ -4196,11 +4205,14 @@
      of the view in user coordinates."
 
 
-    transformation isNil ifTrue:[
+    |currentTransformation|
+
+    currentTransformation := gc transformation.
+    currentTransformation isNil ifTrue:[
 	^ Rectangle left:0 top:0 width:width height:height.
     ].
-    ^ Rectangle origin:(transformation translation negated)
-		extent:((width @ height) scaledBy:(transformation scale)).
+    ^ Rectangle origin:(currentTransformation translation negated)
+		extent:((width @ height) scaledBy:(currentTransformation scale)).
 
     "Created: 12.7.1996 / 11:57:04 / stefan"
 !
@@ -4253,7 +4265,7 @@
     self hiddenOnRealize:false.
     realized ifFalse:[
 	superView isNil ifTrue:[                "/ I am a topView
-	    drawableId isNil ifTrue:[
+	    self drawableId isNil ifTrue:[
 		"this once was:
 		   self realize.
 		 but we don't want Topviews to realize implicitly.
@@ -4304,7 +4316,7 @@
      visible."
 
     self beVisible.
-    device sync.    "thats a round-trip; when returning, the view is definitely visible"
+    self graphicsDevice sync.    "thats a round-trip; when returning, the view is definitely visible"
 
 "/    realized := true.
 "/    shown := true.
@@ -4563,17 +4575,17 @@
      element at some defined place."
 
     subViews isNil ifTrue:[
-        subViews := OrderedCollection with:newView
+	subViews := OrderedCollection with:newView
     ] ifFalse:[
-        (subViews includesIdentical:newView) ifTrue:[
-            self error:'trying to add a view twice' mayProceed:true.
-            ^ self.
-        ].
-        aViewOrNil isNil ifTrue:[
-            subViews add:newView
-        ] ifFalse:[
-            subViews add:newView after:aViewOrNil.
-        ]
+	(subViews includesIdentical:newView) ifTrue:[
+	    self error:'trying to add a view twice' mayProceed:true.
+	    ^ self.
+	].
+	aViewOrNil isNil ifTrue:[
+	    subViews add:newView
+	] ifFalse:[
+	    subViews add:newView after:aViewOrNil.
+	]
     ].
     self setContainerIn:newView.
 
@@ -4588,17 +4600,17 @@
      element at some defined place."
 
     subViews isNil ifTrue:[
-        subViews := OrderedCollection with:newView
+	subViews := OrderedCollection with:newView
     ] ifFalse:[
-        (subViews includesIdentical:newView) ifTrue:[
-            self error:'trying to add a view twice' mayProceed:true.
-            ^ self.
-        ].
-        aViewOrNil isNil ifTrue:[
-            subViews addFirst:newView
-        ] ifFalse:[
-            subViews add:newView before:aViewOrNil.
-        ]
+	(subViews includesIdentical:newView) ifTrue:[
+	    self error:'trying to add a view twice' mayProceed:true.
+	    ^ self.
+	].
+	aViewOrNil isNil ifTrue:[
+	    subViews addFirst:newView
+	] ifFalse:[
+	    subViews add:newView before:aViewOrNil.
+	]
     ].
     self setContainerIn:newView.
 
@@ -4705,11 +4717,11 @@
     "common code for addSubView* methods"
 
     aView container:self.
-    (aView graphicsDevice ~~ device) ifTrue:[
+    (aView graphicsDevice ~~ self graphicsDevice) ifTrue:[
 	'SimpleView [warning]: subview (' errorPrint. aView class name errorPrint.
 	') has different device than me (' errorPrint.
 	self class name errorPrint. ').' errorPrintCR.
-	aView device:device
+	aView device:self graphicsDevice
     ].
 
     "Created: 9.5.1996 / 00:46:59 / cg"
@@ -4757,50 +4769,50 @@
 
     ok := true.
     bitmaps := #('wheel1' 'wheel2' 'wheel3' 'wheel4')
-	       collect:[:name |
-		   |f|
-
-		   f := Smalltalk imageFromFileNamed:(name , '.xbm') forClass:self class.
-		   f isNil ifTrue:[
-			('SimpleView [warning]: no bitmap file: ' , name , '.xbm') errorPrintCR.
-			ok := false
-		   ].
-		   f
-	       ].
+               collect:[:name |
+                   |f|
+
+                   f := Smalltalk imageFromFileNamed:(name , '.xbm') forClass:self class.
+                   f isNil ifTrue:[
+                        ('SimpleView [warning]: no bitmap file: ' , name , '.xbm') errorPrintCR.
+                        ok := false
+                   ].
+                   f
+               ].
 
     ok ifTrue:[
-	maskForm := Smalltalk imageFromFileNamed:'wheelm.xbm' forClass:self class.
-	maskForm isNil ifTrue:[
-	    ('SimpleView [warning]: no bitmap file: wheelm.xbm') errorPrintCR.
-	    ok := false
-	].
+        maskForm := Smalltalk imageFromFileNamed:'wheelm.xbm' forClass:self class.
+        maskForm isNil ifTrue:[
+            ('SimpleView [warning]: no bitmap file: wheelm.xbm') errorPrintCR.
+            ok := false
+        ].
     ].
 
     ok ifFalse:[
-	self cursor:Cursor wait.
-	aBlock ensure:[
-	    self cursor:oldCursor
-	]
+        self cursor:Cursor wait.
+        aBlock ensure:[
+            self cursor:oldCursor
+        ]
     ] ifTrue:[
-	cursors := bitmaps collect:[:form | (Cursor sourceForm:form
-						      maskForm:maskForm
-							  hotX:8
-							  hotY:8) onDevice:device].
-
-	process := [
-		    Delay waitForSeconds:0.25.
-		    [true] whileTrue:[
-			cursors do:[:curs |
-			    self cursor:curs.
-			    Delay waitForSeconds:0.05
-			]
-		    ]
-		   ] forkAt:(Processor activeProcess priority + 1).
-
-	aBlock ensure:[
-	    process terminate.
-	    self cursor:oldCursor
-	]
+        cursors := bitmaps collect:[:form | (Cursor sourceForm:form
+                                                      maskForm:maskForm
+                                                          hotX:8
+                                                          hotY:8) onDevice:self graphicsDevice].
+
+        process := [
+                    Delay waitForSeconds:0.25.
+                    [
+                        cursors do:[:curs |
+                            self cursor:curs.
+                            Delay waitForSeconds:0.05.
+                        ]
+                    ] loop.
+           ] forkAt:(Processor activeProcess priority + 1).
+
+        aBlock ensure:[
+            process terminate.
+            self cursor:oldCursor
+        ]
     ].
 
     "
@@ -5205,7 +5217,7 @@
     ].
 
     ((edgeStyle == #soft) and:[level > 2]) ifTrue:[
-	super paint:(device blackColor).
+	super paint:(self graphicsDevice blackColor).
 	super displayDeviceLineFromX:0 y:0 toX:0 y:b.
     ].
 
@@ -5305,7 +5317,7 @@
 	super displayDeviceLineFromX:i y:i toX:(r - i) y:i
     ].
     ((edgeStyle == #soft) and:[level > 2]) ifTrue:[
-	super paint:(device blackColor).
+	super paint:(self graphicsDevice blackColor).
 	super displayDeviceLineFromX:0 y:0 toX:r y:0.
     ].
 
@@ -5318,31 +5330,32 @@
     "redraw my edges (if any)"
 
     (level ~~ 0) ifTrue:[
-	shown ifTrue:[
-	    self clippingRectangle:nil.
-	    self drawEdges.
-	    self deviceClippingRectangle:innerClipRect
-	]
+        shown ifTrue:[
+            gc clippingBounds:nil.
+            self drawEdges.
+            gc deviceClippingBounds:innerClipRect
+        ]
     ]
 
     "Modified: / 25.5.1999 / 14:50:25 / cg"
 ! !
 
-!SimpleView methodsFor:'enumerating subviews'!
-
-allSubViewsDetect:aBlock ifNone:exceptionBlock
-    "find a subview for which aBlock returns true (recursively)"
+!SimpleView methodsFor:'enumerating view hierarchy'!
+
+allSubViewsDetect:aBlock ifNone:exceptionValue
+    "find a subview for which aBlock returns true (recursively).
+     If there is none, return the value from exceptionValue"
 
     subViews notNil ifTrue:[
-	subViews do:[:aSubview |
-	    |v|
-
-	    (aBlock value:aSubview) ifTrue:[ ^ aSubview ].
-	    v := aSubview allSubViewsDetect:aBlock ifNone:nil.
-	    v notNil ifTrue:[^ v].
-	]
-    ].
-    ^ exceptionBlock value.
+        subViews do:[:aSubview |
+            |v|
+
+            (aBlock value:aSubview) ifTrue:[ ^ aSubview ].
+            v := aSubview allSubViewsDetect:aBlock ifNone:nil.
+            v notNil ifTrue:[^ v].
+        ]
+    ].
+    ^ exceptionValue value.
 
     "Modified: 12.2.1997 / 12:23:38 / cg"
 !
@@ -5359,6 +5372,32 @@
     "Modified: 12.2.1997 / 12:23:38 / cg"
 !
 
+allSuperViewsDetect:aBlock ifNone:exceptionValue
+    "find a container for which aBlock returns true (recursively).
+     If there is none, return the value from exceptionValue"
+
+    |v|
+
+    v := self container.
+    [v notNil] whileTrue:[
+        (aBlock value:v) ifTrue:[^ v].
+        v := v container.
+    ].
+    ^ exceptionValue value
+!
+
+allSuperViewsDo:aBlock
+    "evaluate aBlock for all superviews (recursively)"
+
+    |v|
+
+    v := self container.
+    [v notNil] whileTrue:[
+        aBlock value:v.
+        v := v container.
+    ].
+!
+
 allVisibleSubViewsDetect:aBlock ifNone:exceptionBlock
     "find a visible subview for which aBlock returns true (recursively)"
 
@@ -5511,8 +5550,8 @@
     "button was moved"
 
     self topView == TopView currentWindowBeingMoved ifTrue:[
-        self topView doWindowMove.
-        ^ self.
+	self topView doWindowMove.
+	^ self.
     ].
 
     "Created: / 03-03-2011 / 19:11:11 / cg"
@@ -5540,16 +5579,16 @@
     |topView|
 
     components notNil ifTrue:[
-        self componentsContainingX:x y:y do:[:comp :cx :cy |
-            comp buttonPress:button x:cx y:cy.
-            ^ self
-        ]
+	self componentsContainingX:x y:y do:[:comp :cx :cy |
+	    comp buttonPress:button x:cx y:cy.
+	    ^ self
+	]
     ].
 
     "/ an undecorated (but modeless) topView -> do a window move
     (topView := self topView) startWindowMoveOnButtonPress ifTrue:[
-        topView startWindowMove.
-        ^ self.
+	topView startWindowMove.
+	^ self.
     ].
 
     super buttonPress:button x:x y:y
@@ -5561,15 +5600,15 @@
     "button was released - check my components for a hit."
 
     components notNil ifTrue:[
-        self componentsContainingX:x y:y do:[:comp :cx :cy |
-            comp buttonRelease:button x:cx y:cy.
-            ^ self
-        ]
+	self componentsContainingX:x y:y do:[:comp :cx :cy |
+	    comp buttonRelease:button x:cx y:cy.
+	    ^ self
+	]
     ].
 
     self topView == TopView currentWindowBeingMoved ifTrue:[
-        self topView endWindowMove.
-        ^ self.
+	self topView endWindowMove.
+	^ self.
     ].
 
     super buttonRelease:button x:x y:y
@@ -5626,11 +5665,11 @@
     top := y.
 
     (superView isNil
-    and:[drawableId notNil]) ifTrue:[
+    and:[self drawableId notNil]) ifTrue:[
 	"/ have to be careful - some window managers (motif) wrap another
 	"/ view around and the reported origin is relative to that.
 	"/ not relative to the screen.
-	p := device translatePoint:0@0 fromView:self toView:nil.
+	p := self graphicsDevice translatePoint:0@0 fromView:self toView:nil.
 	p := p + self borderWidth.
 	left := p x.
 	top := p y.
@@ -5874,7 +5913,7 @@
 "/    Transcript show:'  Data:'; showCR:dropObjects.
 
     self alienDrop:dropObjects position:dropPosition.
-    device dragFinish:dropHandle.
+    self graphicsDevice dragFinish:dropHandle.
 
     "Modified: / 13-10-2006 / 10:10:23 / cg"
 !
@@ -5883,16 +5922,16 @@
     "a low level redraw event from device
       - let subclass handle the redraw and take care of edges here"
 
-    |leftEdge topEdge rightEdge botEdge anyEdge nx ny nw nh dx dy dw dh old oldPaint|
+    |leftEdge topEdge rightEdge botEdge anyEdge nx ny nw nh old oldPaint|
 
     shown ifFalse:[
-	^ self
-    ].
-
-    nw := dw := w.
-    nh := dh := h.
-    nx := dx := x.
-    ny := dy := y.
+        ^ self
+    ].
+
+    nw := w.
+    nh := h.
+    nx := x.
+    ny := y.
 
     anyEdge := false.
 
@@ -5900,114 +5939,112 @@
      check if there is a need to draw an edge (i.e. if margin is hit)
     "
     (margin ~~ 0) ifTrue:[
-	leftEdge := false.
-	topEdge := false.
-	rightEdge := false.
-	botEdge := false.
-	transformation notNil ifTrue:[
-	    "
-	     need device coordinates for this test
-	    "
-	    nx := transformation applyToX:nx.
-	    ny := transformation applyToY:ny.
-	    nw := transformation applyScaleX:nw.
-	    nh := transformation applyScaleY:nh.
-	].
-	"
-	 adjust expose rectangle, to exclude the margin.
-	 Care for rounding errors ...
-	"
-	(nx isMemberOf:SmallInteger) ifFalse:[
-	    old := nx.
-	    nx := nx truncated.
-	    nw := nw + (nx - old).
-	].
-	(ny isMemberOf:SmallInteger) ifFalse:[
-	    old := ny.
-	    ny := ny truncated.
-	    nh := nh + (ny - old).
-	].
-	(nw isMemberOf:SmallInteger) ifFalse:[
-	    nw := nw truncated + 1
-	].
-	(nh isMemberOf:SmallInteger) ifFalse:[
-	    nh := nh truncated + 1
-	].
-
-	dx := nx.
-	dy := ny.
-	dw := nw.
-	dh := nh.
-
-	(nx < margin) ifTrue:[
-	    old := nx.
-	    nx := margin.
-	    nw := nw - (nx - old).
-	    leftEdge := anyEdge := true.
-	].
-	((nx + nw - 1) >= (width - margin)) ifTrue:[
-	    nw := (width - margin - nx).
-	    rightEdge := anyEdge := true.
-	].
-	(ny < margin) ifTrue:[
-	    old := ny.
-	    ny := margin.
-	    nh := nh - (ny - old).
-	    topEdge := anyEdge := true.
-	].
-	((ny + nh - 1) >= (height - margin)) ifTrue:[
-	    nh := (height - margin - ny).
-	    botEdge := anyEdge := true.
-	].
-	transformation notNil ifTrue:[
-	    "
-	     need logical coordinates for redraw
-	    "
-	    nx := transformation applyInverseToX:nx.
-	    ny := transformation applyInverseToY:ny.
-	    nw := transformation applyInverseScaleX:nw.
-	    nh := transformation applyInverseScaleY:nh.
-	].
+        |currentTransformation|
+
+        leftEdge := false.
+        topEdge := false.
+        rightEdge := false.
+        botEdge := false.
+        currentTransformation := gc transformation.
+        currentTransformation notNil ifTrue:[
+            "
+             need device coordinates for this test
+            "
+            nx := currentTransformation applyToX:nx.
+            ny := currentTransformation applyToY:ny.
+            nw := currentTransformation applyScaleX:nw.
+            nh := currentTransformation applyScaleY:nh.
+        ].
+        "
+         adjust expose rectangle, to exclude the margin.
+         Care for rounding errors ...
+        "
+        (nx isMemberOf:SmallInteger) ifFalse:[
+            old := nx.
+            nx := nx truncated.
+            nw := nw + (nx - old).
+        ].
+        (ny isMemberOf:SmallInteger) ifFalse:[
+            old := ny.
+            ny := ny truncated.
+            nh := nh + (ny - old).
+        ].
+        (nw isMemberOf:SmallInteger) ifFalse:[
+            nw := nw truncated + 1
+        ].
+        (nh isMemberOf:SmallInteger) ifFalse:[
+            nh := nh truncated + 1
+        ].
+
+        (nx < margin) ifTrue:[
+            old := nx.
+            nx := margin.
+            nw := nw - (nx - old).
+            leftEdge := anyEdge := true.
+        ].
+        ((nx + nw - 1) >= (width - margin)) ifTrue:[
+            nw := (width - margin - nx).
+            rightEdge := anyEdge := true.
+        ].
+        (ny < margin) ifTrue:[
+            old := ny.
+            ny := margin.
+            nh := nh - (ny - old).
+            topEdge := anyEdge := true.
+        ].
+        ((ny + nh - 1) >= (height - margin)) ifTrue:[
+            nh := (height - margin - ny).
+            botEdge := anyEdge := true.
+        ].
+        currentTransformation notNil ifTrue:[
+            "
+             need logical coordinates for redraw
+            "
+            nx := currentTransformation applyInverseToX:nx.
+            ny := currentTransformation applyInverseToY:ny.
+            nw := currentTransformation applyInverseScaleX:nw.
+            nh := currentTransformation applyInverseScaleY:nh.
+        ].
     ].
 
     (nw > 0 and:[nh > 0]) ifTrue:[
-	"
-	 redraw inside area
-	"
-	self clippingRectangle:(Rectangle left:nx top:ny width:nw height:nh).
-
-	self redrawX:nx y:ny width:nw height:nh.
+        "
+         redraw inside area
+        "
+        self 
+            clippingBounds:(Rectangle left:nx top:ny width:nw height:nh);
+            redrawX:nx y:ny width:nw height:nh.
     ].
 
     "
      redraw edge(s)
     "
     anyEdge ifTrue:[
-	self deviceClippingRectangle:nil.
-	oldPaint := paint.
-	border notNil ifTrue:[
-	    border displayOn:self forDisplayBox:(Rectangle left:0 top:0 width:width height:height).
-	] ifFalse:[
-	    (topEdge and:[leftEdge and:[botEdge and:[rightEdge]]]) ifTrue:[
-		self drawEdges
-	    ] ifFalse:[
-		topEdge ifTrue:[
-		    self drawTopEdge
-		].
-		leftEdge ifTrue:[
-		    self drawLeftEdge
-		].
-		botEdge ifTrue:[
-		    self drawBottomEdge
-		].
-		rightEdge ifTrue:[
-		    self drawRightEdge
-		]
-	    ].
-	].
-	self paint:oldPaint.
-    ].
-    self deviceClippingRectangle:innerClipRect.
+        self clippingBounds:nil.
+        oldPaint := self paint.
+        border notNil ifTrue:[
+            border displayOn:self forDisplayBox:(Rectangle left:0 top:0 width:width height:height).
+        ] ifFalse:[
+            (topEdge and:[leftEdge and:[botEdge and:[rightEdge]]]) ifTrue:[
+                self drawEdges
+            ] ifFalse:[
+                topEdge ifTrue:[
+                    self drawTopEdge
+                ].
+                leftEdge ifTrue:[
+                    self drawLeftEdge
+                ].
+                botEdge ifTrue:[
+                    self drawBottomEdge
+                ].
+                rightEdge ifTrue:[
+                    self drawRightEdge
+                ]
+            ].
+        ].
+        self paint:oldPaint.
+    ].
+    gc deviceClippingBounds:innerClipRect.
 
     "Modified: / 25.5.1999 / 14:57:38 / cg"
 !
@@ -6221,18 +6258,18 @@
 
     "/ first ask my flags if its enforced or forbidden
     self requestFocusOnPointerEnter ifTrue:[
-        doRequestFocus := true
+	doRequestFocus := true
     ] ifFalse:[
-        self doNotRequestFocusOnPointerEnter ifTrue:[
-            doRequestFocus := false
-        ] ifFalse:[
-            "/ then look for the settings.
-            doRequestFocus := self wantsFocusWithPointerEnter
-        ]
+	self doNotRequestFocusOnPointerEnter ifTrue:[
+	    doRequestFocus := false
+	] ifFalse:[
+	    "/ then look for the settings.
+	    doRequestFocus := self wantsFocusWithPointerEnter
+	]
     ].
 
     doRequestFocus ifTrue:[
-        self requestFocus.
+	self requestFocus.
     ].
 
     "Modified: / 01-08-2012 / 17:06:41 / cg"
@@ -6240,9 +6277,9 @@
 
 propertyChange:propertyId state: state
 
-    "A property has changed, nothing to do here.    
+    "A property has changed, nothing to do here.
      Note:
-     This is very X specific. PropertyChange events must be enabled 
+     This is very X specific. PropertyChange events must be enabled
      to get this event. To enable, do:
 
     self enableEvent: #propertyChange
@@ -6289,7 +6326,7 @@
 !
 
 sizeChanged:how
-    "tell subviews if I change size.
+    "tell subviews that I changed size.
      How is either #smaller, #larger or nil, and is used to control the order,
      in which subviews are notified (possibly reducing redraw activity)"
 
@@ -6550,7 +6587,7 @@
 !
 
 simulateButtonPress:button at:aPoint
-    "simulate a button press by determining which sub-view is affected and 
+    "simulate a button press by determining which sub-view is affected and
      synthetically generating a buttonPressEvent for wjatever view is underneath.
      Returns the view which precessed the event or nil."
 
@@ -6564,7 +6601,7 @@
 !
 
 simulateButtonRelease:button at:aPoint
-    "simulate a button release by determining which sub-view is affected and 
+    "simulate a button release by determining which sub-view is affected and
      synthetically generating a buttonPressEvent for wjatever view is underneath.
      Returns the view which precessed the event or nil."
 
@@ -6578,22 +6615,22 @@
 !
 
 simulateUserEvent:ev at:aPoint
-    "simulate a button press by determining which sub-view is affected and 
+    "simulate a button press by determining which sub-view is affected and
      synthetically generating a buttonPressEvent for wjatever view is underneath.
      Returns the view which precessed the event or nil."
 
     ((0@0 corner:self extent) containsPoint:aPoint) ifTrue:[
-        self subViews do:[:each |
-            |whichView|
-
-            whichView := each simulateUserEvent:ev at:(device translatePoint:aPoint fromView:self toView:each).
-            whichView notNil ifTrue:[^ whichView].
-        ].
-        ev x:aPoint x.
-        ev y:aPoint y.
-        ev view:self.
-        self sensor pushEvent:ev.
-        ^ self
+	self subViews do:[:each |
+	    |whichView|
+
+	    whichView := each simulateUserEvent:ev at:(self graphicsDevice translatePoint:aPoint fromView:self toView:each).
+	    whichView notNil ifTrue:[^ whichView].
+	].
+	ev x:aPoint x.
+	ev y:aPoint y.
+	ev view:self.
+	self sensor pushEvent:ev.
+	^ self
     ].
     ^ nil
 
@@ -6617,7 +6654,7 @@
 	    ]
 	] newProcess.
 
-    device buttonLongPressedHandlerProcess:p.
+    self graphicsDevice buttonLongPressedHandlerProcess:p.
     p resume.
 !
 
@@ -6626,9 +6663,9 @@
 
     |p|
 
-    (p := device buttonLongPressedHandlerProcess) notNil ifTrue:[
+    (p := self graphicsDevice buttonLongPressedHandlerProcess) notNil ifTrue:[
 "/ Transcript showCR:'stop'.
-	device buttonLongPressedHandlerProcess:nil.
+	self graphicsDevice buttonLongPressedHandlerProcess:nil.
 	p terminate.
     ].
 ! !
@@ -6695,16 +6732,16 @@
     index == 0 ifTrue:[ ^ nil ].
 
     subviewsInFocusOrder from:(index + 1) do:[:eachChildAfterTheOne |
-        eachChildAfterTheOne shown ifTrue:[
-            (eachChildAfterTheOne canTab 
-            and:[eachChildAfterTheOne enabled]) ifTrue:[
-                ^ eachChildAfterTheOne
-            ].
-
-            (viewInSubView := eachChildAfterTheOne focusNext) notNil ifTrue:[
-                ^ viewInSubView
-            ].
-        ].
+	eachChildAfterTheOne shown ifTrue:[
+	    (eachChildAfterTheOne canTab
+	    and:[eachChildAfterTheOne enabled]) ifTrue:[
+		^ eachChildAfterTheOne
+	    ].
+
+	    (viewInSubView := eachChildAfterTheOne focusNext) notNil ifTrue:[
+		^ viewInSubView
+	    ].
+	].
     ].
     ^ nil
 !
@@ -6716,15 +6753,15 @@
     |viewInSubView|
 
     self subviewsInFocusOrder do:[:aSubView|
-        (aSubView canTab
-        and:[aSubView enabled
-        and:[aCondition value:aSubView]]) ifTrue:[
-            ^ aSubView
-        ].
-
-        (viewInSubView := aSubView focusNextForWhich:aCondition) notNil ifTrue:[
-            ^ viewInSubView
-        ]
+	(aSubView canTab
+	and:[aSubView enabled
+	and:[aCondition value:aSubView]]) ifTrue:[
+	    ^ aSubView
+	].
+
+	(viewInSubView := aSubView focusNextForWhich:aCondition) notNil ifTrue:[
+	    ^ viewInSubView
+	]
     ].
     ^ nil
 !
@@ -6813,7 +6850,7 @@
 
     "/ Transcript show:'take: '; showCR:self.
     windowGroup notNil ifTrue:[
-        ^ windowGroup focusRequestFrom:self
+	^ windowGroup focusRequestFrom:self
     ].
     "/ Transcript show:'oops: '; showCR:self.
     ^ true
@@ -6850,30 +6887,30 @@
     |delta clrId bd|
 
     explicit ifTrue:[
-	(drawableId notNil
+	(self drawableId notNil
 	and:[superView notNil
 	and:[styleSheet notNil]]) ifTrue:[
 	    (styleSheet at:#'focus.showBorder' default:true) ifTrue:[
-		(device supportsWindowBorder:(bd := DefaultFocusBorderWidth)) ifFalse:[
-		    (device supportsWindowBorder:(bd := 1)) ifFalse:[
+		(self graphicsDevice supportsWindowBorder:(bd := DefaultFocusBorderWidth)) ifFalse:[
+		    (self graphicsDevice supportsWindowBorder:(bd := 1)) ifFalse:[
 			bd := 0.
 		    ]
 		].
 		delta := bd - self borderWidth.
 		delta ~~ 0 ifTrue:[
 		    (left == 0 or:[top == 0]) ifTrue:[
-			device resizeWindow:drawableId width:width-delta-delta height:height-delta-delta.
+			self graphicsDevice resizeWindow:self drawableId width:width-delta-delta height:height-delta-delta.
 		    ] ifFalse:[
-			device moveWindow:drawableId x:left-delta y:top-delta.
+			self graphicsDevice moveWindow:self drawableId x:left-delta y:top-delta.
 		    ].
-		    device setWindowBorderWidth:bd in:drawableId.
+		    self graphicsDevice setWindowBorderWidth:bd in:self drawableId.
 		].
 
-		clrId := (DefaultFocusColor onDevice:device) colorId.
+		clrId := (DefaultFocusColor onDevice:self graphicsDevice) colorId.
 		clrId isNil ifTrue:[
-		    clrId := device blackpixel
+		    clrId := self graphicsDevice blackpixel
 		].
-		device setWindowBorderColor:clrId in:drawableId.
+		self graphicsDevice setWindowBorderColor:clrId in:self drawableId.
 	    ]
 	]
     ] ifFalse:[
@@ -6894,18 +6931,18 @@
     |delta bd|
 
     explicit ifTrue:[
-	(drawableId notNil and:[superView notNil]) ifTrue:[
+	(self drawableId notNil and:[superView notNil]) ifTrue:[
 	    (styleSheet at:#'focus.showBorder' default:true) ifTrue:[
-		(device supportsWindowBorder:(bd := self borderWidth)) ifFalse:[
-		    (device supportsWindowBorder:(bd := 1)) ifFalse:[
+		(self graphicsDevice supportsWindowBorder:(bd := self borderWidth)) ifFalse:[
+		    (self graphicsDevice supportsWindowBorder:(bd := 1)) ifFalse:[
 			bd := 0.
 		    ]
 		].
 		delta := DefaultFocusBorderWidth - bd.
 		delta ~~ 0 ifTrue:[
-		    device setWindowBorderWidth:bd in:drawableId.
-		    device moveWindow:drawableId x:left y:top.
-		    device resizeWindow:drawableId width:width height:height.
+		    self graphicsDevice setWindowBorderWidth:bd in:self drawableId.
+		    self graphicsDevice moveWindow:self drawableId x:left y:top.
+		    self graphicsDevice resizeWindow:self drawableId width:width height:height.
 		].
 		self setBorderColor.
 	    ]
@@ -6964,10 +7001,10 @@
 wantsFocusWithButtonPress
     "views which do not like to take the keyboard focus
      with buttonPress can do so by redefining this
-     to return false 
+     to return false
      (actually: they should, because it is quite annoying
       in the UI if a menuPanel or button takes my keyboard focus.
-      So we should onsider making the default false here, so every 
+      So we should onsider making the default false here, so every
       widget writer has to think twice...
       Can we do such a major change?)"
 
@@ -6993,15 +7030,13 @@
 forceUngrabKeyboard
     "force a keyboard ungrab - even if was not the grabber"
 
-    device ungrabKeyboard.
-
+    self graphicsDevice ungrabKeyboard.
 !
 
 forceUngrabPointer
     "force a pointer ungrab - even if was not the grabber"
 
-    device ungrabPointer
-
+    self graphicsDevice ungrabPointer
 !
 
 grabKeyboard
@@ -7010,7 +7045,7 @@
      Returns true, if the grab was sucessfull (could fail, if some other
      application has a grab - but thats very unlikely)."
 
-    ^ device grabKeyboardInView:self.
+    ^ self graphicsDevice grabKeyboardInView:self.
 !
 
 grabPointer
@@ -7039,10 +7074,10 @@
 "/    ].
 
     aCursorOrNil notNil ifTrue:[
-	cursor := (aCursorOrNil onDevice:device).
-	^ device grabPointerInView:self withCursor:cursor
-    ].
-    ^ device grabPointerInView:self
+	cursor := (aCursorOrNil onDevice:self graphicsDevice).
+	^ self graphicsDevice grabPointerInView:self withCursor:cursor
+    ].
+    ^ self graphicsDevice grabPointerInView:self
 !
 
 ungrabKeyboard
@@ -7050,17 +7085,16 @@
 
     |sensor|
 
-    device activeKeyboardGrab == self ifTrue:[
+    self graphicsDevice activeKeyboardGrab == self ifTrue:[
 	(sensor := self sensor) notNil ifTrue:[
 	    "/ make certain all X events have been received
-	    device sync.
+	    self graphicsDevice sync.
 	    "/ now all events have been received.
 	    "/ now, flush all pointer events
 	    sensor flushKeyboardFor:self
 	].
-	device ungrabKeyboard.
-    ].
-
+	self graphicsDevice ungrabKeyboard.
+    ].
 !
 
 ungrabPointer
@@ -7068,15 +7102,15 @@
 
     |sensor|
 
-    device activePointerGrab == self ifTrue:[
+    self graphicsDevice activePointerGrab == self ifTrue:[
 	(sensor := self sensor) notNil ifTrue:[
 	    "/ make certain all X events have been received
-	    device sync.
+	    self graphicsDevice sync.
 	    "/ now all events have been received.
 	    "/ now, flush all pointer events
 	    sensor flushMotionEventsFor:self
 	].
-	device ungrabPointer.
+	self graphicsDevice ungrabPointer.
     ]
 ! !
 
@@ -7207,7 +7241,7 @@
     DefaultLightColor notNil ifTrue:[
 	lightColor := DefaultLightColor.
     ] ifFalse:[
-	device hasGrayscales ifTrue:[
+	self graphicsDevice hasGrayscales ifTrue:[
 	    (viewBackground isImageOrForm and:[viewBackground colorMap isNil]) ifTrue:[
 		lightColor := viewBackground averageColor lightened.
 	    ] ifFalse:[
@@ -7226,7 +7260,7 @@
     DefaultShadowColor notNil ifTrue:[
 	shadowColor := DefaultShadowColor.
     ] ifFalse:[
-	shadowColor := Black
+	shadowColor := self blackColor.
     ].
 
     ((DefaultBorderWidth ? 1) ~= 0 and:[DefaultBorderColor notNil]) ifTrue:[
@@ -7234,7 +7268,7 @@
     ].
 
     "/ font := self defaultFont.  -- already done in #initialize
-    font := font onDevice:device.
+    gc createFontOnDevice.
 
     "Modified: 28.5.1996 / 21:13:58 / cg"
 !
@@ -7276,7 +7310,7 @@
 
     super initialize.
 
-    font := self defaultFont onDevice:device.
+    self basicFont:self defaultFont.
 
     shown := realized := false.
     "/ hiddenOnRealize := false.
@@ -7331,7 +7365,7 @@
 prepareForReinit
     super prepareForReinit.
     windowGroup notNil ifTrue:[
-	windowGroup reinitialize
+        windowGroup reinitialize
     ]
 !
 
@@ -7341,12 +7375,12 @@
     |t|
 
     self initStyle.
-    (drawableId notNil and:[gcId notNil]) ifTrue:[
-	"force a change"
-	t := self borderWidth. self borderWidth:nil. self borderWidth:t.
-	t := viewBackground. viewBackground := nil. self viewBackground:t.
-	self clearView.
-	self invalidate.
+    (self drawableId notNil and:[self gcId notNil]) ifTrue:[
+        "force a change"
+        t := self borderWidth. self borderWidth:nil. self borderWidth:t.
+        t := viewBackground. viewBackground := nil. self viewBackground:t.
+        self clearView.
+        self invalidate.
     ].
 
     "Modified: / 18.9.1998 / 21:15:33 / cg"
@@ -7358,7 +7392,7 @@
     |myController sv|
 
     "if I have already been reinited - return"
-    drawableId notNil ifTrue:[
+    self drawableId notNil ifTrue:[
 	^ self
     ].
 
@@ -7384,10 +7418,10 @@
 	 a hidden iconView or menu ..."
 	superView notNil ifTrue:[
 "/            shown ifTrue:[
-	    device
-		moveResizeWindow:drawableId x:left y:top width:width height:height;
-		mapWindow:drawableId
-"/                mapView:self id:drawableId iconified:false
+	    self graphicsDevice
+		moveResizeWindow:self drawableId x:left y:top width:width height:height;
+		mapWindow:self drawableId
+"/                mapView:self id:self drawableId iconified:false
 "/                atX:left y:top width:width height:height
 "/                minExtent:(self minExtent) maxExtent:(self maxExtent)
 "/            ].
@@ -7468,19 +7502,19 @@
     key := aKeyEvent key.
     rawKey := aKeyEvent rawKey.
     (shown and:[ subViews notNil ]) ifTrue:[
-        subViews do:[:aSubView |
-            aSubView shown ifTrue:[
-                (aSubView enabled
-                    and:[ (mnemonic := aSubView mnemonicKey) notNil
-                    and:[ (mnemonic == rawKey or:[ mnemonic == key ]) ]])
-                ifTrue:[ 
-                    ^ aSubView 
-                ].
-                (view := aSubView mnemonicViewNext:aKeyEvent) notNil ifTrue:[
-                    ^ view
-                ].
-            ]
-        ]
+	subViews do:[:aSubView |
+	    aSubView shown ifTrue:[
+		(aSubView enabled
+		    and:[ (mnemonic := aSubView mnemonicKey) notNil
+		    and:[ (mnemonic == rawKey or:[ mnemonic == key ]) ]])
+		ifTrue:[
+		    ^ aSubView
+		].
+		(view := aSubView mnemonicViewNext:aKeyEvent) notNil ifTrue:[
+		    ^ view
+		].
+	    ]
+	]
     ].
     ^ nil
 
@@ -7781,30 +7815,30 @@
 !
 
 computeInnerClip
-    "compute, but do not set the inside clip-area"
+    "compute, but do not set the inside clip-area, in device coordinates"
 
     |m2 nX nY nW nH|
 
     margin isNil ifTrue:[margin := 0].
     (margin ~~ 0) ifTrue:[
-	m2 := margin + margin.
-	nX := nY := margin.
-	nW := width - m2.
-	nH := height - m2.
+        m2 := margin + margin.
+        nX := nY := margin.
+        nW := width - m2.
+        nH := height - m2.
 "/        transformation notNil ifTrue:[
 "/            nX := transformation applyInverseToX:nX.
 "/            nY := transformation applyInverseToY:nY.
 "/            nW := transformation applyInverseScaleX:nW.
 "/            nH := transformation applyInverseScaleY:nH.
 "/        ].
-	innerClipRect := Rectangle
-				 left:nX
-				 top:nY
-				 width:nW
-				 height:nH
+        innerClipRect := Rectangle
+                                 left:nX
+                                 top:nY
+                                 width:nW
+                                 height:nH
     ] ifFalse:[
-	"no clipping"
-	innerClipRect := nil
+        "no clipping"
+        innerClipRect := nil
     ]
 
     "Modified: / 22.5.1999 / 16:50:58 / cg"
@@ -7869,7 +7903,7 @@
 		 and:[aPoint y between:(v top)  and:(v bottom)]
 		) ifTrue:[
 		    "/ found a subview - the point is there
-		    p := device translatePoint:aPoint fromView:self toView:v.
+		    p := self graphicsDevice translatePoint:aPoint fromView:self toView:v.
 		    ^ v detectViewAt:p ignoreInvisible:ignoreInvisible.
 		]
 	    ]
@@ -7905,7 +7939,7 @@
     bw := self borderWidth ? 0.
 
     superView isNil ifTrue:[
-	inRect := 0@0 extent:device extent
+	inRect := 0@0 extent:self graphicsDevice extent
     ] ifFalse:[
 	inRect := superView viewRectangle.
     ].
@@ -8033,8 +8067,8 @@
 	"/ no, have to do it if drawableId is there
 	"/ (otherwise, we could not move unmapped views around ...
 	"/
-	drawableId notNil ifTrue:[
-	    device moveWindow:drawableId x:left y:top
+	self drawableId notNil ifTrue:[
+	    self graphicsDevice moveWindow:self drawableId x:left y:top
 	] ifFalse:[
 	    self originChangedFlag:true
 	]
@@ -8090,7 +8124,7 @@
     left := newLeft.
 
 "/    shown ifTrue:[                  "4-nov-94 actually correct,"
-    drawableId notNil ifTrue:[        "but theres a bug in menus when resized while hidden"
+    self drawableId notNil ifTrue:[        "but theres a bug in menus when resized while hidden"
 	mustRedrawBottomEdge := (margin ~~ 0) and:[newHeight < height].
 	mustRedrawRightEdge := (margin ~~ 0) and:[newWidth < width].
 
@@ -8115,7 +8149,7 @@
 		oldPaint := nil.
 		newWidth > width ifTrue:[
 		    self clippingRectangle:nil.
-		    oldPaint := paint.
+		    oldPaint := self paint.
 		    self paint:viewBackground.
 		    self fillDeviceRectangleX:(width - margin)
 					    y:0
@@ -8125,7 +8159,7 @@
 		].
 		newHeight > height ifTrue:[
 		    self clippingRectangle:nil.
-		    oldPaint := paint.
+		    oldPaint := self paint.
 		    self paint:viewBackground.
 		    self fillDeviceRectangleX:0
 					    y:(height - margin)
@@ -8149,20 +8183,19 @@
 
 	"have to tell X, when extent of view is changed"
 	sameOrigin ifTrue:[
-	    device resizeWindow:drawableId width:width height:height.
-
+	    self graphicsDevice resizeWindow:self drawableId width:width height:height.
 	] ifFalse:[
 	    "claus: some xservers seem to do better when resizing
 	     first ...."
 "
 	    (how == #smaller) ifTrue:[
-		device resizeWindow:drawableId width:width height:height.
-		device moveWindow:drawableId x:left y:top
+		self graphicsDevice resizeWindow:drawableId width:width height:height.
+		self graphicsDevice moveWindow:drawableId x:left y:top
 	    ] ifFalse:[
-		device moveResizeWindow:drawableId x:left y:top width:width height:height
+		self graphicsDevice moveResizeWindow:drawableId x:left y:top width:width height:height
 	    ].
 "
-	    device moveResizeWindow:drawableId x:left y:top
+	    self graphicsDevice moveResizeWindow:self drawableId x:left y:top
 					   width:width height:height.
 	].
 
@@ -8182,7 +8215,7 @@
 		    ].
 		] ifFalse:[
 		    self deviceClippingRectangle:nil.
-		    oldPaint := paint.
+		    oldPaint := self paint.
 		    mustRedrawBottomEdge ifTrue:[
 			self drawBottomEdge
 		    ].
@@ -8241,8 +8274,8 @@
     bw := self borderWidth ? 0.
 
     superView isNil ifTrue:[
-	superWidth := device width + bw.
-	superHeight := device height + bw.
+	superWidth := self graphicsDevice width + bw.
+	superHeight := self graphicsDevice height + bw.
 	superLeft := superTop := 0.
     ] ifFalse:[
 	inRect := superView viewRectangle.
@@ -8307,7 +8340,7 @@
     "compute, and set the inside clip-area"
 
     self computeInnerClip.
-    self deviceClippingRectangle:innerClipRect.
+    self clippingBounds:innerClipRect.
 
     "Modified: / 25.5.1999 / 14:45:53 / cg"
 !
@@ -8321,10 +8354,10 @@
     |form|
 
     (form := viewShape borderShapeForm) notNil ifTrue:[
-        self windowBorderShape:form.
+        gc windowBorderShape:form.
     ].
     (form := viewShape viewShapeForm) notNil ifTrue:[
-        self windowShape:form.
+        gc windowShape:form.
     ].
 
     "Created: 18.9.1997 / 11:09:00 / cg"
@@ -8349,22 +8382,22 @@
     "/ focusViewInWindowGroup := windowGroup focusView.
     "/ focusViewToCheck := focusViewInWindowGroup.
 
-    focusViewOnDisplay := device focusView.
+    focusViewOnDisplay := self graphicsDevice focusView.
     focusViewToCheck := focusViewOnDisplay.
 
     focusViewToCheck == self ifTrue:[ ^ true ].
 
     focusViewToCheck notNil ifTrue:[
-        (focusViewToCheck isComponentOf: self) ifTrue:[ ^ true ].
-
-        "mhmh - is there a delegation to me ?"
-        (delegate := focusViewToCheck delegate) notNil ifTrue:[
-            delegate == self ifTrue:[^ true].
-            "/ no: delegate does not understand this (EnterFieldGroup or KbdForwarder)
-            "/ we will see, if commenting this leads to problems...
-            "/ (delegate isComponentOf: self) ifTrue:[ ^ true ].
-            ^ delegate askFor:#delegatesTo: with:self
-        ]
+	(focusViewToCheck isComponentOf: self) ifTrue:[ ^ true ].
+
+	"mhmh - is there a delegation to me ?"
+	(delegate := focusViewToCheck delegate) notNil ifTrue:[
+	    delegate == self ifTrue:[^ true].
+	    "/ no: delegate does not understand this (EnterFieldGroup or KbdForwarder)
+	    "/ we will see, if commenting this leads to problems...
+	    "/ (delegate isComponentOf: self) ifTrue:[ ^ true ].
+	    ^ delegate askFor:#delegatesTo: with:self
+	]
     ].
     ^ false
 
@@ -8480,17 +8513,17 @@
     "/ focusViewInWindowGroup := windowGroup focusView.
     "/ focusViewToCheck := focusViewInWindowGroup.
 
-    focusViewOnDisplay := device focusView.
+    focusViewOnDisplay := self graphicsDevice focusView.
     focusViewToCheck := focusViewOnDisplay.
 
     focusViewToCheck == self ifTrue:[ ^ true ].
 
     focusViewToCheck notNil ifTrue:[
-        "mhmh - is there a delegation to me ?"
-        (delegate := focusViewToCheck delegate) notNil ifTrue:[
-            delegate == self ifTrue:[^ true].
-            ^ delegate askFor:#delegatesTo: with:self
-        ]
+	"mhmh - is there a delegation to me ?"
+	(delegate := focusViewToCheck delegate) notNil ifTrue:[
+	    delegate == self ifTrue:[^ true].
+	    ^ delegate askFor:#delegatesTo: with:self
+	]
     ].
     ^ false
 
@@ -8559,6 +8592,12 @@
 
 !
 
+isICCCWindowGroupWindow
+    "needed for checkForEndOfDispatch"
+
+    ^ false
+!
+
 isInputField
     "return true, if the receiver is some kind of input view,
      i.e. it should (can) be part of an enterGroup.
@@ -8676,10 +8715,10 @@
     newBits := flagBits bitClear:(FlagOriginChanged bitOr: FlagExtentChanged).
 
     originChanged ifTrue:[
-        newBits := newBits bitOr:FlagOriginChanged
+	newBits := newBits bitOr:FlagOriginChanged
     ].
     extentChanged ifTrue:[
-        newBits := newBits bitOr:FlagExtentChanged
+	newBits := newBits bitOr:FlagExtentChanged
     ].
 
     flagBits := newBits.
@@ -8691,13 +8730,13 @@
     newBits := flagBits bitClear:((FlagOriginChanged bitOr: FlagExtentChanged) bitOr: FlagCornerChanged).
 
     originChanged ifTrue:[
-        newBits := newBits bitOr:FlagOriginChanged
+	newBits := newBits bitOr:FlagOriginChanged
     ].
     extentChanged ifTrue:[
-        newBits := newBits bitOr:FlagExtentChanged
+	newBits := newBits bitOr:FlagExtentChanged
     ].
     cornerChanged ifTrue:[
-        newBits := newBits bitOr:FlagCornerChanged
+	newBits := newBits bitOr:FlagCornerChanged
     ].
 
     flagBits := newBits.
@@ -8880,7 +8919,7 @@
 
     myClass := self class.
     (myClass == View or:[myClass == SimpleView]) ifTrue:[
-        ^ ViewSpec "/ CompositeSpecCollection
+	^ ViewSpec "/ CompositeSpecCollection
     ].
 
     "/ try: appending 'Spec' to my classes name
@@ -8888,8 +8927,8 @@
     myName := self class name.
     cls := Smalltalk classNamed:(myName , 'Spec').
     cls notNil ifTrue:[
-        cls := cls autoload.
-        (cls isSubclassOf:UISpecification) ifTrue:[^ cls].
+	cls := cls autoload.
+	(cls isSubclassOf:UISpecification) ifTrue:[^ cls].
     ].
 
     (myName endsWith:'View') ifTrue:[
@@ -8900,12 +8939,12 @@
 "/            (cls isSubclassOf:UISpecification) ifTrue:[^ cls].
 "/        ].
 
-        "/ try with 'View' replaced by 'Spec'
-        cls := Smalltalk classNamed:((myName copyButLast:4) , 'View').
-        cls notNil ifTrue:[
-            cls := cls autoload.
-            (cls isSubclassOf:UISpecification) ifTrue:[^ cls].
-        ]
+	"/ try with 'View' replaced by 'Spec'
+	cls := Smalltalk classNamed:((myName copyButLast:4) , 'View').
+	cls notNil ifTrue:[
+	    cls := cls autoload.
+	    (cls isSubclassOf:UISpecification) ifTrue:[^ cls].
+	]
     ].
 
     "/ fall back for all others
@@ -8959,7 +8998,7 @@
     "create (i.e. tell my device about me) if not already created.
      This does not make the view visible (needs a #map for that)"
 
-    drawableId isNil ifTrue:[
+    self drawableId isNil ifTrue:[
 	"
 	 make certain that superview is created also
 	"
@@ -8977,11 +9016,11 @@
 	    "/ if the display is not already dispatching events,
 	    "/ this starts the event process.
 	    "/
-	    device startDispatch
+	    self graphicsDevice startDispatch
 	].
 
 	cursor notNil ifTrue:[
-	    cursor := cursor onDevice:device.
+	    cursor := cursor onDevice:self graphicsDevice.
 	].
 
 	self extentChangedBeforeCreatedFlag ifTrue:[
@@ -9016,7 +9055,7 @@
 createWithAllSubViews
     "create, then create all subviews"
 
-    drawableId isNil ifTrue:[self create].
+    self drawableId isNil ifTrue:[self create].
     subViews notNil ifTrue:[
 	subViews do:[:subView | subView createWithAllSubViews]
     ]
@@ -9033,8 +9072,8 @@
      If you redefine this method, make certain that 'super fetchDeviceResources'
      is always sent."
 
-    shadowColor notNil ifTrue:[shadowColor := shadowColor onDevice:device].
-    lightColor notNil ifTrue:[lightColor := lightColor onDevice:device].
+    shadowColor notNil ifTrue:[shadowColor := shadowColor onDevice:self graphicsDevice].
+    lightColor notNil ifTrue:[lightColor := lightColor onDevice:self graphicsDevice].
 
     "Created: 13.1.1997 / 21:51:59 / cg"
 !
@@ -9080,7 +9119,7 @@
 		self originFromRelativeOrigin:relativeOrigin
 	    ] ifFalse:[
 		shown ifTrue:[
-		    device moveWindow:drawableId x:left y:top.
+		    self graphicsDevice moveWindow:self drawableId x:left y:top.
 		] ifFalse:[
 		    self pixelOrigin:left@top
 		].
@@ -9107,24 +9146,24 @@
 
     realized ifFalse:[^ self].
     (windowGroup notNil and:[windowGroup isModal]) ifTrue:[
-        masterGroup := windowGroup previousGroup.
-        windowGroup focusView:nil.
+	masterGroup := windowGroup previousGroup.
+	windowGroup focusView:nil.
     ].
 
     self unmap.
-    device flush.
+    self flush.
 
     masterGroup notNil ifTrue:[
-        "
-         this is a kludge for IRIS and others which do not provide backingstore:
-         when we hide a modalbox (such as a searchbox) which covered
-         a scrollbar, the scrollbars bitblt-method will copy from the
-         not-yet redrawn area - effectively clearing the scroller.
-         We need a short delay here, since at this time, the expose event has
-         not yet arrived.
-        "
-        Delay waitForSeconds:0.05.
-        masterGroup processExposeEvents
+	"
+	 this is a kludge for IRIS and others which do not provide backingstore:
+	 when we hide a modalbox (such as a searchbox) which covered
+	 a scrollbar, the scrollbars bitblt-method will copy from the
+	 not-yet redrawn area - effectively clearing the scroller.
+	 We need a short delay here, since at this time, the expose event has
+	 not yet arrived.
+	"
+	Delay waitForSeconds:0.05.
+	masterGroup processExposeEvents
     ].
 
 "/    WindowGroup leaveSignal raise.
@@ -9187,7 +9226,7 @@
     |subs|
 
     realized ifFalse:[
-	drawableId isNil ifTrue:[
+	self drawableId isNil ifTrue:[
 	    "
 	     first time ?
 	     yes, realize (implies a map)
@@ -9200,19 +9239,19 @@
 	    realized := true.
 	    aPoint isNil ifTrue:[
 		iconified ifTrue:[
-		    device
-			mapView:self id:drawableId iconified:iconified
+		    self graphicsDevice
+			mapView:self id:self drawableId iconified:iconified
 			atX:0 y:0
 			width:width height:height
 			minExtent:(self minExtent) maxExtent:(self maxExtent).
 		] ifFalse:[
-		    device mapWindow:drawableId.
+		    self graphicsDevice mapWindow:self drawableId.
 		]
 	    ] ifFalse:[
 		left := aPoint x.
 		top := aPoint y.
-		device
-		    mapView:self id:drawableId iconified:iconified
+		self graphicsDevice
+		    mapView:self id:self drawableId iconified:iconified
 		    atX:left y:top
 		    width:width height:height
 		    minExtent:(self minExtent) maxExtent:(self maxExtent).
@@ -9267,7 +9306,7 @@
 
     isInputOnly := self isInputOnly.
 
-    self
+    gc
       createWindowFor:self
       type:(self windowType)
       origin:(left @ top)
@@ -9283,8 +9322,6 @@
       icon:nil iconMask:nil
       iconView:nil.
 
-    Lobby registerChange:self.
-
     "/ if there is a global eventListener,
     "/ give it a chance to track views
 
@@ -9299,11 +9336,11 @@
 "/        ]
 "/    ].
     (viewGravity notNil "and:[viewGravity ~~ #NorthWest]") ifTrue:[
-        super viewGravity:viewGravity.
+        gc viewGravity:viewGravity.
     ].
     (bitGravity notNil "and:[bitGravity ~~ #NorthWest]") ifTrue:[
         isInputOnly ifFalse:[
-            super bitGravity:bitGravity.
+            gc bitGravity:bitGravity.
         ]
     ].
     viewShape notNil ifTrue:[
@@ -9407,9 +9444,9 @@
     "/ fetch device colors, to avoid reallocation at redraw time
     self fetchDeviceResources.
 
-    drawableId isNil ifTrue:[
+    self drawableId isNil ifTrue:[
 	self create.
-	drawableId isNil ifTrue:[
+	self drawableId isNil ifTrue:[
 	    ('SimpleView [warning]: could not create view: ' , self class name) errorPrintCR.
 	    ^ self
 	]
@@ -9511,7 +9548,7 @@
 recreate
     "recreate (i.e. tell X about me) after a snapin or a migration"
 
-    drawableId isNil ifTrue:[
+    self drawableId isNil ifTrue:[
 	super recreate.
 	self physicalCreate.
 
@@ -9525,9 +9562,9 @@
 	 XXX event masks must become symbolic
 	"
 	eventMask isNil ifTrue:[
-	    eventMask := device defaultEventMask
-	].
-	device setEventMask:eventMask in:drawableId
+	    eventMask := self graphicsDevice defaultEventMask
+	].
+	self graphicsDevice setEventMask:eventMask in:self drawableId
     ]
 !
 
@@ -9542,8 +9579,8 @@
 	 now, make the view visible
 	"
 	realized := true.
-	device
-	    mapView:self id:drawableId iconified:false
+	self graphicsDevice
+	    mapView:self id:self drawableId iconified:false
 	    atX:left y:top width:width height:height
 	    minExtent:(self minExtent) maxExtent:(self maxExtent)
     ]
@@ -9566,8 +9603,8 @@
 rerealizeInGroup:aWindowGroup
     "rerealize at old position in (a possibly different) windowGroup."
 
-    drawableId isNil ifTrue:[self create].
-    drawableId notNil ifTrue:[
+    self drawableId isNil ifTrue:[self create].
+    self drawableId notNil ifTrue:[
 	aWindowGroup ~~ windowGroup ifTrue:[
 	    windowGroup notNil ifTrue:[
 		windowGroup removeView:self
@@ -9585,17 +9622,17 @@
 rerealizeWithAllSubViews
     "rerealize myself with all subviews"
 
-    drawableId notNil ifTrue:[
+    self drawableId notNil ifTrue:[
 	realized := true.
 	self realizeAllSubViews.
 	superView isNil ifTrue:[
-	    device
-		mapView:self id:drawableId iconified:false
+	    self graphicsDevice
+		mapView:self id:self drawableId iconified:false
 		atX:left y:top width:width height:height
 		minExtent:(self minExtent) maxExtent:(self maxExtent)
 	] ifFalse:[
-	    device
-		mapWindow:drawableId
+	    self graphicsDevice
+		mapWindow:self drawableId
 	].
     ]
 
@@ -9629,12 +9666,12 @@
 
     realized ifTrue:[
 	realized := false.
-	drawableId notNil ifTrue:[
-	    device unmapWindow:drawableId.
+	self drawableId notNil ifTrue:[
+	    self graphicsDevice unmapWindow:self drawableId.
 
 	    "/ make it go away immediately
 	    "/ (this hides the subview killing)
-	    device flush.
+	    self flush.
 	].
 
 	"/ Normally, this is not correct with X, where the
@@ -9702,9 +9739,36 @@
      when problem or warning conditions arise.
      Someone may redefine this to flash its contents (instead of black/white)."
 
-    self fill:Black.
+    self flash:nil
+
+    "
+     |v|
+
+     v := View new openAndWait.
+     Delay waitForSeconds:2.
+     v flash.
+     Delay waitForSeconds:2.
+     v destroy
+    "
+
+    "Modified: / 16.7.1998 / 18:46:48 / cg"
+!
+
+flash:messageOrNil
+    "flash the view - fill it black, then white, finally
+     redraw completely.
+     Can be used to wakeup the user :-)
+     when problem or warning conditions arise.
+     Someone may redefine this to flash its contents (instead of black/white)."
+
+    self fill:self blackColor.
+    messageOrNil notNil ifTrue:[
+        self withForeground:Color white do:[
+            self displayString:messageOrNil centeredAt:(self center).
+        ].
+    ].
     Delay waitForSeconds:0.1.
-    self fill:White.
+    self fill:self whiteColor.
     Delay waitForSeconds:0.1.
     self fill:viewBackground.
 "/    self clear.
@@ -9723,6 +9787,12 @@
     "Modified: / 16.7.1998 / 18:46:48 / cg"
 !
 
+flashReadOnly
+    "flash the view and show 'Read Only' for a moment."
+
+    self flash:(resources string:'Read Only')
+!
+
 invalidate
     "add a damage to redraw the recevier to its input event queue.
      This is preferable to calling redraw directly, in that the drawing is done by
@@ -9768,7 +9838,7 @@
      damaged areas right now.
      The given rectangle is in logical coordinate space."
 
-    |r|
+    |r currentTransformation|
 
     shown ifFalse:[
 	"/ no need to add damage - will get a full-redraw anyway,
@@ -9777,8 +9847,9 @@
     ].
 
     r := aRectangle.
-    transformation notNil ifTrue:[
-	r := transformation applyTo:r.
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	r := currentTransformation applyTo:r.
     ].
     self invalidateDeviceRectangle:r repairNow:doRepairNow
 
@@ -9888,18 +9959,19 @@
      must inverse-transform back to logical coordinates. (since the view thinks
      in its coordinate space)"
 
-    |lx ly lw lh|
-
-    transformation isNil ifTrue:[
+    |lx ly lw lh currentTransformation|
+
+    currentTransformation := gc transformation.
+    currentTransformation isNil ifTrue:[
 	lx := x.
 	ly := y.
 	lw := w.
 	lh := h.
     ] ifFalse:[
-	lx := transformation applyInverseToX:x.
-	ly := transformation applyInverseToY:y.
-	lw := transformation applyInverseScaleX:w.
-	lh := transformation applyInverseScaleY:h.
+	lx := currentTransformation applyInverseToX:x.
+	ly := currentTransformation applyInverseToY:y.
+	lw := currentTransformation applyInverseScaleX:w.
+	lh := currentTransformation applyInverseScaleY:h.
     ].
     self redrawX:lx y:ly width:lw height:lh
 !
@@ -9915,12 +9987,12 @@
     shown ifFalse:[^ self].
 
     area := Rectangle left:x top:y width:w height:h.
-    oldClip := clipRect.
+    oldClip := gc clippingBoundsOrNil.
     self clippingRectangle:area.
 
     self clearExposedAreaInRedraw ifTrue:[
 	"/ win95 workaround: non-existing bg-pixmap support (obsolete)
-	(viewBackground isImageOrForm and:[ device supportsAnyViewBackgroundPixmaps not ]) ifTrue:[
+	(viewBackground isImageOrForm and:[ self graphicsDevice supportsAnyViewBackgroundPixmaps not ]) ifTrue:[
 	    self fillRectangleWithViewBackgroundX:x y:y width:w height:h
 	] ifFalse:[
 	    self clearRectangleX:x y:y width:w height:h.
@@ -9999,7 +10071,7 @@
     "return the amount to scroll when stepping left/right.
      Subclasses may want to redefine this."
 
-    ^ (device horizontalPixelPerMillimeter * 20) asInteger
+    ^ (self graphicsDevice horizontalPixelPerMillimeter * 20) asInteger
 !
 
 pageDown
@@ -10053,11 +10125,12 @@
 scrollHorizontalToPercent:percent
     "scroll to a position given in percent of total"
 
-    |wCont|
+    |wCont currentTransformation|
 
     wCont := self widthOfContents.
-    transformation notNil ifTrue:[
-	wCont := transformation applyScaleX:wCont.
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	wCont := currentTransformation applyScaleX:wCont.
     ].
     self scrollHorizontalTo:
 	    ((((wCont * percent) / 100.0) + 0.5) asInteger)
@@ -10135,16 +10208,17 @@
 scrollToPercent:originAsPercent
     "scroll to a position given in percent of total (x and y as a Point)"
 
-    |wCont hCont percent|
+    |wCont hCont percent currentTransformation|
 
     percent := originAsPercent asPoint.
 
     wCont := self widthOfContents.
     hCont := self heightOfContents.
 
-    transformation notNil ifTrue:[
-	wCont := transformation applyScaleX:wCont.
-	hCont := transformation applyScaleY:hCont.
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	wCont := currentTransformation applyScaleX:wCont.
+	hCont := currentTransformation applyScaleY:hCont.
     ].
     self scrollTo:
 	    ((((wCont * percent x) / 100.0) + 0.5) asInteger) @
@@ -10157,14 +10231,14 @@
 scrollToRight
     "move viewOrigin to the right"
 
-    |wCont|
+    |wCont currentTransformation|
 
     wCont := self widthOfContents.
-    transformation notNil ifTrue:[
-	wCont := transformation applyScaleX:wCont.
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	wCont := currentTransformation applyScaleX:wCont.
     ].
     self scrollHorizontalTo:((wCont - self innerWidth) max:0)
-
 !
 
 scrollToTop
@@ -10208,11 +10282,12 @@
 scrollVerticalToPercent:percent
     "scroll to a position given in percent of total"
 
-    |hCont|
+    |hCont currentTransformation|
 
     hCont := self heightOfContents.
-    transformation notNil ifTrue:[
-	hCont := transformation applyScaleY:hCont.
+    currentTransformation := gc transformation.
+    currentTransformation notNil ifTrue:[
+	hCont := currentTransformation applyScaleY:hCont.
     ].
     self scrollVerticalTo:
 	    ((((hCont * percent) / 100.0) + 0.5) asInteger)
@@ -10222,7 +10297,7 @@
     "return the amount to scroll when stepping up/down (also used for mouseWheel).
      Subclasses may want to redefine this."
 
-    ^ (device verticalPixelPerMillimeter * 20) asInteger
+    ^ (self graphicsDevice verticalPixelPerMillimeter * 20) asInteger
 !
 
 widthForScrollBetween:yStart and:yEnd
@@ -10260,19 +10335,6 @@
 	allowScrollBeyondContents:false
 !
 
-scrollTo:newOrigin redraw:doRedraw allowScrollBehondContents:allowScrollBehondContents
-    <resource: #obsolete>
-    "change origin to have newOrigin be visible at the top-left.
-     The argument defines the integer device coordinates of the new top-left
-     point."
-
-    self obsoleteMethodWarning:'use #scrollTo:redraw:allowScrollBeyondContents:'.
-    ^ self
-        scrollTo:newOrigin redraw:doRedraw allowScrollBeyondContents:allowScrollBehondContents
-
-    "Modified: / 07-03-2012 / 14:05:06 / cg"
-!
-
 scrollTo:newOrigin redraw:doRedraw allowScrollBeyondContents:allowScrollBehondContents
     "change origin to have newOrigin be visible at the top-left.
      The argument defines the integer device coordinates of the new top-left
@@ -10284,17 +10346,18 @@
      orgY
      x y iw ih
      hCont wCont fromX toX fromY toY copyWidth copyHeight
-     redrawX redrawY wg|
+     redrawX redrawY wg currentTransformation|
 
     hCont := self heightOfContents.
     wCont := self widthOfContents.
-    transformation isNil ifTrue:[
+    currentTransformation := gc transformation.
+    currentTransformation isNil ifTrue:[
 	orgY := orgX := 0
     ] ifFalse:[
-	wCont := (transformation applyScaleX:wCont) rounded.
-	hCont := (transformation applyScaleY:hCont) rounded.
-	orgY := transformation translation y negated.
-	orgX := transformation translation x negated
+	wCont := (currentTransformation applyScaleX:wCont) rounded.
+	hCont := (currentTransformation applyScaleY:hCont) rounded.
+	orgY := currentTransformation translation y negated.
+	orgX := currentTransformation translation x negated
     ].
 
     iw := self innerWidth.
@@ -10616,8 +10679,8 @@
 
     isPopup := self isPopUpView.
     aWindowGroup notNil ifTrue:[
-        mainGroup := aWindowGroup mainGroup.
-        mainView := mainGroup mainView.
+	mainGroup := aWindowGroup mainGroup.
+	mainView := mainGroup mainView.
     ].
 
     "/ set the windowgroup BEFORE sending the aboutToOpen notification
@@ -10625,139 +10688,139 @@
     "/ this allows for the handler to enqueue an event,
     "/ or to add event hooks.
     Processor activeProcessIsSystemProcess ifTrue:[
-        "
-         put myself into the modal group, let it handle events for
-         me as well. This is only a half way solution, since the view
-         is not modal at all ... however, the only situation
-         where this happens is with modal boxes popped while in a
-         modal browser. You will forgive me for that inconvenience.
-        "
-        windowGroup := aWindowGroup.
-        aWindowGroup notNil ifTrue:[aWindowGroup addTopView:self].
+	"
+	 put myself into the modal group, let it handle events for
+	 me as well. This is only a half way solution, since the view
+	 is not modal at all ... however, the only situation
+	 where this happens is with modal boxes popped while in a
+	 modal browser. You will forgive me for that inconvenience.
+	"
+	windowGroup := aWindowGroup.
+	aWindowGroup notNil ifTrue:[aWindowGroup addTopView:self].
     ] ifFalse:[
-        previousGroup := WindowGroup activeGroup.
-
-        "/ create a new window group put myself into it 
-        windowGroup := self windowGroupClass new
-                                addTopView:self;
-                                setPreviousGroup:previousGroup.
-
-        superView notNil ifTrue:[
-            "/
-            "/ special: this is a modal subview,
-            "/ prevent the view from reassigning its windowGroup when realized
-            "/ (subviews normaly place themself into the superviews group)
-            "/
-            windowGroup isForModalSubview:true.
-        ].
+	previousGroup := WindowGroup activeGroup.
+
+	"/ create a new window group put myself into it
+	windowGroup := self windowGroupClass new
+				addTopView:self;
+				setPreviousGroup:previousGroup.
+
+	superView notNil ifTrue:[
+	    "/
+	    "/ special: this is a modal subview,
+	    "/ prevent the view from reassigning its windowGroup when realized
+	    "/ (subviews normaly place themself into the superviews group)
+	    "/
+	    windowGroup isForModalSubview:true.
+	].
     ].
 
     makeTransient := true.
     isPopup ifFalse:[
-        "/ the following allows for knowledgable programmers to suppress dialog boxes,
-        "/ or to patch common controls right before opening...
-        (Dialog aboutToOpenBoxNotificationSignal raiseRequestWith:self) == #abort ifTrue:[
-            ^ self
-        ].
-        "/ the following allows for hooks to add a bell sound or other whenever a dialog opens
-        device modalWindowListenersDo:[:listener | listener aboutToOpenWindow:self].
-
-        "/ the following raises the corresponding mainview, so the dialog shows above
-        "/ any currently covered view. However, be careful if being debugged, or if this dialog
-        "/ is opened by an already open dialog.
-        mainView notNil ifTrue:[
-            (mainView windowGroup isInModalLoop 
-                or:[ mainView windowGroup isDebugged 
-                or:[ WindowGroup activeGroup isDebugged 
-            ]]) ifFalse:[
-                self tracePoint:#cg message:'activate'.
-                self debuggingCodeFor:#cg is:[ Transcript showCR:mainView; showCR:mainView windowGroup. ].
-                mainView activate; setForegroundWindow.
-            ] ifTrue:[
-                makeTransient := false.
-            ]
-        ].
+	"/ the following allows for knowledgable programmers to suppress dialog boxes,
+	"/ or to patch common controls right before opening...
+	(Dialog aboutToOpenBoxNotificationSignal raiseRequestWith:self) == #abort ifTrue:[
+	    ^ self
+	].
+	"/ the following allows for hooks to add a bell sound or other whenever a dialog opens
+	self graphicsDevice modalWindowListenersDo:[:listener | listener aboutToOpenWindow:self].
+
+	"/ the following raises the corresponding mainview, so the dialog shows above
+	"/ any currently covered view. However, be careful if being debugged, or if this dialog
+	"/ is opened by an already open dialog.
+	mainView notNil ifTrue:[
+	    (mainView windowGroup isInModalLoop
+		or:[ mainView windowGroup isDebugged
+		or:[ WindowGroup activeGroup isDebugged
+	    ]]) ifFalse:[
+		self tracePoint:#cg message:'activate'.
+		self debuggingCodeFor:#cg is:[ Transcript showCR:mainView; showCR:mainView windowGroup. ].
+		mainView activate; setForegroundWindow.
+	    ] ifTrue:[
+		makeTransient := false.
+	    ]
+	].
     ].
     makeTransient ifTrue:[
-        mainView notNil ifTrue:[
-            "set the transient property.
-             This is currently used for X, to tell the Window Manager
-             That this view should be always on top of the mainView"
-            drawableId isNil ifTrue:[self create].
-            device setTransient:drawableId for:mainView id.
-        ]
+	mainView notNil ifTrue:[
+	    "set the transient property.
+	     This is currently used for X, to tell the Window Manager
+	     That this view should be always on top of the mainView"
+	    self drawableId isNil ifTrue:[self create].
+	    self graphicsDevice setTransient:self drawableId for:mainView id.
+	]
     ].
 
     self raise.
 
     Processor activeProcessIsSystemProcess ifTrue:[
-        self realize
+	self realize
     ] ifFalse:[
-        "
-         show a stop-cursor in the suspended window groups
-        "
-        (mainGroup notNil and:[isPopup not]) ifTrue:[
-            mainGroup showCursor:(Cursor stop).
-            previousGroup ~~ mainGroup ifTrue:[
-                previousGroup showCursor:(Cursor stop).
-            ].
-            cursorChanged := true.
-        ].
-
-        "
-         go dispatch events in this new group
-         (thus current windowgroup is blocked from interaction)
-        "
-        AbortOperationRequest handle:[:ex |
-            AbortOperationRequest handle:[:ex2 |
-                "/ an aborted hide (user confirmation ?)
-                self breakPoint:#cg.
-                ex exit.
-            ] do:[
-                self hide.
-                realized ifTrue:[
-                    "/ self halt. "/ hide handled and closeRequest not wanted:
-                    ex exit.
-                ].
-            ].
-        ] do:[
-            [
-                [
-                    windowGroup startupModal:[realized and:aBlock] forGroup:aWindowGroup
-                ] ifCurtailed:[
-                    self hide.
-                ]
-            ] ensure:[
-                aWindowGroup notNil ifTrue:[
-                    aWindowGroup graphicsDevice sync.  "thats a round trip - make sure that all drawing has been processed"
-                    "/ ensure that eventListener runs here ...
-                    Delay waitForSeconds:0.05.
-                    aWindowGroup processExposeEvents.
-
-                    (self isPopUpView or:[ ReturnFocusWhenClosingModalBoxes ]) ifTrue:[
-                        "
-                         return the input focus to the previously active group's top.
-                         This helps with window managers which need an explicit click
-                         on the view for the focus.
-                        "
-                        tops := aWindowGroup topViews.
-                        (tops notEmptyOrNil) ifTrue:[
-                            tops first getKeyboardFocus
-                        ].
-                    ].
-
-                    "
-                     restore cursors in the changed groups
-                    "
-                    cursorChanged notNil ifTrue:[
-                        mainGroup restoreCursors.
-                        previousGroup ~~ mainGroup ifTrue:[
-                            previousGroup restoreCursors.
-                        ].
-                    ].
-                ].
-            ]
-        ].
+	"
+	 show a stop-cursor in the suspended window groups
+	"
+	(mainGroup notNil and:[isPopup not]) ifTrue:[
+	    mainGroup showCursor:(Cursor stop).
+	    previousGroup ~~ mainGroup ifTrue:[
+		previousGroup showCursor:(Cursor stop).
+	    ].
+	    cursorChanged := true.
+	].
+
+	"
+	 go dispatch events in this new group
+	 (thus current windowgroup is blocked from interaction)
+	"
+	AbortOperationRequest handle:[:ex |
+	    AbortOperationRequest handle:[:ex2 |
+		"/ an aborted hide (user confirmation ?)
+		self breakPoint:#cg.
+		ex exit.
+	    ] do:[
+		self hide.
+		realized ifTrue:[
+		    "/ self halt. "/ hide handled and closeRequest not wanted:
+		    ex exit.
+		].
+	    ].
+	] do:[
+	    [
+		[
+		    windowGroup startupModal:[realized and:aBlock] forGroup:aWindowGroup
+		] ifCurtailed:[
+		    self hide.
+		]
+	    ] ensure:[
+		aWindowGroup notNil ifTrue:[
+		    aWindowGroup graphicsDevice sync.  "thats a round trip - make sure that all drawing has been processed"
+		    "/ ensure that eventListener runs here ...
+		    Delay waitForSeconds:0.05.
+		    aWindowGroup processExposeEvents.
+
+		    (self isPopUpView or:[ ReturnFocusWhenClosingModalBoxes ]) ifTrue:[
+			"
+			 return the input focus to the previously active group's top.
+			 This helps with window managers which need an explicit click
+			 on the view for the focus.
+			"
+			tops := aWindowGroup topViews.
+			(tops notEmptyOrNil) ifTrue:[
+			    tops first getKeyboardFocus
+			].
+		    ].
+
+		    "
+		     restore cursors in the changed groups
+		    "
+		    cursorChanged notNil ifTrue:[
+			mainGroup restoreCursors.
+			previousGroup ~~ mainGroup ifTrue:[
+			    previousGroup restoreCursors.
+			].
+		    ].
+		].
+	    ]
+	].
     ]
 
     "Created: / 10-12-1995 / 14:06:14 / cg"
@@ -10769,8 +10832,8 @@
      (i.e. circumvents window managers positioning)"
 
     self origin:aPoint.
-    drawableId isNil ifTrue:[self create].
-"/    device setTransient:drawableId for:0.
+    self drawableId isNil ifTrue:[self create].
+"/    device setTransient:self drawableId for:0.
     ^ self openModal
 
     "
@@ -10789,7 +10852,7 @@
     "open up the view modeless - positions the view
      (i.e. circumvents window managers positioning)"
 
-    ^ self openModalAt:(device centerOfMonitorHavingPointer - (self extent//2)).
+    ^ self openModalAt:(self graphicsDevice centerOfMonitorHavingPointer - (self extent//2)).
 
     "
      View new openModal
@@ -10861,28 +10924,28 @@
     |newGroup|
 
     StandardSystemView cancelAutoRaise.
-    drawableId isNil ifTrue:[self create].
+    self drawableId isNil ifTrue:[self create].
 
     windowGroup isNil ifTrue:[
-        newGroup := true.
-        windowGroup := self windowGroupClass new.
+	newGroup := true.
+	windowGroup := self windowGroupClass new.
     ] ifFalse:[
-        newGroup := false.
+	newGroup := false.
     ].
 
     windowGroup addTopView:self.
 
     "/ the following allows for hooks to be informed whenever a non-modal view opens
-    device nonModalWindowListenersDo:[:listener | listener aboutToOpenWindow:self].
+    self graphicsDevice nonModalWindowListenersDo:[:listener | listener aboutToOpenWindow:self].
 
     newGroup ifTrue:[
-        (aPoint isNil and:[iconified not]) ifTrue:[
-            windowGroup startupWith:[self realize].
-        ] ifFalse:[
-            windowGroup startupWith:[self realizeKeepingGroup:false at:aPoint iconified:iconified].
-        ].
+	(aPoint isNil and:[iconified not]) ifTrue:[
+	    windowGroup startupWith:[self realize].
+	] ifFalse:[
+	    windowGroup startupWith:[self realizeKeepingGroup:false at:aPoint iconified:iconified].
+	].
     ] ifFalse:[
-        self realizeInGroup.
+	self realizeInGroup.
     ].
 
     "
@@ -10901,7 +10964,7 @@
     "open up the view modeless - positions the view
      (i.e. circumvents window managers positioning)"
 
-    ^ self openModelessAt:(device centerOfMonitorHavingPointer - (self extent//2)).
+    ^ self openModelessAt:(self graphicsDevice centerOfMonitorHavingPointer - (self extent//2)).
 
     "
      View new openModeless
@@ -10930,7 +10993,7 @@
 
     n := 0.
     [self shown] whileFalse:[
-	(device notNil and:[device isOpen not]) ifTrue:[^ self].
+	(self graphicsDevice notNil and:[self graphicsDevice isOpen not]) ifTrue:[^ self].
 
 	"/ this was added to avoid a deadlock, when called from within
 	"/ the event dispatch process (as when doing foo inspect there).
@@ -10971,6 +11034,13 @@
 
 isApplicationSubView
     ^ false
+!
+
+isCodeView2
+
+    ^ false
+
+    "Created: / 20-07-2010 / 15:42:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !SimpleView methodsFor:'user interaction & notifications'!
@@ -11009,74 +11079,74 @@
 "
     this is a hook notification, raised right before a dialog box is about to be opened.
     This allows for standard dialogs (such as confirmers, choosers or notifiers) to
-    be customized by additional widgets. 
+    be customized by additional widgets.
 
     i.e. its typical use is like:
-        |doNotShowHolder|
-
-        doNotShowHolder := false asValue.
-        Dialog aboutToOpenBoxNotificationSignal handle:[:ex |
-            |box|
-
-            box := ex box.
-            box verticalPanel
-                add:(CheckBox label:('Do not show this information in the future.')
-                              model:doNotShowHolder).
-        ] do:[
-            Dialog information:'This is a standard information box.\(but has an additional check toggle in it)' withCRs.
-        ].
+	|doNotShowHolder|
+
+	doNotShowHolder := false asValue.
+	Dialog aboutToOpenBoxNotificationSignal handle:[:ex |
+	    |box|
+
+	    box := ex box.
+	    box verticalPanel
+		add:(CheckBox label:('Do not show this information in the future.')
+			      model:doNotShowHolder).
+	] do:[
+	    Dialog information:'This is a standard information box.\(but has an additional check toggle in it)' withCRs.
+	].
 
     Another application is to suppress dialogs, by returning #abort from the query
     (of course, in real life, the Dialog call is deeply nested below the handler and done elsewhere):
 
-        Dialog aboutToOpenBoxNotificationSignal 
-            answer:#abort
-            do:[
-                Dialog information:'This box is not shown.'
-            ].
+	Dialog aboutToOpenBoxNotificationSignal
+	    answer:#abort
+	    do:[
+		Dialog information:'This box is not shown.'
+	    ].
 
     or to automatically answer all dialogs by simulating user entering a return:
 
-        Dialog aboutToOpenBoxNotificationSignal 
-            handle:[:ex |
-                ex box windowGroup sensor
-                    pushEvent:    
-                        (WindowEvent 
-                                keyPress:#Return
-                                rawKey:#Return
-                                hasShift:false ctrl:false alt:false meta:false
-                                button1:false button2:false button3:false
-                                x:1 y:1 view:ex box).
-            ] do:[
-                Transcript showCR:(Dialog confirm:'Please confirm.')
-            ].
+	Dialog aboutToOpenBoxNotificationSignal
+	    handle:[:ex |
+		ex box windowGroup sensor
+		    pushEvent:
+			(WindowEvent
+				keyPress:#Return
+				rawKey:#Return
+				hasShift:false ctrl:false alt:false meta:false
+				button1:false button2:false button3:false
+				x:1 y:1 view:ex box).
+	    ] do:[
+		Transcript showCR:(Dialog confirm:'Please confirm.')
+	    ].
 
     or an escape:
 
-        Dialog aboutToOpenBoxNotificationSignal 
-            handle:[:ex |
-                ex box windowGroup sensor
-                    pushEvent:    
-                        (WindowEvent 
-                                keyPress:#Escape
-                                rawKey:#Escape
-                                hasShift:false ctrl:false alt:false meta:false
-                                button1:false button2:false button3:false
-                                x:1 y:1 view:ex box).
-            ] do:[
-                Transcript showCR:(Dialog confirm:'Please confirm.')
-            ].
+	Dialog aboutToOpenBoxNotificationSignal
+	    handle:[:ex |
+		ex box windowGroup sensor
+		    pushEvent:
+			(WindowEvent
+				keyPress:#Escape
+				rawKey:#Escape
+				hasShift:false ctrl:false alt:false meta:false
+				button1:false button2:false button3:false
+				x:1 y:1 view:ex box).
+	    ] do:[
+		Transcript showCR:(Dialog confirm:'Please confirm.')
+	    ].
 
     Finally, a recorder may want to keep track of which dialogs have been opened:
     (of course, again, the Dialog calls are deeply nested below the handler and done elsewhere):
 
-        Dialog aboutToOpenBoxNotificationSignal handle:[:ex |
-            Transcript showCR:ex box topView label
-        ] do:[
-            Dialog information:'box #1.'.
-            Dialog information:'box #2.'.
-            Dialog confirm:'bla'.
-        ].
+	Dialog aboutToOpenBoxNotificationSignal handle:[:ex |
+	    Transcript showCR:ex box topView label
+	] do:[
+	    Dialog information:'box #1.'.
+	    Dialog information:'box #2.'.
+	    Dialog confirm:'bla'.
+	].
 
 "
 ! !
@@ -11150,11 +11220,11 @@
 !SimpleView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/SimpleView.st,v 1.740 2014-02-06 11:48:50 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/SimpleView.st,v 1.751.2.1 2014-05-08 08:27:50 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/SimpleView.st,v 1.740 2014-02-06 11:48:50 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/SimpleView.st,v 1.751.2.1 2014-05-08 08:27:50 stefan Exp $'
 !
 
 version_SVN
--- a/StandardSystemView.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/StandardSystemView.st	Thu May 08 10:27:51 2014 +0200
@@ -9,6 +9,8 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 19-03-2014 at 15:29:39'                   !
+
 "{ Package: 'stx:libview' }"
 
 TopView subclass:#StandardSystemView
@@ -337,7 +339,7 @@
     IncludeHostNameInLabel := false.
     WindowLabelFormat := self defaultWindowLabelFormat.
 
-    TakeFocusWhenMapped := (Screen notNil and:[Screen platformName = 'WIN32']).
+    TakeFocusWhenMapped := (Screen notNil and:[Screen isWindowsPlatform]).
 
     "Created: / 20.8.1997 / 14:16:32 / cg"
     "Modified: / 24.8.1998 / 17:16:33 / cg"
@@ -753,27 +755,27 @@
      depends on good-will of window manager"
 
     maxExtent ~= max ifTrue:[
-	maxExtent := max.
-	maxExtent x isNil ifTrue:[
-	    maxExtent := 99999 @ maxExtent y.
-	].
-	maxExtent y isNil ifTrue:[
-	    maxExtent := maxExtent x @ 99999.
-	].
+        maxExtent := max.
+        maxExtent x isNil ifTrue:[
+            maxExtent := 99999 @ maxExtent y.
+        ].
+        maxExtent y isNil ifTrue:[
+            maxExtent := maxExtent x @ 99999.
+        ].
 
-	drawableId notNil ifTrue:[
-	    device setWindowMinExtent:nil maxExtent:max in:drawableId
-	].
+        self drawableId notNil ifTrue:[
+            self graphicsDevice setWindowMinExtent:nil maxExtent:max in:self drawableId
+        ].
 
-	"/ if my current extent is larger than the new
-	"/ maxExtent, adjust.
+        "/ if my current extent is larger than the new
+        "/ maxExtent, adjust.
 
-	(width notNil and:[height notNil]) ifTrue:[
-	    ((width > (max x)) or:
-	     [height > (max y)]) ifTrue: [
-		self extent:(max min:self extent)
-	    ]
-	]
+        (width notNil and:[height notNil]) ifTrue:[
+            ((width > (max x)) or:
+             [height > (max y)]) ifTrue: [
+                self extent:(max min:self extent)
+            ]
+        ]
     ].
 !
 
@@ -788,22 +790,21 @@
      depends on good-will of window manager"
 
     minExtent ~= min ifTrue:[
-	minExtent := min.
-	drawableId notNil ifTrue:[
-	    device setWindowMinExtent:min maxExtent:nil in:drawableId
-	].
+        minExtent := min.
+        self drawableId notNil ifTrue:[
+            self graphicsDevice setWindowMinExtent:min maxExtent:nil in:self drawableId
+        ].
 
-	"/ if my current extent is smaller than the new
-	"/ minExtent, adjust.
+        "/ if my current extent is smaller than the new
+        "/ minExtent, adjust.
 
-	(width notNil and:[height notNil]) ifTrue:[
-	    ((width < (min x)) or:
-	     [height < (min y)]) ifTrue: [
-		self extent:(min max:self extent)
-	    ]
-	]
+        (width notNil and:[height notNil]) ifTrue:[
+            ((width < (min x)) or:
+             [height < (min y)]) ifTrue: [
+                self extent:(min max:self extent)
+            ]
+        ]
     ]
-
 ! !
 
 !StandardSystemView methodsFor:'accessing-look'!
@@ -822,15 +823,15 @@
     icon := aFormOrImage.
     iconValue := icon value.
     iconValue notNil ifTrue:[
-	drawableId notNil ifTrue:[
-	    i := device convertedIcon:iconValue.
-	    (i notNil and:[i id notNil]) ifTrue:[
-		(m := iconValue mask) notNil ifTrue:[
-		    m := device convertedIconMask:m.
-		].
-		device setWindowIcon:i mask:m in:drawableId
-	    ]
-	]
+        self drawableId notNil ifTrue:[
+            i := self graphicsDevice convertedIcon:iconValue.
+            (i notNil and:[i id notNil]) ifTrue:[
+                (m := iconValue mask) notNil ifTrue:[
+                    m := self graphicsDevice convertedIconMask:m.
+                ].
+                self graphicsDevice setWindowIcon:i mask:m in:self drawableId
+            ]
+        ]
     ]
 
     "Modified: / 30-10-2007 / 16:39:15 / cg"
@@ -848,14 +849,14 @@
     |newLabel|
 
     (newLabel := aString string) ~= iconLabel ifTrue:[
-	iconLabel := newLabel.
-	drawableId notNil ifTrue:[
-	    device setIconName:newLabel in:drawableId.
-	    "
-	     unbuffered - to make it visible right NOW
-	    "
-	    device flush.
-	]
+        iconLabel := newLabel.
+        self drawableId notNil ifTrue:[
+            self graphicsDevice setIconName:newLabel in:self drawableId.
+            "
+             unbuffered - to make it visible right NOW
+            "
+            self flush.
+        ]
     ]
 !
 
@@ -869,9 +870,9 @@
 
     "/ only images possibly have iconMasks
     icon notNil ifTrue:[
-	(mask := icon value mask) notNil ifTrue:[
-	    ^ device convertedIconMask:mask
-	]
+        (mask := icon value mask) notNil ifTrue:[
+            ^ self graphicsDevice convertedIconMask:mask
+        ]
     ].
 
     ^ nil
@@ -899,10 +900,10 @@
      This may not be supported on all display types"
 
     iconView := aView.
-    drawableId notNil ifTrue:[
-	aView create.
-	device setWindowIconWindow:aView in:drawableId.
-	aView setRealized:true.
+    self drawableId notNil ifTrue:[
+        aView create.
+        self graphicsDevice setWindowIconWindow:aView in:self drawableId.
+        aView setRealized:true.
     ]
 
     "Modified: 4.4.1997 / 16:21:37 / cg"
@@ -926,7 +927,8 @@
     newLabel notNil ifTrue:[newLabel := newLabel string].
     newLabel ~= label ifTrue:[
         label := newLabel.
-        "drawableId notNil" realized ifTrue: [
+        "/ fix: cg: realized is a bad test here - could still be unmapped...
+        self drawableId notNil "realized" ifTrue: [
             expandedLabel := self windowLabelFor:label.
             self windowName:(expandedLabel ? '').
             shown ifTrue:[
@@ -1048,7 +1050,7 @@
 "/ 'focusIn ' print. windowGroup process name printCR.
 "/ 'focusView is ' print. windowGroup focusView printCR.
 
-        WindowGroup takeFocusFromDevice:device.
+        WindowGroup takeFocusFromDevice:self graphicsDevice.
 
         v := windowGroup focusView.
         v isNil ifTrue:[
@@ -1191,7 +1193,7 @@
     super initialize.
 
     "/ self setBorderWidth:2.         "- notice: many window managers ignore this"
-    device platformName = #WIN32 ifTrue:[
+    self graphicsDevice isWindowsPlatform ifTrue:[
         minExtent := 0 @ 0.
     ] ifFalse:[
         minExtent := 10 @ 10.
@@ -1206,7 +1208,7 @@
 
 mapped
     super mapped.
-    device platformName = #WIN32 ifTrue:[
+    self graphicsDevice isWindowsPlatform ifTrue:[
         "don't do this in X11 - switching between 
          virtual desktops would change the window stacking all the time"
         self setForegroundWindow.
@@ -1221,17 +1223,18 @@
      when we come up on a smaller display,
      make certain, that the receiver is visible"
 
-    |dX dY limitRight limitBottom|
+    |dX dY limitRight limitBottom graphicsDevice|
 
-    dX := (device horizontalPixelPerMillimeter * 20) rounded.
-    dY := (device verticalPixelPerMillimeter * 20) rounded.
+    graphicsDevice := self graphicsDevice.
+    dX := (graphicsDevice horizontalPixelPerMillimeter * 20) rounded.
+    dY := (graphicsDevice verticalPixelPerMillimeter * 20) rounded.
 
-    limitRight := device usableWidth - dX.
-    limitBottom := device usableHeight - dY.
+    limitRight := graphicsDevice usableWidth - dX.
+    limitBottom := graphicsDevice usableHeight - dY.
     ((self left > limitRight) or:[
       self top > limitBottom]) ifTrue:[
-	'StandardSystemView [info]: moving view into visible area' infoPrintCR.
-	self origin:limitRight @ limitBottom
+        'StandardSystemView [info]: moving view into visible area' infoPrintCR.
+        self origin:limitRight @ limitBottom
     ]
 
     "Modified: 10.1.1997 / 15:12:19 / cg"
@@ -1246,8 +1249,8 @@
     |myController|
 
     "if I have already been reinited - return"
-    drawableId notNil ifTrue:[
-	^ self
+    self drawableId notNil ifTrue:[
+        ^ self
     ].
 
     "have to kludge with the controller
@@ -1260,14 +1263,14 @@
     self recreate.
 
     "if I was iconified (not realized), remap iconified"
-    device
-	mapView:self id:drawableId iconified:(realized "shown" not)
-	atX:left y:top width:width height:height
-	minExtent:minExtent maxExtent:maxExtent.
+    self graphicsDevice
+        mapView:self id:self drawableId iconified:(realized "shown" not)
+        atX:left y:top width:width height:height
+        minExtent:minExtent maxExtent:maxExtent.
 
     "and restart the window-group process"
     windowGroup notNil ifTrue:[
-	windowGroup restart
+        windowGroup restart
     ].
 
     "restore controller"
@@ -1322,7 +1325,7 @@
      this means converting it to a format (typically: monochrome) which
      the device supports. Return a compatible version of the icon."
 
-    ^ device convertedIcon:icon
+    ^ self graphicsDevice convertedIcon:icon
 
     "Modified: / 30-10-2007 / 16:39:55 / cg"
 !
@@ -1332,7 +1335,7 @@
      this means converting it to a format (typically: monochrome) which
      the device supports. Return a compatible version of the icon."
 
-    ^ device convertedIcon:iconArg
+    ^ self graphicsDevice convertedIcon:iconArg
 
     "Modified: / 30-10-2007 / 16:37:31 / cg"
 !
@@ -1343,7 +1346,7 @@
      mask - future versions may add alpha channel masks, if the device supports
      them ..."
 
-    ^ device convertedIconMask:aMask
+    ^ self graphicsDevice convertedIconMask:aMask
 
     "Modified: / 30-10-2007 / 16:38:58 / cg"
 !
@@ -1433,18 +1436,18 @@
     "iconify the receiver"
 
     shown ifTrue:[
-	self unmap.
+        self unmap.
 
-	"if it was iconified, try to remap iconified"
-	device
-	    mapView:self id:drawableId iconified:true
-	    atX:left y:top width:width height:height
-	    minExtent:minExtent maxExtent:maxExtent.
+        "if it was iconified, try to remap iconified"
+        self graphicsDevice
+            mapView:self id:self drawableId iconified:true
+            atX:left y:top width:width height:height
+            minExtent:minExtent maxExtent:maxExtent.
 
-	shown ifTrue:[
-	    shown := false.
-	    self changed:#visibility.
-	].
+        shown ifTrue:[
+            shown := false.
+            self changed:#visibility.
+        ].
     ].
 
     "
@@ -1468,12 +1471,12 @@
     super create.
 
     iconView notNil ifTrue:[
-	iconView create.
-	device setWindowIconWindow:iconView in:drawableId.
-	iconView setRealized:true.
+        iconView create.
+        self graphicsDevice setWindowIconWindow:iconView in:self drawableId.
+        iconView setRealized:true.
     ].
     iconLabel notNil ifTrue:[
-	device setIconName:iconLabel string in:drawableId
+        self graphicsDevice setIconName:iconLabel string in:self drawableId
     ]
 
     "Modified: 10.6.1996 / 20:14:50 / cg"
@@ -1483,13 +1486,13 @@
     "de-iconify the receiver at its old position"
 
     shown ifFalse:[
-	self unmap.
+        self unmap.
 
-	"if it was iconified, try to remap iconified"
-	device
-	    mapView:self id:drawableId iconified:false
-	    atX:left y:top width:width height:height
-	    minExtent:minExtent maxExtent:maxExtent.
+        "if it was iconified, try to remap iconified"
+        self graphicsDevice
+            mapView:self id:self drawableId iconified:false
+            atX:left y:top width:width height:height
+            minExtent:minExtent maxExtent:maxExtent.
     ].
 
     "
@@ -1543,7 +1546,7 @@
     "/ and provide another origin (by payching my origin via setOrigin:).
     WindowSensor preViewCreateNotification:self.
 
-    self
+    gc
       createWindowFor:self
       type:(self windowType)
       origin:org
@@ -1559,8 +1562,6 @@
       icon:icn iconMask:icnMask
       iconView:iconView.
 
-    Lobby registerChange:self.
-
     "/ give global listeners a chance to track views
     WindowSensor postViewCreateNotification:self.
 
@@ -1638,8 +1639,6 @@
 
     super postRealize.
 
-    self windowName:(self windowLabelFor:label).
-
     "/
     "/ let the application add its views to the current project
     "/
@@ -1669,17 +1668,17 @@
     super recreate.
 
     iconView notNil ifTrue:[
-	iconView recreate.
-	device setWindowIconWindow:iconView in:drawableId.
-	iconView setRealized:true.
+        iconView recreate.
+        self graphicsDevice setWindowIconWindow:iconView in:self drawableId.
+        iconView setRealized:true.
     ] ifFalse:[
-	icon notNil ifTrue:[
-	    self icon:(device convertedIcon:icon).
-	].
+        icon notNil ifTrue:[
+            self icon:(self graphicsDevice convertedIcon:icon).
+        ].
     ].
 
     iconLabel notNil ifTrue:[
-	device setIconName:iconLabel in:drawableId
+        self graphicsDevice setIconName:iconLabel in:self drawableId
     ]
 
     "Modified: / 30-10-2007 / 16:39:42 / cg"
@@ -1688,11 +1687,11 @@
 !StandardSystemView class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/StandardSystemView.st,v 1.215 2014-02-06 11:46:44 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/StandardSystemView.st,v 1.219.2.1 2014-05-08 08:27:50 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/StandardSystemView.st,v 1.215 2014-02-06 11:46:44 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/StandardSystemView.st,v 1.219.2.1 2014-05-08 08:27:50 stefan Exp $'
 ! !
 
 
--- a/WindowSensor.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/WindowSensor.st	Thu May 08 10:27:51 2014 +0200
@@ -855,6 +855,8 @@
     [
         Error handle:[:ex |
             ('WindowSensor [Warning]: Error in eventQ handling ignored: ' , ex description) errorPrintCR.
+            "/ thisContext fullPrintAll.
+            "/ whichLock printCR.
             ex return
         ] do:[
             whichLock critical:aBlock
@@ -1949,7 +1951,7 @@
     eventListeners notNil ifTrue:[
         "/ be prepared that a listener removes itself while we iterate...
         eventListeners copy do:[:aListener |
-            (aListener processEvent:anEvent) == true ifTrue:[
+            (aListener notNil and:[(aListener processEvent:anEvent) == true]) ifTrue:[
                 anyListenerReturnedTrue := true
             ]
         ]
@@ -2564,9 +2566,9 @@
 initializeState
     "initialize the event queues to empty"
 
-    damageEventAccessLock := Semaphore forMutualExclusion.
+    damageEventAccessLock := RecursionLock new.
     damageEventAccessLock name:'WSensor ev-q damageEventAccessLock'.
-    userEventAccessLock := Semaphore forMutualExclusion.
+    userEventAccessLock := RecursionLock new.
     userEventAccessLock name:'WSensor ev-q userEventAccessLock'.
 
     damage := OrderedCollection new.
@@ -3156,7 +3158,7 @@
     [
         device flush.
 
-        device platformName = 'WIN32' ifTrue:[
+        device isWindowsPlatform ifTrue:[
             "/ since this is definitely a local display,
             "/ there is no need for a long timeOut
             "/ (it should arrive fast)
@@ -3251,7 +3253,7 @@
 !WindowSensor class methodsFor:'documentation'!
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/WindowSensor.st,v 1.281 2013-09-19 20:46:38 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/WindowSensor.st,v 1.284.2.1 2014-05-08 08:27:50 stefan Exp $'
 ! !
 
 
--- a/XWorkstation.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/XWorkstation.st	Thu May 08 10:27:51 2014 +0200
@@ -1,6 +1,6 @@
 "
 COPYRIGHT (c) 1989 by Claus Gittinger
-	      All Rights Reserved
+              All Rights Reserved
 
  This software is furnished under a license and may be used
  only in accordance with the terms of that license and with the
@@ -9,6 +9,8 @@
  other person.  No title to or ownership of the software is
  hereby transferred.
 "
+'From Smalltalk/X, Version:6.2.3.0 on 04-04-2014 at 21:28:11'                   !
+
 "{ Package: 'stx:libview' }"
 
 DeviceWorkstation subclass:#XWorkstation
@@ -50,6 +52,13 @@
 	privateIn:XWorkstation
 !
 
+DeviceGraphicsContext subclass:#X11GraphicsContext
+	instanceVariableNames:'useXftFont xftDrawId'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:XWorkstation
+!
+
 !XWorkstation primitiveDefinitions!
 %{
 
@@ -247,16 +256,16 @@
  */
 #define __ENTER_XLIB(whichTimeout)   \
     { \
-	__blockingPrimitiveTimoutHandler__ = (VOIDFUNC)__XTimeoutErrorHandler; \
-	__blockingPrimitiveTimeoutArg__ = self; \
-	__blockingPrimitiveTimeout__ = __intVal(__INST(whichTimeout)) * 1000; \
+        __blockingPrimitiveTimoutHandler__ = (VOIDFUNC)__XTimeoutErrorHandler; \
+        __blockingPrimitiveTimeoutArg__ = self; \
+        __blockingPrimitiveTimeout__ = __intVal(__INST(whichTimeout)) * 1000; \
     } {
 
 #define LEAVE_XLIB()   \
     { \
-	__blockingPrimitiveTimoutHandler__ = (VOIDFUNC)0; \
-	__blockingPrimitiveTimeoutArg__ = nil; \
-	__blockingPrimitiveTimeout__ = 0; \
+        __blockingPrimitiveTimoutHandler__ = (VOIDFUNC)0; \
+        __blockingPrimitiveTimeoutArg__ = nil; \
+        __blockingPrimitiveTimeout__ = 0; \
     } }
 
 #define ENTER_XLIB()   __ENTER_XLIB(xlibTimeout)
@@ -350,18 +359,18 @@
 # endif
 static
 dummyToForceLoading() {
-	XCreateSimpleWindow(0, 0, 0, 0, 0, 0, 0, 0, 0);
-	XCloseDisplay(0);
-	XCreateImage(0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0);
-	XSetWindowColormap(0, 0, 0);
-	XQueryColors(0,0,0,0);
+        XCreateSimpleWindow(0, 0, 0, 0, 0, 0, 0, 0, 0);
+        XCloseDisplay(0);
+        XCreateImage(0, 0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0);
+        XSetWindowColormap(0, 0, 0);
+        XQueryColors(0,0,0,0);
 # ifdef SHM
-	XShmAttach(0, 0);
-	XShmCreateImage(0, 0, 0, 0, 0, 0, 0 ,0);
-	XShmDetach(0, 0);
-	XShmPutImage(0, 0, 0, 0 , 0,0,0,0,0,0,0);
-	shmctl(0,0,0);
-	fgetc(0);
+        XShmAttach(0, 0);
+        XShmCreateImage(0, 0, 0, 0, 0, 0, 0 ,0);
+        XShmDetach(0, 0);
+        XShmPutImage(0, 0, 0, 0 , 0,0,0,0,0,0,0);
+        shmctl(0,0,0);
+        fgetc(0);
 # endif
 }
 #endif
@@ -386,36 +395,39 @@
     lastErrorMsg[127] = '\0';
 
     if (lastErrorMsg[0] == '\0') {
-	sprintf(lastErrorMsg, "code: %d", event->error_code);
+        sprintf(lastErrorMsg, "code: %d", event->error_code);
     }
     lastRequestCode = event->request_code;
     lastMinorCode = event->minor_code;
     lastResource = event->resourceid;
     if ((event->error_code == BadWindow) && (lastRequestCode == 4) && (lastMinorCode == 0)) {
-	/*
-	 * this is a BadWindow error for X_DestroyWindow.
-	 * ignore it here, since it results from the GC freeing windows
-	 * in non bottom-up window order.
-	 */
-	return 0;
+        /*
+         * this is a BadWindow error for X_DestroyWindow.
+         * ignore it here, since it results from the GC freeing windows
+         * in non bottom-up window order.
+         */
+        return 0;
     }
 
     if (@global(DeviceWorkstation:ErrorPrinting) == true) {
-	console_fprintf(stderr, "XWorkstation [error]: x-error caught maj=%d (0x%x) min=%d (0x%x) resource=%"_lx_"\n",
-			event->request_code, event->request_code,
-			event->minor_code, event->minor_code, (INT)(event->resourceid));
-	console_fprintf(stderr, "XWorkstation [error]: x-error message is [%d] '%s'\n",
-			event->error_code, lastErrorMsg);
-    }
+        console_fprintf(stderr, "XWorkstation [error]: x-error caught maj=%d (0x%x) min=%d (0x%x) resource=%"_lx_"\n",
+                        event->request_code, event->request_code,
+                        event->minor_code, event->minor_code, (INT)(event->resourceid));
+        console_fprintf(stderr, "XWorkstation [error]: x-error message is [%d] '%s'\n",
+                        event->error_code, lastErrorMsg);
+    }
+#if 0
+    // cg: should no longer be needed - librun no longer sends an errorInterrupt while running on C-stack
 #ifdef XFT
     if ((strncmp(lastErrorMsg, "RenderBadPicture", 16) == 0)) {
-	/*
-	 * this is a RenderBadPicture error from XFT drawing.
-	 * ignore it for now, as this is due to an incomplete implementation
-	 */
-	console_fprintf(stderr, "XWorkstation [info]: x-error ignored\n");
-	return 0;
-    }
+        /*
+         * this is a RenderBadPicture error from XFT drawing.
+         * ignore it for now, as this is due to an incomplete implementation
+         */
+        console_fprintf(stderr, "XWorkstation [info]: x-error ignored\n");
+        return 0;
+    }
+#endif
 #endif
     __errorInterruptWithIDAndParameter__(@symbol(DisplayError), __MKEXTERNALADDRESS(dpy));
     return 0;
@@ -434,10 +446,10 @@
     Display *dpy;
 {
     if (@global(DeviceWorkstation:ErrorPrinting) == true) {
-	console_fprintf(stderr, "XWorkstation [error]: I/O error\n");
+        console_fprintf(stderr, "XWorkstation [error]: I/O error\n");
     }
     __immediateErrorInterruptWithIDAndParameter__(@symbol(DisplayIOError),
-						  __MKEXTERNALADDRESS(dpy));
+                                                  __MKEXTERNALADDRESS(dpy));
 
 #if 0
     /*
@@ -469,12 +481,12 @@
     OBJ displayDeviceInst;
 {
     if ((displayDeviceInst == @global(MainDisplay))
-	|| (displayDeviceInst == @global(DeviceWorkstation:DefaultScreen))) {
-	console_fprintf(stderr, "XWorkstation [error]: keep display connection for master display after X11 timeout (no shutdown)\n");
-	return;
+        || (displayDeviceInst == @global(DeviceWorkstation:DefaultScreen))) {
+        console_fprintf(stderr, "XWorkstation [error]: keep display connection for master display after X11 timeout (no shutdown)\n");
+        return;
     }
     if (@global(DeviceWorkstation:ErrorPrinting) == true) {
-	console_fprintf(stderr, "XWorkstation [error]: X11 request timeout dpy=%"_lx_"\n", (INT)displayDeviceInst);
+        console_fprintf(stderr, "XWorkstation [error]: X11 request timeout dpy=%"_lx_"\n", (INT)displayDeviceInst);
     }
     __OINST(displayDeviceInst, hasConnectionBroken) = true;
 
@@ -486,14 +498,14 @@
      * if we return from the error interrupt ...
      */
     if (__OINST(displayDeviceInst, displayId) != nil) {
-	__internalError("unhandled X11 display timeout error");
-
-	/*
-	 * the current process failed to do an X11 request.
-	 * Terminate it!
-	 */
-	__terminateProcess(0);      /* soft terminate */
-	__terminateProcess(1);      /* hard terminate */
+        __internalError("unhandled X11 display timeout error");
+
+        /*
+         * the current process failed to do an X11 request.
+         * Terminate it!
+         */
+        __terminateProcess(0);      /* soft terminate */
+        __terminateProcess(1);      /* hard terminate */
     }
 }
 
@@ -505,7 +517,7 @@
 copyright
 "
 COPYRIGHT (c) 1989 by Claus Gittinger
-	      All Rights Reserved
+              All Rights Reserved
 
  This software is furnished under a license and may be used
  only in accordance with the terms of that license and with the
@@ -531,28 +543,28 @@
     query is answered by the launcher when opening its applications.
 
     Timeouts:
-	sometimes, X-connections are lost and, as the Xlib is blocking and synchronous by
-	default, this would lead to a locked ST/X system.
-	Therefore, this class defines a timeOut, whenever doing an Xlib call.
-	The default for this timeout is 30seconds.
-	This may be a problem with windowmanagers which show a rubber-band rectangle
-	when creating windows.
-	If the user does not specify the rectangle within 30 seconds, the device assumes
-	a timeout and closes the connection.
-	As a (kludgy) workaround, a second timeout value is used for window-creation.
-	This secondary timeout value defaults to 60*5 seconds (5 minutes).
+        sometimes, X-connections are lost and, as the Xlib is blocking and synchronous by
+        default, this would lead to a locked ST/X system.
+        Therefore, this class defines a timeOut, whenever doing an Xlib call.
+        The default for this timeout is 30seconds.
+        This may be a problem with windowmanagers which show a rubber-band rectangle
+        when creating windows.
+        If the user does not specify the rectangle within 30 seconds, the device assumes
+        a timeout and closes the connection.
+        As a (kludgy) workaround, a second timeout value is used for window-creation.
+        This secondary timeout value defaults to 60*5 seconds (5 minutes).
 
     See more documentation in my superclass, DeviceWorkstation.
 
     [author:]
-	Claus Gittinger
+        Claus Gittinger
 "
 ! !
 
 !XWorkstation class methodsFor:'initialization'!
 
 initialize
-    ConservativeSync := OperatingSystem platformName == #win32.
+    ConservativeSync := OperatingSystem isMSWINDOWSlike.
 
     "/ some XServers crash, when given too long strings in XDrawString/XDrawInageString.
     "/ the following is an adjustable soft-limit.
@@ -563,18 +575,18 @@
     DefaultXLibTimeoutForWindowCreation := 5*60.
 
     RawKeySymTranslation isNil ifTrue:[
-	"/ the following table maps X-keyevents to ST/X
-	"/ device independend events.
-	"/ It is NOT meant as a keyboardMap replacement.
-
-	RawKeySymTranslation := Dictionary new:6.
-	RawKeySymTranslation
-	    at:#'Delete_line' put:#DeleteLine;
-	    at:#'Delete_word' put:#DeleteWord;
-	    at:#Down put:#CursorDown;
-	    at:#Up put:#CursorUp;
-	    at:#Left put:#CursorLeft;
-	    at:#Right put:#CursorRight.
+        "/ the following table maps X-keyevents to ST/X
+        "/ device independend events.
+        "/ It is NOT meant as a keyboardMap replacement.
+
+        RawKeySymTranslation := Dictionary new:6.
+        RawKeySymTranslation
+            at:#'Delete_line' put:#DeleteLine;
+            at:#'Delete_word' put:#DeleteWord;
+            at:#Down put:#CursorDown;
+            at:#Up put:#CursorUp;
+            at:#Left put:#CursorLeft;
+            at:#Right put:#CursorRight.
     ]
 
     "Modified: / 27.4.1999 / 17:21:30 / cg"
@@ -593,8 +605,8 @@
 %{
 #ifdef COUNT_RESOURCES
     console_fprintf(stderr, "colors:%d bitmaps:%d views:%d gc:%d cursors:%d fonts:%d\n",
-	    __cnt_color, __cnt_bitmap,
-	    __cnt_view, __cnt_gc, __cnt_cursor, __cnt_font);
+            __cnt_color, __cnt_bitmap,
+            __cnt_view, __cnt_gc, __cnt_cursor, __cnt_font);
 #endif
 %}
 
@@ -637,31 +649,31 @@
     "
     match := 'XRequest.' , requestCode printString.
     ErrorDBCache isNil ifTrue:[
-	ErrorDBCache := IdentityDictionary new.
+        ErrorDBCache := IdentityDictionary new.
     ].
 
     "if there is no XErrorDB or no entry, the line for the requestCode is cached as nil"
     line := ErrorDBCache at:requestCode ifAbsentPut:[
-	    |errorLine|
-
-	    s := '/usr/share/X11/XErrorDB' asFilename readStreamOrNil.
-	    s notNil ifTrue:[
-		errorLine := s peekForLineStartingWith:match.
-		errorLine notNil ifTrue:[
-		    errorLine := errorLine copyFrom:(errorLine indexOf:$:)+1.
-		].
-		s close.
-	    ].
-	    errorLine
-	].
+            |errorLine|
+
+            s := '/usr/share/X11/XErrorDB' asFilename readStreamOrNil.
+            s notNil ifTrue:[
+                errorLine := s peekForLineStartingWith:match.
+                errorLine notNil ifTrue:[
+                    errorLine := errorLine copyFrom:(errorLine indexOf:$:)+1.
+                ].
+                s close.
+            ].
+            errorLine
+        ].
 
     line isNil ifTrue:[
-	line := match
+        line := match
     ].
     ^ string , ' in ' , line.
 
     "
-	Screen lastErrorString
+        Screen lastErrorString
     "
 !
 
@@ -683,7 +695,7 @@
 %{  /* NOCONTEXT */
 
       if (lastResource != 0) {
-	 RETURN ( __MKEXTERNALADDRESS(lastResource) );
+         RETURN ( __MKEXTERNALADDRESS(lastResource) );
       }
 %}.
 
@@ -691,7 +703,7 @@
 
 
      "
-	 Screen resourceIdOfLastError
+         Screen resourceIdOfLastError
      "
 !
 
@@ -736,6 +748,21 @@
     "Created: / 20-12-2013 / 11:02:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
+displayIdOrErrorIfBroken
+    (hasConnectionBroken or:[displayId isNil]) ifTrue:[
+	self primitiveFailedOrClosedConnection.
+	^ nil.
+    ].
+    ^ displayId
+!
+
+displayIdOrNilIfBroken
+    hasConnectionBroken ifTrue:[
+	^ nil.
+    ].
+    ^ displayId
+!
+
 maxOperationsUntilFlush
     ^ maxOperationsUntilFlush
 !
@@ -771,7 +798,7 @@
 
     prev := activateOnClick ? false.
     aBoolean notNil ifTrue:[
-	activateOnClick := aBoolean.
+        activateOnClick := aBoolean.
     ].
     ^ prev
 
@@ -834,13 +861,13 @@
 
 %{  /* NOCONTEXT */
     if (aButton == __MKSMALLINT(1)) {
-	RETURN (__MKSMALLINT(Button1MotionMask));
+        RETURN (__MKSMALLINT(Button1MotionMask));
     }
     if (aButton == __MKSMALLINT(2)) {
-	RETURN (__MKSMALLINT(Button2MotionMask));
+        RETURN (__MKSMALLINT(Button2MotionMask));
     }
     if (aButton == __MKSMALLINT(3)) {
-	RETURN (__MKSMALLINT(Button3MotionMask));
+        RETURN (__MKSMALLINT(Button3MotionMask));
     }
 %}.
     ^ nil
@@ -861,7 +888,7 @@
 %{  /* NOCONTEXT */
 #ifndef WIN32
     if (ISCONNECTED) {
-	RETURN ( __MKSMALLINT(ConnectionNumber(myDpy)) );
+        RETURN ( __MKSMALLINT(ConnectionNumber(myDpy)) );
     }
 #endif
     RETURN (nil);
@@ -888,7 +915,7 @@
 
 %{  /* NOCONTEXT */
     if (ISCONNECTED) {
-	RETURN ( __MKSMALLINT(XProtocolVersion(myDpy)) );
+        RETURN ( __MKSMALLINT(XProtocolVersion(myDpy)) );
     }
     RETURN (nil);
 %}
@@ -904,7 +931,7 @@
      (to avoid bugs in certain implementations)"
 %{
     if (ISCONNECTED) {
-	RETURN ( __MKSTRING(XServerVendor(myDpy)) );
+        RETURN ( __MKSTRING(XServerVendor(myDpy)) );
     }
     RETURN (nil);
 %}
@@ -945,28 +972,28 @@
      && __isExternalAddress(windowId1)
      && __isExternalAddress(windowId2)
      && __bothSmallInteger(x1, y1)) {
-	Display *dpy = myDpy;
-	Window rootWin;
-
-	w1 = __WindowVal(windowId1);
-	w2 = __WindowVal(windowId2);
-
-	rootWin = RootWindow(dpy, screen);
-	if (w1 == rootWin) {
-	    w1 = (Window)__externalAddressVal(rootWindowId);
-	}
-	if (w2 == rootWin) {
-	    w2 = (Window)__externalAddressVal(rootWindowId);
-	}
-
-	ENTER_XLIB();
-	XTranslateCoordinates(dpy, w1, w2,
-			      __intVal(x1), __intVal(y1),
-			      &xpos, &ypos, &child_ret);
-	LEAVE_XLIB();
-
-	x2 = __MKSMALLINT(xpos);
-	y2 = __MKSMALLINT(ypos);
+        Display *dpy = myDpy;
+        Window rootWin;
+
+        w1 = __WindowVal(windowId1);
+        w2 = __WindowVal(windowId2);
+
+        rootWin = RootWindow(dpy, screen);
+        if (w1 == rootWin) {
+            w1 = (Window)__externalAddressVal(rootWindowId);
+        }
+        if (w2 == rootWin) {
+            w2 = (Window)__externalAddressVal(rootWindowId);
+        }
+
+        ENTER_XLIB();
+        XTranslateCoordinates(dpy, w1, w2,
+                              __intVal(x1), __intVal(y1),
+                              &xpos, &ypos, &child_ret);
+        LEAVE_XLIB();
+
+        x2 = __MKSMALLINT(xpos);
+        y2 = __MKSMALLINT(ypos);
     }
 %}.
 
@@ -980,7 +1007,7 @@
 
 %{  /* NOCONTEXT */
     if (ISCONNECTED) {
-	RETURN ( __MKSMALLINT(XVendorRelease(myDpy)) );
+        RETURN ( __MKSMALLINT(XVendorRelease(myDpy)) );
     }
     RETURN (nil);
 %}
@@ -1007,31 +1034,31 @@
     if (ISCONNECTED
      && __isExternalAddress(windowId)
      && __isPoint(aPoint)) {
-	Display *dpy = myDpy;
-
-	xp = _point_X(aPoint);
-	yp = _point_Y(aPoint);
-	if (__bothSmallInteger(xp, yp)) {
-
-	    ENTER_XLIB();
-	    XTranslateCoordinates(dpy,
-				  RootWindow(dpy, screen),
-				  __WindowVal(windowId),
-				  __intVal(xp), __intVal(yp),
-				  &xpos, &ypos, &child_ret);
-	    LEAVE_XLIB();
-
-	    if (child_ret) {
-		RETURN ( __MKEXTERNALADDRESS(child_ret) );
-	    }
-	    RETURN ( nil );
-	}
+        Display *dpy = myDpy;
+
+        xp = _point_X(aPoint);
+        yp = _point_Y(aPoint);
+        if (__bothSmallInteger(xp, yp)) {
+
+            ENTER_XLIB();
+            XTranslateCoordinates(dpy,
+                                  RootWindow(dpy, screen),
+                                  __WindowVal(windowId),
+                                  __intVal(xp), __intVal(yp),
+                                  &xpos, &ypos, &child_ret);
+            LEAVE_XLIB();
+
+            if (child_ret) {
+                RETURN ( __MKEXTERNALADDRESS(child_ret) );
+            }
+            RETURN ( nil );
+        }
     }
 %}.
     windowId notNil ifTrue:[
-	aPoint isPoint ifTrue:[
-	    ^ self viewIdFromPoint:aPoint asPoint truncated in:windowId
-	]
+        aPoint isPoint ifTrue:[
+            ^ self viewIdFromPoint:aPoint asPoint truncated in:windowId
+        ]
     ].
 
     ^ nil
@@ -1051,21 +1078,21 @@
     if (ISCONNECTED
      && (__INST(rootId) != __INST(virtualRootId))
      && __isExternalAddress(__INST(virtualRootId))) {
-	Window vRootWin;
-	Window root;
-	int x, y;
-	unsigned int width, height;
-	unsigned int dummy;
-	int ret;
-
-	vRootWin = __WindowVal(__INST(virtualRootId));
-	ENTER_XLIB();
-	ret = XGetGeometry(myDpy, vRootWin, &root, &x, &y, &width, &height,
-					  &dummy, &dummy);
-	LEAVE_XLIB();
-	if (ret) {
-	    RETURN ( __MKPOINT_INT(width, height) );
-	}
+        Window vRootWin;
+        Window root;
+        int x, y;
+        unsigned int width, height;
+        unsigned int dummy;
+        int ret;
+
+        vRootWin = __WindowVal(__INST(virtualRootId));
+        ENTER_XLIB();
+        ret = XGetGeometry(myDpy, vRootWin, &root, &x, &y, &width, &height,
+                                          &dummy, &dummy);
+        LEAVE_XLIB();
+        if (ret) {
+            RETURN ( __MKPOINT_INT(width, height) );
+        }
     }
 %}.
     ^ width @ height
@@ -1108,9 +1135,9 @@
      This method must be redefined for displays which need it (i.e. X11 on osx)"
 
     OperatingSystem getOSType == #osx ifTrue:[
-	"/ should check for local display here - sigh, osx's Xserver does not give
-	"/ us a hint through the server vendor...
-	^ 16@16
+        "/ should check for local display here - sigh, osx's Xserver does not give
+        "/ us a hint through the server vendor...
+        ^ 16@16
     ].
     ^ 0@0
 !
@@ -1140,11 +1167,11 @@
 
     if (ISCONNECTED
      && __isStringLike(extensionString)) {
-	ENTER_XLIB();
-	if (XQueryExtension(myDpy, __stringVal(extensionString), &dummy, &dummy, &dummy)) {
-	    rslt = true;
-	}
-	LEAVE_XLIB();
+        ENTER_XLIB();
+        if (XQueryExtension(myDpy, __stringVal(extensionString), &dummy, &dummy, &dummy)) {
+            rslt = true;
+        }
+        LEAVE_XLIB();
     }
     RETURN (rslt);
 %}
@@ -1247,44 +1274,44 @@
     int cnt;
 
     if (ISCONNECTED) {
-	Display *dpy = myDpy;
-	int status;
-
-	ENTER_XLIB();
-	status = XGetIconSizes(dpy, RootWindow(dpy, screen), &sizeList, &cnt);
-	LEAVE_XLIB();
-	if (status > 0) {
-	   xIconSizes = __MKEXTERNALBYTES(sizeList);
-	   count = __MKSMALLINT(cnt);
-	}
+        Display *dpy = myDpy;
+        int status;
+
+        ENTER_XLIB();
+        status = XGetIconSizes(dpy, RootWindow(dpy, screen), &sizeList, &cnt);
+        LEAVE_XLIB();
+        if (status > 0) {
+           xIconSizes = __MKEXTERNALBYTES(sizeList);
+           count = __MKSMALLINT(cnt);
+        }
     }
 %}.
     xIconSizes isNil ifTrue:[^ nil].
 
     ret := OrderedCollection new:count.
     1 to:count do:[ :i |
-	|minWidth minHeight maxWidth maxHeight widthStep heightStep d|
-
-%{
-	XIconSize *slp;
-
-	slp = &((XIconSize *)__externalAddressVal(xIconSizes))[__intVal(i)-1];
-	minWidth = __MKSMALLINT(slp->min_width);
-	minHeight = __MKSMALLINT(slp->min_height);
-	maxWidth = __MKSMALLINT(slp->max_width);
-	maxHeight = __MKSMALLINT(slp->max_height);
-	widthStep = __MKSMALLINT(slp->width_inc);
-	heightStep = __MKSMALLINT(slp->height_inc);
-%}.
-	d := IdentityDictionary new.
-	d at:#minWidth put:minWidth.
-	d at:#maxWidth put:maxWidth.
-	d at:#widthStep put:widthStep.
-	d at:#minHeight put:minHeight.
-	d at:#maxHeight put:maxHeight.
-	d at:#heightStep put:heightStep.
-
-	ret add:d
+        |minWidth minHeight maxWidth maxHeight widthStep heightStep d|
+
+%{
+        XIconSize *slp;
+
+        slp = &((XIconSize *)__externalAddressVal(xIconSizes))[__intVal(i)-1];
+        minWidth = __MKSMALLINT(slp->min_width);
+        minHeight = __MKSMALLINT(slp->min_height);
+        maxWidth = __MKSMALLINT(slp->max_width);
+        maxHeight = __MKSMALLINT(slp->max_height);
+        widthStep = __MKSMALLINT(slp->width_inc);
+        heightStep = __MKSMALLINT(slp->height_inc);
+%}.
+        d := IdentityDictionary new.
+        d at:#minWidth put:minWidth.
+        d at:#maxWidth put:maxWidth.
+        d at:#widthStep put:widthStep.
+        d at:#minHeight put:minHeight.
+        d at:#maxHeight put:maxHeight.
+        d at:#heightStep put:heightStep.
+
+        ret add:d
     ].
 
     xIconSizes free.
@@ -1312,52 +1339,52 @@
 %{
 #ifdef XINERAMA
     if (ISCONNECTED && __INST(hasXineramaExtension) == true) {
-	Display *dpy = myDpy;
-	XineramaScreenInfo *screenInfo;
-	int numDisplays;
-	OBJ *cResultArray;
-	int i, ci;
-
-	screenInfo = XineramaQueryScreens (dpy, &numDisplays);
-	if (screenInfo == 0) {
-	    goto out;
-	}
-
-	numberOfMonitors = __mkSmallInteger(numDisplays);
-	resultArray = __ARRAY_NEW_INT(numDisplays * 5);
-	cResultArray = __ArrayInstPtr(resultArray)->a_element;
-
-	for (i=0, ci=0; i < numDisplays; i++, ci+=5) {
-	    cResultArray[ci] = __mkSmallInteger(screenInfo[i].screen_number);
-	    cResultArray[ci+1] = __mkSmallInteger(screenInfo[i].x_org);
-	    cResultArray[ci+2] = __mkSmallInteger(screenInfo[i].y_org);
-	    cResultArray[ci+3] = __mkSmallInteger(screenInfo[i].width);
-	    cResultArray[ci+4] = __mkSmallInteger(screenInfo[i].height);
-	}
-
-	XFree(screenInfo);
+        Display *dpy = myDpy;
+        XineramaScreenInfo *screenInfo;
+        int numDisplays;
+        OBJ *cResultArray;
+        int i, ci;
+
+        screenInfo = XineramaQueryScreens (dpy, &numDisplays);
+        if (screenInfo == 0) {
+            goto out;
+        }
+
+        numberOfMonitors = __mkSmallInteger(numDisplays);
+        resultArray = __ARRAY_NEW_INT(numDisplays * 5);
+        cResultArray = __ArrayInstPtr(resultArray)->a_element;
+
+        for (i=0, ci=0; i < numDisplays; i++, ci+=5) {
+            cResultArray[ci] = __mkSmallInteger(screenInfo[i].screen_number);
+            cResultArray[ci+1] = __mkSmallInteger(screenInfo[i].x_org);
+            cResultArray[ci+2] = __mkSmallInteger(screenInfo[i].y_org);
+            cResultArray[ci+3] = __mkSmallInteger(screenInfo[i].width);
+            cResultArray[ci+4] = __mkSmallInteger(screenInfo[i].height);
+        }
+
+        XFree(screenInfo);
     }
 #endif
 out:;
 %}.
     numberOfMonitors isNil ifTrue:[
-	"no xinerama - the display is the only monitor"
-	^ Array with:self bounds.
+        "no xinerama - the display is the only monitor"
+        ^ Array with:self bounds.
     ].
     rawMonitorBounds = resultArray ifTrue:[
-	^ monitorBounds.
+        ^ monitorBounds.
     ].
 
     bounds := Array new:numberOfMonitors.
     1 to:numberOfMonitors do:[:idx|
-	|rect baseIdx|
-	baseIdx := (idx-1) * 5.
-	rect := Rectangle
-		    left:(resultArray at:baseIdx+2)
-		    top:(resultArray at:baseIdx+3)
-		    width:(resultArray at:baseIdx+4)
-		    height:(resultArray at:baseIdx+5).
-	bounds at:idx put:rect.
+        |rect baseIdx|
+        baseIdx := (idx-1) * 5.
+        rect := Rectangle
+                    left:(resultArray at:baseIdx+2)
+                    top:(resultArray at:baseIdx+3)
+                    width:(resultArray at:baseIdx+4)
+                    height:(resultArray at:baseIdx+5).
+        bounds at:idx put:rect.
     ].
 
     rawMonitorBounds := resultArray.
@@ -1380,8 +1407,8 @@
 
     bounds := self monitorBounds.
     ^ bounds
-	detect:[:eachRectangle| eachRectangle containsPoint:aPoint]
-	ifNone:[super monitorBoundsAt:aPoint].
+        detect:[:eachRectangle| eachRectangle containsPoint:aPoint]
+        ifNone:[super monitorBoundsAt:aPoint].
 
     "
      Screen current monitorBoundsAt:(0@0)
@@ -1396,7 +1423,7 @@
     ^ self monitorBounds size
 
     "
-	Display numberOfMonitors
+        Display numberOfMonitors
     "
 !
 
@@ -1427,7 +1454,7 @@
      Redefined to return a special value on SGI servers."
 
     self serverVendor = 'Silicon Graphics' ifTrue:[
-	^ 86@68
+        ^ 86@68
     ].
     ^ super preferredIconSize
 
@@ -1449,12 +1476,12 @@
 
     minH := self usableHeight.
     self monitorBounds do:[:eachBounds |
-	minH := minH min: eachBounds height.
+        minH := minH min: eachBounds height.
     ].
     ^ minH
 
     "
-	Display smallestMonitorHeight
+        Display smallestMonitorHeight
     "
 !
 
@@ -1469,7 +1496,7 @@
     Display *dpy;
 
     if (! ISCONNECTED) {
-	RETURN (nil);
+        RETURN (nil);
     }
 
     dpy = myDpy;
@@ -1481,30 +1508,30 @@
 %}.
     formatArray := Array new:nFormats.
     1 to:nFormats do:[:index |
-	|info bitsPerPixelInfo depthInfo paddingInfo i|
-
-	i := index.
-%{
-	ScreenFormat *format;
-	Display *dpy = myDpy;
+        |info bitsPerPixelInfo depthInfo paddingInfo i|
+
+        i := index.
+%{
+        ScreenFormat *format;
+        Display *dpy = myDpy;
 
 #ifdef NO_PRIVATE_DISPLAY_ACCESS
-	depthInfo = __MKSMALLINT(1);
-	bitsPerPixelInfo = __MKSMALLINT(1);
-	paddingInfo = __MKSMALLINT(8);
+        depthInfo = __MKSMALLINT(1);
+        bitsPerPixelInfo = __MKSMALLINT(1);
+        paddingInfo = __MKSMALLINT(8);
 #else
-	format = DISPLAYACCESS(dpy)->pixmap_format;
-	format += (__intVal(i)-1);
-	bitsPerPixelInfo = __MKSMALLINT(format->bits_per_pixel);
-	depthInfo = __MKSMALLINT(format->depth);
-	paddingInfo = __MKSMALLINT(format->scanline_pad);
-#endif
-%}.
-	info := IdentityDictionary new.
-	info at:#depth put:depthInfo.
-	info at:#bitsPerPixel put:bitsPerPixelInfo.
-	info at:#padding put:paddingInfo.
-	formatArray at:index put:info.
+        format = DISPLAYACCESS(dpy)->pixmap_format;
+        format += (__intVal(i)-1);
+        bitsPerPixelInfo = __MKSMALLINT(format->bits_per_pixel);
+        depthInfo = __MKSMALLINT(format->depth);
+        paddingInfo = __MKSMALLINT(format->scanline_pad);
+#endif
+%}.
+        info := IdentityDictionary new.
+        info at:#depth put:depthInfo.
+        info at:#bitsPerPixel put:bitsPerPixelInfo.
+        info at:#padding put:paddingInfo.
+        formatArray at:index put:info.
     ].
     ^ formatArray
 
@@ -1589,8 +1616,8 @@
 
     h := (self monitorBoundsAt:aPoint) height.
     OperatingSystem isOSXlike ifTrue:[
-	"/ take away some space for the icon-panel at the bottom.
-	^ h - 50
+        "/ take away some space for the icon-panel at the bottom.
+        ^ h - 50
     ].
     ^ h
 
@@ -1613,7 +1640,7 @@
 
     bitmapId := self primCreateBitmapFromArray:anArray width:w height:h.
     bitmapId isNil ifTrue:[
-	self primitiveFailedOrClosedConnection
+        self primitiveFailedOrClosedConnection
     ].
     ^ bitmapId
 !
@@ -1628,35 +1655,35 @@
 
     if (ISCONNECTED
      && __isStringLike(aString)) {
-	Display *dpy = myDpy;
-	char *filename;
-	int status;
-	Pixmap newBitmap;
-	unsigned b_width, b_height;
-	int b_x_hot, b_y_hot;
-
-	filename = (char *) __stringVal(aString);
-
-
-	ENTER_XLIB();
-	status = XReadBitmapFile(dpy, RootWindow(dpy, screen),
-				 filename, &b_width, &b_height, &newBitmap,
-				 &b_x_hot, &b_y_hot);
-	LEAVE_XLIB();
-
-
-	if ((status == BitmapSuccess)  && newBitmap) {
+        Display *dpy = myDpy;
+        char *filename;
+        int status;
+        Pixmap newBitmap;
+        unsigned b_width, b_height;
+        int b_x_hot, b_y_hot;
+
+        filename = (char *) __stringVal(aString);
+
+
+        ENTER_XLIB();
+        status = XReadBitmapFile(dpy, RootWindow(dpy, screen),
+                                 filename, &b_width, &b_height, &newBitmap,
+                                 &b_x_hot, &b_y_hot);
+        LEAVE_XLIB();
+
+
+        if ((status == BitmapSuccess)  && newBitmap) {
 #ifdef COUNT_RESOURCES
-	    __cnt_bitmap++;
-#endif
-	    w = __MKSMALLINT(b_width);
-	    h = __MKSMALLINT(b_height);
-	    id = __MKEXTERNALADDRESS(newBitmap);
-	}
+            __cnt_bitmap++;
+#endif
+            w = __MKSMALLINT(b_width);
+            h = __MKSMALLINT(b_height);
+            id = __MKEXTERNALADDRESS(newBitmap);
+        }
     }
 %}.
     id notNil ifTrue:[
-	aForm setWidth:w height:h
+        aForm setWidth:w height:h
     ].
     ^ id
 !
@@ -1672,19 +1699,19 @@
     Pixmap newBitmap;
 
     if (__bothSmallInteger(w, h) && ISCONNECTED) {
-	Display *dpy = myDpy;
-
-
-	ENTER_XLIB();
-	newBitmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
-				       __intVal(w), __intVal(h), 1);
-	LEAVE_XLIB();
+        Display *dpy = myDpy;
+
+
+        ENTER_XLIB();
+        newBitmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
+                                       __intVal(w), __intVal(h), 1);
+        LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	if (newBitmap)
-	    __cnt_bitmap++;
-#endif
-
-	RETURN ( (newBitmap != (Pixmap)0) ? __MKEXTERNALADDRESS(newBitmap) : nil );
+        if (newBitmap)
+            __cnt_bitmap++;
+#endif
+
+        RETURN ( (newBitmap != (Pixmap)0) ? __MKEXTERNALADDRESS(newBitmap) : nil );
     }
 %}.
     self primitiveFailedOrClosedConnection.
@@ -1702,19 +1729,19 @@
     Pixmap newBitmap;
 
     if (__bothSmallInteger(w, h) && ISCONNECTED) {
-	Display *dpy = myDpy;
-
-
-	ENTER_XLIB();
-	newBitmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
-				       __intVal(w), __intVal(h), __intVal(d));
-	LEAVE_XLIB();
+        Display *dpy = myDpy;
+
+
+        ENTER_XLIB();
+        newBitmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
+                                       __intVal(w), __intVal(h), __intVal(d));
+        LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	if (newBitmap)
-	    __cnt_bitmap++;
-#endif
-
-	RETURN ( (newBitmap != (Pixmap)0) ? __MKEXTERNALADDRESS(newBitmap) : nil );
+        if (newBitmap)
+            __cnt_bitmap++;
+#endif
+
+        RETURN ( (newBitmap != (Pixmap)0) ? __MKEXTERNALADDRESS(newBitmap) : nil );
     }
 %}.
     self primitiveFailedOrClosedConnection.
@@ -1743,7 +1770,7 @@
      vBgForm deepForm preferredVisual preferredDepth
      wiconId wiconMaskId wiconViewId windowGroupWindowId|
 
-    displayId isNil ifTrue:[
+    self isOpen ifFalse:[
 	self primitiveFailedOrClosedConnection.
 	^ nil
     ].
@@ -2141,25 +2168,25 @@
      * ignore closed connection
      */
     if (! ISCONNECTED) {
-	RETURN ( self );
+        RETURN ( self );
     }
 
     if (__isExternalAddress(aGCId)) {
-	GC gc = __GCVal(aGCId);
-
-	if (gc) {
-	    __ExternalAddressInstPtr(aGCId)->e_address = NULL;
-
-	    ENTER_XLIB();
-	    XFreeGC(myDpy, gc);
-	    LEAVE_XLIB();
+        GC gc = __GCVal(aGCId);
+
+        if (gc) {
+            __ExternalAddressInstPtr(aGCId)->e_address = NULL;
+
+            ENTER_XLIB();
+            XFreeGC(myDpy, gc);
+            LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	    __cnt_gc--;
-#endif
-	} else {
-	    console_fprintf(stderr, "XWorkstation [warning]: trying to destroy GC twice\n");
-	}
-	RETURN ( self );
+            __cnt_gc--;
+#endif
+        } else {
+            console_fprintf(stderr, "XWorkstation [warning]: trying to destroy GC twice\n");
+        }
+        RETURN ( self );
     }
 %}.
     self primitiveFailed
@@ -2173,31 +2200,31 @@
      * ignore closed connection
      */
     if (! ISCONNECTED) {
-	RETURN ( self );
+        RETURN ( self );
     }
 
     if (__isExternalAddress(aDrawableId)) {
-	Pixmap pix = __PixmapVal(aDrawableId);
-
-	if (pix) {
-
-	    ENTER_XLIB();
-	    XFreePixmap(myDpy, pix);
-	    LEAVE_XLIB();
+        Pixmap pix = __PixmapVal(aDrawableId);
+
+        if (pix) {
+
+            ENTER_XLIB();
+            XFreePixmap(myDpy, pix);
+            LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	    __cnt_bitmap--;
-#endif
-
-	}
-	RETURN ( self );
+            __cnt_bitmap--;
+#endif
+
+        }
+        RETURN ( self );
     }
 %}.
     self primitiveFailed
 !
 
-destroyView:aView withId:aWindowId
-    self primDestroyView:aView withId:aWindowId.
-    self removeKnownView:aView withId:aWindowId.
+destroyView:aViewOrNil withId:aWindowId
+    self primDestroyViewWithId:aWindowId.
+    self removeKnownView:aViewOrNil withId:aWindowId.
 !
 
 dpsContextFor:aDrawableId and:aGCId
@@ -2214,16 +2241,16 @@
      && __isExternalAddress(aGCId)
      && ISCONNECTED) {
 
-	ENTER_XLIB();
-	dps = XDPSCreateContext(myDpy, __DrawableVal(aDrawableId),
-				       __GCVal(aGCId),
-				       0, height, 0, colormap, NULL, 0,
-				       XDPSDefaultTextBackstop,
-				       XDPSDefaultErrorProc,
-				       NULL);
-	LEAVE_XLIB();
-
-	RETURN ( dps ? __MKEXTERNALADDRESS(dps) : nil );
+        ENTER_XLIB();
+        dps = XDPSCreateContext(myDpy, __DrawableVal(aDrawableId),
+                                       __GCVal(aGCId),
+                                       0, height, 0, colormap, NULL, 0,
+                                       XDPSDefaultTextBackstop,
+                                       XDPSDefaultErrorProc,
+                                       NULL);
+        LEAVE_XLIB();
+
+        RETURN ( dps ? __MKEXTERNALADDRESS(dps) : nil );
     }
 #endif
 %}.
@@ -2240,16 +2267,16 @@
 
     if (__isExternalAddress(aDrawableId) && ISCONNECTED) {
 
-	ENTER_XLIB();
-	gc = XCreateGC(myDpy, __DrawableVal(aDrawableId), 0L, (XGCValues *)0);
-	LEAVE_XLIB();
+        ENTER_XLIB();
+        gc = XCreateGC(myDpy, __DrawableVal(aDrawableId), 0L, (XGCValues *)0);
+        LEAVE_XLIB();
 
 #ifdef COUNT_RESOURCES
-	if (gc)
-	    __cnt_gc++;
-#endif
-
-	RETURN ( gc ? __MKEXTERNALADDRESS(gc) : nil );
+        if (gc)
+            __cnt_gc++;
+#endif
+
+        RETURN ( gc ? __MKEXTERNALADDRESS(gc) : nil );
     }
 %}.
     self primitiveFailedOrClosedConnection.
@@ -2286,86 +2313,86 @@
     int bytesPerRow;
 
     if (! ISCONNECTED) {
-	RETURN (nil);
+        RETURN (nil);
     }
 
     dpy = myDpy;
     if (firstCall) {
-	for (index=0; index < 256; index++) {
-	    int t = 0;
-
-	    if (index & 128) t |=   1;
-	    if (index &  64) t |=   2;
-	    if (index &  32) t |=   4;
-	    if (index &  16) t |=   8;
-	    if (index &   8) t |=  16;
-	    if (index &   4) t |=  32;
-	    if (index &   2) t |=  64;
-	    if (index &   1) t |= 128;
-
-	    reverseBitTable[index] = t;
-	}
-	firstCall = 0;
+        for (index=0; index < 256; index++) {
+            int t = 0;
+
+            if (index & 128) t |=   1;
+            if (index &  64) t |=   2;
+            if (index &  32) t |=   4;
+            if (index &  16) t |=   8;
+            if (index &   8) t |=  16;
+            if (index &   4) t |=  32;
+            if (index &   2) t |=  64;
+            if (index &   1) t |= 128;
+
+            reverseBitTable[index] = t;
+        }
+        firstCall = 0;
     }
 
     if (__bothSmallInteger(w, h) && _isNonNilObject(anArray)) {
-	newBitmap = (Pixmap)0;
-	b_width = __intVal(w);
-	b_height = __intVal(h);
-	bytesPerRow = (b_width + 7) / 8;
-	nBytes = b_height * bytesPerRow;
-	if (nBytes < sizeof(fastBits)) {
-	    cp = b_bits = fastBits;
-	    allocatedBits = 0;
-	} else {
-	    cp = b_bits = allocatedBits = (unsigned char *) malloc(nBytes);
-	    if (! cp) goto fail;
-	}
-
-	if (__isArrayLike(anArray)) {
-	    index = 1;
-	    op = &(__ArrayInstPtr(anArray)->a_element[index - 1]);
-	    for (row = b_height; row; row--) {
-		for (col = bytesPerRow; col; col--) {
-		    num = *op++;
-		    if (__isSmallInteger(num)) {
-			bits = __intVal(num);
-		    } else {
-			bits = __longIntVal(num);
-			if (bits == 0) {
-			    goto fail;
-			}
-		    }
-		    *cp++ = reverseBitTable[bits & 0xFF];
-		}
-	    }
-	} else {
-	    if (__isByteArrayLike(anArray)) {
-		pBits = __ByteArrayInstPtr(anArray)->ba_element;
-		for (col = b_height*bytesPerRow; col; col--) {
-		    *cp++ = reverseBitTable[*pBits++];
-		}
-	    } else {
-		goto fail;
-	    }
-	}
-
-
-	ENTER_XLIB();
-	newBitmap = XCreateBitmapFromData(dpy, RootWindow(dpy, screen),
-					       (char *)b_bits,
-					       b_width, b_height);
-	LEAVE_XLIB();
+        newBitmap = (Pixmap)0;
+        b_width = __intVal(w);
+        b_height = __intVal(h);
+        bytesPerRow = (b_width + 7) / 8;
+        nBytes = b_height * bytesPerRow;
+        if (nBytes < sizeof(fastBits)) {
+            cp = b_bits = fastBits;
+            allocatedBits = 0;
+        } else {
+            cp = b_bits = allocatedBits = (unsigned char *) malloc(nBytes);
+            if (! cp) goto fail;
+        }
+
+        if (__isArrayLike(anArray)) {
+            index = 1;
+            op = &(__ArrayInstPtr(anArray)->a_element[index - 1]);
+            for (row = b_height; row; row--) {
+                for (col = bytesPerRow; col; col--) {
+                    num = *op++;
+                    if (__isSmallInteger(num)) {
+                        bits = __intVal(num);
+                    } else {
+                        bits = __longIntVal(num);
+                        if (bits == 0) {
+                            goto fail;
+                        }
+                    }
+                    *cp++ = reverseBitTable[bits & 0xFF];
+                }
+            }
+        } else {
+            if (__isByteArrayLike(anArray)) {
+                pBits = __ByteArrayInstPtr(anArray)->ba_element;
+                for (col = b_height*bytesPerRow; col; col--) {
+                    *cp++ = reverseBitTable[*pBits++];
+                }
+            } else {
+                goto fail;
+            }
+        }
+
+
+        ENTER_XLIB();
+        newBitmap = XCreateBitmapFromData(dpy, RootWindow(dpy, screen),
+                                               (char *)b_bits,
+                                               b_width, b_height);
+        LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	if (newBitmap)
-	    __cnt_bitmap++;
+        if (newBitmap)
+            __cnt_bitmap++;
 #endif
 
 
 fail: ;
-	if (allocatedBits)
-	    free(allocatedBits);
-	RETURN ( newBitmap ? __MKEXTERNALADDRESS(newBitmap) : nil );
+        if (allocatedBits)
+            free(allocatedBits);
+        RETURN ( newBitmap ? __MKEXTERNALADDRESS(newBitmap) : nil );
     }
 %}.
     ^ nil
@@ -2378,7 +2405,7 @@
 
 !
 
-primDestroyView:aView withId:aWindowId
+primDestroyViewWithId:aWindowId
     <context: #return>
 %{
     if (! ISCONNECTED) {
@@ -2436,14 +2463,14 @@
 
     s := aString ? ''.
     s isString ifFalse:[
-	s := s asStringWithCRsFrom:1 to:(s size) compressTabs:false withCR:false
+        s := s asStringWithCRsFrom:1 to:(s size) compressTabs:false withCR:false
     ].
 
     viewID := aView id.
     viewID notNil ifTrue:[ "/ if the view is not already closed
-	"/ for now - should add support to pass emphasis information too
-	s := s string.
-	self setPrimaryText:s owner:viewID.
+        "/ for now - should add support to pass emphasis information too
+        s := s string.
+        self setPrimaryText:s owner:viewID.
     ]
 
     "Created: / 27-03-2012 / 14:46:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
@@ -2464,20 +2491,20 @@
     Status ok;
 
     if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-
-	ENTER_XLIB();
-	ok = XAllocColorCells(dpy, DefaultColormap(dpy, screen), (Bool)0,
-				   &dummy, 0, &color.pixel, 1);
-	LEAVE_XLIB();
-
-	if (ok) {
+        Display *dpy = myDpy;
+
+
+        ENTER_XLIB();
+        ok = XAllocColorCells(dpy, DefaultColormap(dpy, screen), (Bool)0,
+                                   &dummy, 0, &color.pixel, 1);
+        LEAVE_XLIB();
+
+        if (ok) {
 #ifdef COUNT_RESOURCES
-	    __cnt_color++;
-#endif
-	    RETURN ( __MKSMALLINT(color.pixel) );
-	}
+            __cnt_color++;
+#endif
+            RETURN ( __MKSMALLINT(color.pixel) );
+        }
     }
 %}.
     ^ nil
@@ -2498,35 +2525,35 @@
 
     if (ISCONNECTED
      && __isStringLike(aString)) {
-	Display *dpy = myDpy;
-
-	colorname = (char *) __stringVal(aString);
-
-
-	ENTER_XLIB();
-	ok = XParseColor(dpy, DefaultColormap(dpy, screen), colorname, &ecolor);
-	LEAVE_XLIB();
-	if (ok) {
+        Display *dpy = myDpy;
+
+        colorname = (char *) __stringVal(aString);
+
+
+        ENTER_XLIB();
+        ok = XParseColor(dpy, DefaultColormap(dpy, screen), colorname, &ecolor);
+        LEAVE_XLIB();
+        if (ok) {
 #ifdef QUICK_TRUE_COLORS
-	    if (__INST(visualType) == @symbol(TrueColor)) {
-		id = ((ecolor.red >> (16 - __intVal(__INST(bitsRed)))) << __intVal(__INST(redShift))) & __intVal(__INST(redMask));
-		id += ((ecolor.green >> (16 - __intVal(__INST(bitsGreen)))) << __intVal(__INST(greenShift))) & __intVal(__INST(greenMask));
-		id += ((ecolor.blue >> (16 - __intVal(__INST(bitsBlue)))) << __intVal(__INST(blueShift))) & __intVal(__INST(blueMask));
-		RETURN ( __MKSMALLINT(id) );
-	    }
-#endif
-	    ENTER_XLIB();
-	    ok = XAllocColor(dpy, DefaultColormap(dpy, screen), &ecolor);
-	    LEAVE_XLIB();
-	}
-
-	if (! ok) {
-	    RETURN ( nil );
-	}
+            if (__INST(visualType) == @symbol(TrueColor)) {
+                id = ((ecolor.red >> (16 - __intVal(__INST(bitsRed)))) << __intVal(__INST(redShift))) & __intVal(__INST(redMask));
+                id += ((ecolor.green >> (16 - __intVal(__INST(bitsGreen)))) << __intVal(__INST(greenShift))) & __intVal(__INST(greenMask));
+                id += ((ecolor.blue >> (16 - __intVal(__INST(bitsBlue)))) << __intVal(__INST(blueShift))) & __intVal(__INST(blueMask));
+                RETURN ( __MKSMALLINT(id) );
+            }
+#endif
+            ENTER_XLIB();
+            ok = XAllocColor(dpy, DefaultColormap(dpy, screen), &ecolor);
+            LEAVE_XLIB();
+        }
+
+        if (! ok) {
+            RETURN ( nil );
+        }
 #ifdef COUNT_RESOURCES
-	__cnt_color++;
-#endif
-	RETURN ( __MKSMALLINT(ecolor.pixel) );
+        __cnt_color++;
+#endif
+        RETURN ( __MKSMALLINT(ecolor.pixel) );
     }
 %}.
     ^ super colorNamed:aString
@@ -2546,30 +2573,30 @@
     if (__bothSmallInteger(r, g)
      && __isSmallInteger(b)
      && ISCONNECTED) {
-	ecolor.red = __intVal(r);
-	ecolor.green= __intVal(g);
-	ecolor.blue = __intVal(b);
+        ecolor.red = __intVal(r);
+        ecolor.green= __intVal(g);
+        ecolor.blue = __intVal(b);
 #ifdef QUICK_TRUE_COLORS
-	if (__INST(visualType) == @symbol(TrueColor)) {
-	    id = ((ecolor.red >> (16 - __intVal(__INST(bitsRed)))) << __intVal(__INST(redShift))) & __intVal(__INST(redMask));
-	    id += ((ecolor.green >> (16 - __intVal(__INST(bitsGreen)))) << __intVal(__INST(greenShift))) & __intVal(__INST(greenMask));
-	    id += ((ecolor.blue >> (16 - __intVal(__INST(bitsBlue)))) << __intVal(__INST(blueShift))) & __intVal(__INST(blueMask));
-	    RETURN ( __MKSMALLINT(id) );
-	}
-#endif
-	dpy = myDpy;
-
-	ENTER_XLIB();
-	ok = XAllocColor(dpy, DefaultColormap(dpy, screen), &ecolor);
-	LEAVE_XLIB();
-
-	if (! ok) {
-	    RETURN ( nil );
-	}
+        if (__INST(visualType) == @symbol(TrueColor)) {
+            id = ((ecolor.red >> (16 - __intVal(__INST(bitsRed)))) << __intVal(__INST(redShift))) & __intVal(__INST(redMask));
+            id += ((ecolor.green >> (16 - __intVal(__INST(bitsGreen)))) << __intVal(__INST(greenShift))) & __intVal(__INST(greenMask));
+            id += ((ecolor.blue >> (16 - __intVal(__INST(bitsBlue)))) << __intVal(__INST(blueShift))) & __intVal(__INST(blueMask));
+            RETURN ( __MKSMALLINT(id) );
+        }
+#endif
+        dpy = myDpy;
+
+        ENTER_XLIB();
+        ok = XAllocColor(dpy, DefaultColormap(dpy, screen), &ecolor);
+        LEAVE_XLIB();
+
+        if (! ok) {
+            RETURN ( nil );
+        }
 #ifdef COUNT_RESOURCES
-	__cnt_color++;
-#endif
-	RETURN ( __MKSMALLINT(ecolor.pixel) );
+        __cnt_color++;
+#endif
+        RETURN ( __MKSMALLINT(ecolor.pixel) );
     }
 %}.
     ^ super colorScaledRed:r scaledGreen:g scaledBlue:b
@@ -2600,8 +2627,8 @@
 
 #ifdef QUICK_TRUE_COLORS
     if (__INST(visualType) == @symbol(TrueColor)) {
-	/* no need to do anything on TrueColor displays ... */
-	RETURN (self);
+        /* no need to do anything on TrueColor displays ... */
+        RETURN (self);
     }
 #endif
 
@@ -2609,21 +2636,21 @@
      * ignore closed connection
      */
     if (! ISCONNECTED) {
-	RETURN (self);
+        RETURN (self);
     }
 
     if (__isSmallInteger(colorIndex)) {
-	dpy = myDpy;
-	color = (long) __intVal(colorIndex);
-
-	ENTER_XLIB();
-	XFreeColors(dpy, DefaultColormap(dpy, screen), &color, 1, 0L);
-	LEAVE_XLIB();
+        dpy = myDpy;
+        color = (long) __intVal(colorIndex);
+
+        ENTER_XLIB();
+        XFreeColors(dpy, DefaultColormap(dpy, screen), &color, 1, 0L);
+        LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	__cnt_color--;
-#endif
-
-	RETURN ( self );
+        __cnt_color--;
+#endif
+
+        RETURN ( self );
     }
 %}.
     self primitiveFailed
@@ -2642,29 +2669,29 @@
 
     if (ISCONNECTED
      && __isSmallInteger(index)) {
-	Display *dpy = myDpy;
-
-	color.pixel = __intVal(index);
-
-	ENTER_XLIB();
-	XQueryColor(dpy, DefaultColormap(dpy, screen), &color);
-	LEAVE_XLIB();
-
-
-	/*
-	 * have to compensate for an error in X ?, which does not scale
-	 * colors correctly if lesser than 16bits are valid in a color,
-	 * (for example, color white on a 4bitsPerRGB server will Return
-	 * (16rF000 16rF000 16rF000) instead of (16rFFFF 16rFFFF 16rFFFF)
-	 */
-	bits = __intVal(__INST(bitsPerRGB));
-	scale = (1<<bits) - 1;
-	shift = 16 - bits;
-
-	sr = ((double)(color.red>>shift) / scale) * 0xFFFF;
-	sg = ((double)(color.green>>shift) / scale) * 0xFFFF;
-	sb = ((double)(color.blue>>shift) / scale) * 0xFFFF;
-	RETURN ( __ARRAY_WITH3(__MKSMALLINT(sr), __MKSMALLINT(sg), __MKSMALLINT(sb)));
+        Display *dpy = myDpy;
+
+        color.pixel = __intVal(index);
+
+        ENTER_XLIB();
+        XQueryColor(dpy, DefaultColormap(dpy, screen), &color);
+        LEAVE_XLIB();
+
+
+        /*
+         * have to compensate for an error in X ?, which does not scale
+         * colors correctly if lesser than 16bits are valid in a color,
+         * (for example, color white on a 4bitsPerRGB server will Return
+         * (16rF000 16rF000 16rF000) instead of (16rFFFF 16rFFFF 16rFFFF)
+         */
+        bits = __intVal(__INST(bitsPerRGB));
+        scale = (1<<bits) - 1;
+        shift = 16 - bits;
+
+        sr = ((double)(color.red>>shift) / scale) * 0xFFFF;
+        sg = ((double)(color.green>>shift) / scale) * 0xFFFF;
+        sb = ((double)(color.blue>>shift) / scale) * 0xFFFF;
+        RETURN ( __ARRAY_WITH3(__MKSMALLINT(sr), __MKSMALLINT(sg), __MKSMALLINT(sb)));
     }
 %}.
     ^ super getScaledRGBFrom:index
@@ -2683,39 +2710,39 @@
 
     if (ISCONNECTED
      && __isStringLike(colorName)) {
-	Display *dpy = myDpy;
-
-
-	if (XParseColor(dpy, DefaultColormap(dpy, screen),
-			     (char *) __stringVal(colorName), &color)) {
-	    /*
-	     * have to compensate for an error in X ?, which does not scale
-	     * colors correctly if lesser than 16bits are valid in a color,
-	     * (for example, color white on a 4bitsPerRGB server will Return
-	     * (16rF000 16rF000 16rF000) instead of (16rFFFF 16rFFFF 16rFFFF)
-	     */
-	    bits = __intVal(__INST(bitsPerRGB));
-	    scale = (1<<bits) - 1;
-	    shift = 16 - bits;
-
-	    /* do assignment to doubles (no cast) - avoid alignment problems in HPPA */
-	    dr = color.red>>shift;
-	    dg = color.green>>shift;
-	    db = color.blue>>shift;
-
-	    sr = (dr / scale) * 0xFFFF;
-	    sg = (dg / scale) * 0xFFFF;
-	    sb = (db / scale) * 0xFFFF;
-	    RETURN ( __ARRAY_WITH3(__MKSMALLINT(sr), __MKSMALLINT(sg), __MKSMALLINT(sb)));
-	}
+        Display *dpy = myDpy;
+
+
+        if (XParseColor(dpy, DefaultColormap(dpy, screen),
+                             (char *) __stringVal(colorName), &color)) {
+            /*
+             * have to compensate for an error in X ?, which does not scale
+             * colors correctly if lesser than 16bits are valid in a color,
+             * (for example, color white on a 4bitsPerRGB server will Return
+             * (16rF000 16rF000 16rF000) instead of (16rFFFF 16rFFFF 16rFFFF)
+             */
+            bits = __intVal(__INST(bitsPerRGB));
+            scale = (1<<bits) - 1;
+            shift = 16 - bits;
+
+            /* do assignment to doubles (no cast) - avoid alignment problems in HPPA */
+            dr = color.red>>shift;
+            dg = color.green>>shift;
+            db = color.blue>>shift;
+
+            sr = (dr / scale) * 0xFFFF;
+            sg = (dg / scale) * 0xFFFF;
+            sb = (db / scale) * 0xFFFF;
+            RETURN ( __ARRAY_WITH3(__MKSMALLINT(sr), __MKSMALLINT(sg), __MKSMALLINT(sb)));
+        }
 
     }
 %}.
     ^ super getScaledRGBFromName:colorName
 
     "
-	Screen current getScaledRGBFromName:'red'
-	Screen current getScaledRGBFromName:'orange'
+        Screen current getScaledRGBFromName:'red'
+        Screen current getScaledRGBFromName:'orange'
     "
 !
 
@@ -2730,22 +2757,22 @@
     aStream isNil ifTrue:[^ nil].
     list := OrderedCollection new.
     [aStream atEnd] whileFalse:[
-	line := aStream nextLine.
-	line notNil ifTrue:[
-	    "skip the r/g/b numbers"
-	    index := 1.
-	    [(line at:index) isSeparator] whileTrue:[index := index + 1].
-	    [(line at:index) isDigit] whileTrue:[index := index + 1].
-	    [(line at:index) isSeparator] whileTrue:[index := index + 1].
-	    [(line at:index) isDigit] whileTrue:[index := index + 1].
-	    [(line at:index) isSeparator] whileTrue:[index := index + 1].
-	    [(line at:index) isDigit] whileTrue:[index := index + 1].
-	    [(line at:index) isSeparator] whileTrue:[index := index + 1].
-	    colorName := line copyFrom:index.
-	    ((colorName occurrencesOf:(Character space)) == 0) ifTrue:[
-		list add:colorName
-	    ]
-	]
+        line := aStream nextLine.
+        line notNil ifTrue:[
+            "skip the r/g/b numbers"
+            index := 1.
+            [(line at:index) isSeparator] whileTrue:[index := index + 1].
+            [(line at:index) isDigit] whileTrue:[index := index + 1].
+            [(line at:index) isSeparator] whileTrue:[index := index + 1].
+            [(line at:index) isDigit] whileTrue:[index := index + 1].
+            [(line at:index) isSeparator] whileTrue:[index := index + 1].
+            [(line at:index) isDigit] whileTrue:[index := index + 1].
+            [(line at:index) isSeparator] whileTrue:[index := index + 1].
+            colorName := line copyFrom:index.
+            ((colorName occurrencesOf:(Character space)) == 0) ifTrue:[
+                list add:colorName
+            ]
+        ]
     ].
     aStream close.
     ^ list sort
@@ -2765,10 +2792,10 @@
 %{  /* NOCONTEXT */
 
     if (__isSmallInteger(aPercentage)) {
-	RETURN ( __MKSMALLINT(0xFFFF * __intVal(aPercentage) / 100) );
+        RETURN ( __MKSMALLINT(0xFFFF * __intVal(aPercentage) / 100) );
     }
     if (__isFloat(aPercentage)) {
-	RETURN ( __MKSMALLINT(0xFFFF * (int)(__floatVal(aPercentage)) / 100) );
+        RETURN ( __MKSMALLINT(0xFFFF * (int)(__floatVal(aPercentage)) / 100) );
     }
 %}.
     ^ (16rFFFF * aPercentage / 100) rounded
@@ -2788,33 +2815,33 @@
     int ok = 1;
 
     if (__isSmallInteger(sred))
-	r = __intVal(sred);
+        r = __intVal(sred);
     else ok = 0;
 
     if (__isSmallInteger(sgreen))
-	g = __intVal(sgreen);
+        g = __intVal(sgreen);
     else ok = 0;
 
     if (__isSmallInteger(sblue))
-	b = __intVal(sblue);
+        b = __intVal(sblue);
     else ok = 0;
 
     if (ISCONNECTED
      && __isSmallInteger(index) && ok) {
-	Display *dpy = myDpy;
-
-	color.pixel = __intVal(index);
-	color.red = r;
-	color.green = g;
-	color.blue = b;
-	color.flags = DoRed | DoGreen | DoBlue;
-
-
-	ENTER_XLIB();
-	XStoreColor(dpy, DefaultColormap(dpy, screen), &color);
-	LEAVE_XLIB();
-
-	RETURN ( self );
+        Display *dpy = myDpy;
+
+        color.pixel = __intVal(index);
+        color.red = r;
+        color.green = g;
+        color.blue = b;
+        color.flags = DoRed | DoGreen | DoBlue;
+
+
+        ENTER_XLIB();
+        XStoreColor(dpy, DefaultColormap(dpy, screen), &color);
+        LEAVE_XLIB();
+
+        RETURN ( self );
     }
 %}.
     self primitiveFailedOrClosedConnection
@@ -2831,30 +2858,30 @@
     "/ if you add something here, also add to #shapeNumberFromCursor ...
 
     ^ #(
-	#upLeftArrow            "/ XC_top_left_arrow
-	#upRightHand            "/ XC_hand1
-	#upDownArrow            "/ XC_sb_v_double_arrow
-	#leftRightArrow         "/ XC_sb_h_double_arrow
-	#upLimitArrow           "/ XC_top_side
-	#downLimitArrow         "/ XC_bottom_side
-	#leftLimitArrow         "/ XC_left_side
-	#rightLimitArrow        "/ XC_right_side
-	#text                   "/ XC_xterm
-	#upRightArrow           "/ XC_draft_large
-	#leftHand               "/ XC_hand2
-	#questionMark           "/ XC_question_arrow
-	#cross                  "/ XC_X_cursor
-	#wait                   "/ XC_watch
-	#crossHair              "/ XC_tcross
-	#origin                 "/ XC_ul_angle
-	#topLeft                "/ XC_ul_angle
-	#corner                 "/ XC_lr_angle
-	#bottomRight            "/ XC_lr_angle
-	#topRight               "/ XC_ur_angle
-	#bottomLeft             "/ XC_ll_angle
-	#square                 "/ XC_dotbox
-	#fourWay                "/ XC_fleur
-	#crossCursor            "/ XC_X_cursor
+        #upLeftArrow            "/ XC_top_left_arrow
+        #upRightHand            "/ XC_hand1
+        #upDownArrow            "/ XC_sb_v_double_arrow
+        #leftRightArrow         "/ XC_sb_h_double_arrow
+        #upLimitArrow           "/ XC_top_side
+        #downLimitArrow         "/ XC_bottom_side
+        #leftLimitArrow         "/ XC_left_side
+        #rightLimitArrow        "/ XC_right_side
+        #text                   "/ XC_xterm
+        #upRightArrow           "/ XC_draft_large
+        #leftHand               "/ XC_hand2
+        #questionMark           "/ XC_question_arrow
+        #cross                  "/ XC_X_cursor
+        #wait                   "/ XC_watch
+        #crossHair              "/ XC_tcross
+        #origin                 "/ XC_ul_angle
+        #topLeft                "/ XC_ul_angle
+        #corner                 "/ XC_lr_angle
+        #bottomRight            "/ XC_lr_angle
+        #topRight               "/ XC_ur_angle
+        #bottomLeft             "/ XC_ll_angle
+        #square                 "/ XC_dotbox
+        #fourWay                "/ XC_fleur
+        #crossCursor            "/ XC_X_cursor
       )
 
     "Created: 8.4.1997 / 10:12:30 / cg"
@@ -2883,18 +2910,18 @@
      && __bothSmallInteger(bgR, bgG)
      && __bothSmallInteger(bgB, fgR)) {
 
-	fgcolor.red = __intVal(fgR);
-	fgcolor.green= __intVal(fgG);
-	fgcolor.blue = __intVal(fgB);
-	bgcolor.red = __intVal(bgR);
-	bgcolor.green= __intVal(bgG);
-	bgcolor.blue = __intVal(bgB);
-
-	ENTER_XLIB();
-	XRecolorCursor(myDpy, __CursorVal(aCursorId), &fgcolor, &bgcolor);
-	LEAVE_XLIB();
-
-	RETURN ( self );
+        fgcolor.red = __intVal(fgR);
+        fgcolor.green= __intVal(fgG);
+        fgcolor.blue = __intVal(fgB);
+        bgcolor.red = __intVal(bgR);
+        bgcolor.green= __intVal(bgG);
+        bgcolor.blue = __intVal(bgB);
+
+        ENTER_XLIB();
+        XRecolorCursor(myDpy, __CursorVal(aCursorId), &fgcolor, &bgcolor);
+        LEAVE_XLIB();
+
+        RETURN ( self );
     }
 %}.
     self primitiveFailedOrClosedConnection
@@ -2916,10 +2943,10 @@
     "create a cursor given 2 bitmaps (source, mask) and a hotspot"
 
     ^ self
-	primCreateCursorSourceFormId:sourceForm id
-	maskFormId:maskForm id
-	hotX:hx hotY:hy
-	width:w height:h
+        primCreateCursorSourceFormId:sourceForm id
+        maskFormId:maskForm id
+        hotX:hx hotY:hy
+        width:w height:h
 !
 
 destroyCursor:aCursorId
@@ -2931,22 +2958,22 @@
      * ignore closed connection
      */
     if (! ISCONNECTED) {
-	RETURN ( self );
+        RETURN ( self );
     }
 
     if (__isExternalAddress(aCursorId)) {
-	Cursor curs = __CursorVal(aCursorId);
-
-	if (curs) {
-
-	    ENTER_XLIB();
-	    XFreeCursor(myDpy, curs);
-	    LEAVE_XLIB();
+        Cursor curs = __CursorVal(aCursorId);
+
+        if (curs) {
+
+            ENTER_XLIB();
+            XFreeCursor(myDpy, curs);
+            LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	    __cnt_cursor--;
-#endif
-	}
-	RETURN ( self );
+            __cnt_cursor--;
+#endif
+        }
+        RETURN ( self );
     }
 %}.
     self primitiveFailed
@@ -2966,17 +2993,17 @@
     if (ISCONNECTED
      && __isSmallInteger(aShapeNumber)) {
 
-	ENTER_XLIB();
-	newCursor = XCreateFontCursor(myDpy, __intVal(aShapeNumber));
-	LEAVE_XLIB();
+        ENTER_XLIB();
+        newCursor = XCreateFontCursor(myDpy, __intVal(aShapeNumber));
+        LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	if (newCursor)
-	    __cnt_cursor++;
-#endif
-
-	if (newCursor != (Cursor)0) {
-	    RETURN (__MKEXTERNALADDRESS(newCursor));
-	}
+        if (newCursor)
+            __cnt_cursor++;
+#endif
+
+        if (newCursor != (Cursor)0) {
+            RETURN (__MKEXTERNALADDRESS(newCursor));
+        }
     }
 %}.
     self primitiveFailedOrClosedConnection.
@@ -2995,28 +3022,28 @@
      && __isExternalAddress(sourceId)
      && __isExternalAddress(maskId)
      && __bothSmallInteger(hx, hy)) {
-	fgColor.red = 0;        /* fg is black */
-	fgColor.green = 0;
-	fgColor.blue = 0;
-	bgColor.red = 0xFFFF;   /* bg is white */
-	bgColor.green = 0xFFFF;
-	bgColor.blue = 0xFFFF;
-
-
-	ENTER_XLIB();
-	newCursor = XCreatePixmapCursor(myDpy,
-				__PixmapVal(sourceId),
-				__PixmapVal(maskId),
-				&fgColor, &bgColor, __intVal(hx), __intVal(hy));
-	LEAVE_XLIB();
+        fgColor.red = 0;        /* fg is black */
+        fgColor.green = 0;
+        fgColor.blue = 0;
+        bgColor.red = 0xFFFF;   /* bg is white */
+        bgColor.green = 0xFFFF;
+        bgColor.blue = 0xFFFF;
+
+
+        ENTER_XLIB();
+        newCursor = XCreatePixmapCursor(myDpy,
+                                __PixmapVal(sourceId),
+                                __PixmapVal(maskId),
+                                &fgColor, &bgColor, __intVal(hx), __intVal(hy));
+        LEAVE_XLIB();
 #ifdef COUNT_RESOURCES
-	if (newCursor)
-	    __cnt_cursor++;
-#endif
-
-	if (newCursor != (Cursor)0) {
-	    RETURN (__MKEXTERNALADDRESS(newCursor));
-	}
+        if (newCursor)
+            __cnt_cursor++;
+#endif
+
+        if (newCursor != (Cursor)0) {
+            RETURN (__MKEXTERNALADDRESS(newCursor));
+        }
     }
 %}.
     self primitiveFailedOrClosedConnection.
@@ -3071,128 +3098,128 @@
 
     (msgType := self atomIDOf:#DndProtocol) notNil ifTrue:[
 
-	"/ DND can drop files, file, dir, links, dirLink and text
-	"/ check for this.
-
-	dropObjects isCollection ifFalse:[
-	    dropColl := Array with:dropObjects
-	] ifTrue:[
-	    dropColl := dropObjects
-	].
-	anyFile := anyDir := anyText := anyOther := false.
-	dropColl do:[:aDropObject |
-	    aDropObject isFileObject ifTrue:[
-		aDropObject theObject isDirectory ifTrue:[
-		    anyDir := true
-		] ifFalse:[
-		    anyFile := true
-		]
-	    ] ifFalse:[
-		aDropObject isTextObject ifTrue:[
-		    anyText := true
-		] ifFalse:[
-		    anyOther := true
-		]
-	    ]
-	].
-
-	anyOther ifTrue:[
-	    "/ DND does not support this ...
-	    'XWorkstation [info]: DND can only drop files or text' infoPrintCR.
-	    ^ false
-	].
-	anyText ifTrue:[
-	    (anyFile or:[anyDir]) ifTrue:[
-		"/ DND does not support mixed types
-		'XWorkstation [info]: DND cannot drop both files and text' infoPrintCR.
-		^ false
-	    ]
-	].
-
-	dropCollSize := dropColl size.
-	anyFile ifTrue:[
-	    dropType := #DndFiles.
-	    dropCollSize == 1 ifTrue:[
-		dropType := #DndFile
-	    ]
-	] ifFalse:[
-	    anyDir ifTrue:[
-		dropType := #DndFiles.
-		dropCollSize == 1 ifTrue:[
-		    dropType := #DndDir
-		]
-	    ] ifFalse:[
-		anyText ifTrue:[
-		    dropCollSize == 1 ifTrue:[
-			dropType := #DndText
-		    ] ifFalse:[
-			"/ can only drop a single text object
-			'XWorkstation [info]: DND can only drop a single text' infoPrintCR.
-			^ false
-		    ]
-		] ifFalse:[
-		    "/ mhmh ...
-		    'XWorkstation [info]: DND cannot drop this' infoPrintCR.
-		    ^ false
-		]
-	    ]
-	].
-
-	dropTypeCode := self dndDropTypes indexOf:dropType.
-	dropTypeCode == 0 ifTrue:[
-	    'XWorkstation [info]: DND cannot drop this' infoPrintCR.
-	    ^ false
-	].
-	dropTypeCode := dropTypeCode - 1.
-
-
-	"/ place the selection inTo the DndSelection property
-	"/ of the rootView ...
-	"/ ... need a single string, with 0-terminated parts.
-
-	strings := OrderedCollection new.
-	sz := 0.
-	dropColl do:[:anObject |
-	    |s o|
-
-	    o := anObject theObject.
-	    anObject isFileObject ifTrue:[
-		o := o pathName
-	    ].
-	    s := o asString.
-	    strings add:s.
-	    sz := sz + (s size) + 1.
-	].
-	val := String new:sz.
-	idx := 1.
-	strings do:[:aString |
-	    |sz|
-
-	    sz := aString size.
-	    val replaceFrom:idx to:(idx + sz - 1) with:aString startingAt:1.
-	    idx := idx + sz.
-	    val at:idx put:(Character value:0).
-	    idx := idx + 1
-	].
-
-	self
-	    setProperty:(self atomIDOf:#DndSelection)
-	    type:(self atomIDOf:#STRING)
-	    value:val
-	    for:rootId.
-
-	^ self
-	    sendClientEvent:msgType
-	    format:32
-	    to:destinationId
-	    propagate:true
-	    eventMask:nil
-	    window:destinationId
-	    data1:dropTypeCode
-	    data2:0
-	    data3:destinationId
-	    data4:nil
-	    data5:nil.
+        "/ DND can drop files, file, dir, links, dirLink and text
+        "/ check for this.
+
+        dropObjects isCollection ifFalse:[
+            dropColl := Array with:dropObjects
+        ] ifTrue:[
+            dropColl := dropObjects
+        ].
+        anyFile := anyDir := anyText := anyOther := false.
+        dropColl do:[:aDropObject |
+            aDropObject isFileObject ifTrue:[
+                aDropObject theObject isDirectory ifTrue:[
+                    anyDir := true
+                ] ifFalse:[
+                    anyFile := true
+                ]
+            ] ifFalse:[
+                aDropObject isTextObject ifTrue:[
+                    anyText := true
+                ] ifFalse:[
+                    anyOther := true
+                ]
+            ]
+        ].
+
+        anyOther ifTrue:[
+            "/ DND does not support this ...
+            'XWorkstation [info]: DND can only drop files or text' infoPrintCR.
+            ^ false
+        ].
+        anyText ifTrue:[
+            (anyFile or:[anyDir]) ifTrue:[
+                "/ DND does not support mixed types
+                'XWorkstation [info]: DND cannot drop both files and text' infoPrintCR.
+                ^ false
+            ]
+        ].
+
+        dropCollSize := dropColl size.
+        anyFile ifTrue:[
+            dropType := #DndFiles.
+            dropCollSize == 1 ifTrue:[
+                dropType := #DndFile
+            ]
+        ] ifFalse:[
+            anyDir ifTrue:[
+                dropType := #DndFiles.
+                dropCollSize == 1 ifTrue:[
+                    dropType := #DndDir
+                ]
+            ] ifFalse:[
+                anyText ifTrue:[
+                    dropCollSize == 1 ifTrue:[
+                        dropType := #DndText
+                    ] ifFalse:[
+                        "/ can only drop a single text object
+                        'XWorkstation [info]: DND can only drop a single text' infoPrintCR.
+                        ^ false
+                    ]
+                ] ifFalse:[
+                    "/ mhmh ...
+                    'XWorkstation [info]: DND cannot drop this' infoPrintCR.
+                    ^ false
+                ]
+            ]
+        ].
+
+        dropTypeCode := self dndDropTypes indexOf:dropType.
+        dropTypeCode == 0 ifTrue:[
+            'XWorkstation [info]: DND cannot drop this' infoPrintCR.
+            ^ false
+        ].
+        dropTypeCode := dropTypeCode - 1.
+
+
+        "/ place the selection inTo the DndSelection property
+        "/ of the rootView ...
+        "/ ... need a single string, with 0-terminated parts.
+
+        strings := OrderedCollection new.
+        sz := 0.
+        dropColl do:[:anObject |
+            |s o|
+
+            o := anObject theObject.
+            anObject isFileObject ifTrue:[
+                o := o pathName
+            ].
+            s := o asString.
+            strings add:s.
+            sz := sz + (s size) + 1.
+        ].
+        val := String new:sz.
+        idx := 1.
+        strings do:[:aString |
+            |sz|
+
+            sz := aString size.
+            val replaceFrom:idx to:(idx + sz - 1) with:aString startingAt:1.
+            idx := idx + sz.
+            val at:idx put:(Character value:0).
+            idx := idx + 1
+        ].
+
+        self
+            setProperty:(self atomIDOf:#DndSelection)
+            type:(self atomIDOf:#STRING)
+            value:val
+            for:rootId.
+
+        ^ self
+            sendClientEvent:msgType
+            format:32
+            to:destinationId
+            propagate:true
+            eventMask:nil
+            window:destinationId
+            data1:dropTypeCode
+            data2:0
+            data3:destinationId
+            data4:nil
+            data5:nil.
     ].
 
     ^ false
@@ -3205,14 +3232,14 @@
     "return the dropTypes as supported by DND"
 
     ^ #(
-	    DndUnknown      "/ 0
-	    DndRawData      "/ 1
-	    DndFile         "/ 2
-	    DndFiles        "/ 3
-	    DndText         "/ 4
-	    DndDir          "/ 5
-	    DndLink         "/ 6
-	    DndExe          "/ 7
+            DndUnknown      "/ 0
+            DndRawData      "/ 1
+            DndFile         "/ 2
+            DndFiles        "/ 3
+            DndText         "/ 4
+            DndDir          "/ 5
+            DndLink         "/ 6
+            DndExe          "/ 7
        )
 
     "Created: 6.4.1997 / 12:57:56 / cg"
@@ -3227,11 +3254,11 @@
     "/ see, if the display supports the DND protocol ...
     "/
     (self atomIDOf:#DndProtocol) notNil ifTrue:[
-	^ self
-	    dndDrop:aCollectionOfDropObjects
-	    inWindowID:destinationId
-	    position:destinationPoint
-	    rootPosition:rootPoint
+        ^ self
+            dndDrop:aCollectionOfDropObjects
+            inWindowID:destinationId
+            position:destinationPoint
+            rootPosition:rootPoint
     ].
 
     "/ add more drag&drop protocols here.
@@ -3252,11 +3279,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3270,22 +3297,22 @@
      && __bothSmallInteger(w, h)
      && __bothSmallInteger(srcX, srcY)
      && __bothSmallInteger(dstX, dstY)) {
-	int _sX, _sY, _w, _h, _dX, _dY;
-
-	_sX = __intVal(srcX);
-	_sY = __intVal(srcY);
-	_w = __intVal(w);
-	_h = __intVal(h);
-	_dX = __intVal(dstX);
-	_dY = __intVal(dstY);
-
-	gc = __GCVal(dstGCId);
-	source = __DrawableVal(sourceId);
-	dest =   __DrawableVal(destId);
-	ENTER_XLIB();
-	XCopyArea(myDpy, source, dest, gc, _sX, _sY, _w, _h, _dX, _dY);
-	LEAVE_XLIB();
-	RETURN ( self );
+        int _sX, _sY, _w, _h, _dX, _dY;
+
+        _sX = __intVal(srcX);
+        _sY = __intVal(srcY);
+        _w = __intVal(w);
+        _h = __intVal(h);
+        _dX = __intVal(dstX);
+        _dY = __intVal(dstY);
+
+        gc = __GCVal(dstGCId);
+        source = __DrawableVal(sourceId);
+        dest =   __DrawableVal(destId);
+        ENTER_XLIB();
+        XCopyArea(myDpy, source, dest, gc, _sX, _sY, _w, _h, _dX, _dY);
+        LEAVE_XLIB();
+        RETURN ( self );
     }
 %}.
     "badGC, bad sourceDrawableId or destDrawableID
@@ -3304,11 +3331,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3322,20 +3349,20 @@
      && __bothSmallInteger(w, h)
      && __bothSmallInteger(srcX, srcY)
      && __bothSmallInteger(dstX, dstY)) {
-	Display *dpy = myDpy;
-
-	gc = __GCVal(dstGCId);
-	source = __DrawableVal(sourceId);
-	dest =   __DrawableVal(destId);
-	ENTER_XLIB();
-	XSetGraphicsExposures(dpy, gc, 0);
-	XCopyArea(dpy, source, dest, gc,
-				__intVal(srcX), __intVal(srcY),
-				__intVal(w), __intVal(h),
-				__intVal(dstX), __intVal(dstY));
-	XSetGraphicsExposures(dpy, gc, 1);
-	LEAVE_XLIB();
-	RETURN ( self );
+        Display *dpy = myDpy;
+
+        gc = __GCVal(dstGCId);
+        source = __DrawableVal(sourceId);
+        dest =   __DrawableVal(destId);
+        ENTER_XLIB();
+        XSetGraphicsExposures(dpy, gc, 0);
+        XCopyArea(dpy, source, dest, gc,
+                                __intVal(srcX), __intVal(srcY),
+                                __intVal(w), __intVal(h),
+                                __intVal(dstX), __intVal(dstY));
+        XSetGraphicsExposures(dpy, gc, 1);
+        LEAVE_XLIB();
+        RETURN ( self );
     }
 %}.
     "badGC, bad sourceDrawableId or destDrawableID
@@ -3354,11 +3381,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3372,16 +3399,16 @@
      && __bothSmallInteger(w, h)
      && __bothSmallInteger(srcX, srcY)
      && __bothSmallInteger(dstX, dstY)) {
-	gc = __GCVal(dstGCId);
-	source = __DrawableVal(sourceId);
-	dest =   __DrawableVal(destId);
-	ENTER_XLIB();
-	XCopyPlane(myDpy, source, dest, gc,
-				 __intVal(srcX), __intVal(srcY),
-				 __intVal(w), __intVal(h),
-				 __intVal(dstX), __intVal(dstY), 1);
-	LEAVE_XLIB();
-	RETURN ( self );
+        gc = __GCVal(dstGCId);
+        source = __DrawableVal(sourceId);
+        dest =   __DrawableVal(destId);
+        ENTER_XLIB();
+        XCopyPlane(myDpy, source, dest, gc,
+                                 __intVal(srcX), __intVal(srcY),
+                                 __intVal(w), __intVal(h),
+                                 __intVal(dstX), __intVal(dstY), 1);
+        LEAVE_XLIB();
+        RETURN ( self );
     }
 %}.
     "badGC, bad sourceDrawableId or destDrawableID
@@ -3401,11 +3428,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3419,20 +3446,20 @@
      && __bothSmallInteger(w, h)
      && __bothSmallInteger(srcX, srcY)
      && __bothSmallInteger(dstX, dstY)) {
-	Display *dpy = myDpy;
-
-	gc = __GCVal(dstGCId);
-	source = __DrawableVal(sourceId);
-	dest =   __DrawableVal(destId);
-	ENTER_XLIB();
-	XSetGraphicsExposures(dpy, gc, 0);
-	XCopyPlane(dpy, source, dest, gc,
-				 __intVal(srcX), __intVal(srcY),
-				 __intVal(w), __intVal(h),
-				 __intVal(dstX), __intVal(dstY), 1);
-	XSetGraphicsExposures(dpy, gc, 1);
-	LEAVE_XLIB();
-	RETURN ( self );
+        Display *dpy = myDpy;
+
+        gc = __GCVal(dstGCId);
+        source = __DrawableVal(sourceId);
+        dest =   __DrawableVal(destId);
+        ENTER_XLIB();
+        XSetGraphicsExposures(dpy, gc, 0);
+        XCopyPlane(dpy, source, dest, gc,
+                                 __intVal(srcX), __intVal(srcY),
+                                 __intVal(w), __intVal(h),
+                                 __intVal(dstX), __intVal(dstY), 1);
+        XSetGraphicsExposures(dpy, gc, 1);
+        LEAVE_XLIB();
+        RETURN ( self );
     }
 %}.
     "badGC, bad sourceDrawableId or destDrawableID
@@ -3448,11 +3475,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3462,23 +3489,23 @@
     double f;
 
     if (__isSmallInteger(startAngle))
-	angle1 = __intVal(startAngle) * 64;
+        angle1 = __intVal(startAngle) * 64;
     else if (__isFloat(startAngle)) {
-	f = __floatVal(startAngle);
-	angle1 = f * 64;
+        f = __floatVal(startAngle);
+        angle1 = f * 64;
     } else if (__isShortFloat(startAngle)) {
-	f = __shortFloatVal(startAngle);
-	angle1 = f * 64;
+        f = __shortFloatVal(startAngle);
+        angle1 = f * 64;
     } else goto bad;
 
     if (__isSmallInteger(angle))
-	angle2 = __intVal(angle) * 64;
+        angle2 = __intVal(angle) * 64;
     else if (__isFloat(angle)) {
-	f = __floatVal(angle);
-	angle2 = f * 64;
+        f = __floatVal(angle);
+        angle2 = f * 64;
     } else if (__isShortFloat(angle)) {
-	f = __shortFloatVal(angle);
-	angle2 = f * 64;
+        f = __shortFloatVal(angle);
+        angle2 = f * 64;
     } else goto bad;
 
     if (ISCONNECTED
@@ -3486,20 +3513,20 @@
      && __isExternalAddress(aDrawableId)
      && __bothSmallInteger(x, y)
      && __bothSmallInteger(width, height)) {
-	win = __WindowVal(aDrawableId);
-	gc = __GCVal(aGCId);
-	w = __intVal(width);
-	h = __intVal(height);
-	/*
-	 * need this check here: some servers simply dump core with bad args
-	 */
-	if ((w >= 0) && (h >= 0) && (angle1 >= 0) && (angle2 >= 0)) {
-	    ENTER_XLIB();
-	    XDrawArc(myDpy, win, gc, __intVal(x), __intVal(y),
-				   w, h, angle1, angle2);
-	    LEAVE_XLIB();
-	}
-	RETURN ( self );
+        win = __WindowVal(aDrawableId);
+        gc = __GCVal(aGCId);
+        w = __intVal(width);
+        h = __intVal(height);
+        /*
+         * need this check here: some servers simply dump core with bad args
+         */
+        if ((w >= 0) && (h >= 0) && (angle1 >= 0) && (angle2 >= 0)) {
+            ENTER_XLIB();
+            XDrawArc(myDpy, win, gc, __intVal(x), __intVal(y),
+                                   w, h, angle1, angle2);
+            LEAVE_XLIB();
+        }
+        RETURN ( self );
     }
     bad: ;
 %}.
@@ -3515,11 +3542,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3531,35 +3558,35 @@
      && __isExternalAddress(aDrawableId)
      && __bothSmallInteger(x0, y0)
      && __bothSmallInteger(x1, y1)) {
-	Display *dpy = myDpy;
-	int ix0, iy0, ix1, iy1;
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-
-	ix0 = __intVal(x0);
-	iy0 = __intVal(y0);
-	ix1 = __intVal(x1);
-	iy1 = __intVal(y1);
-
-	/* attention: coordinates in X are shorts and wrap; clamp here. */
-	if (ix0 > 0x7FFF) ix0 = 0x7FFF;
-	else if (ix0 < -0x8000) ix0 = -0x8000;
-	if (iy0 > 0x7FFF) iy0 = 0x7FFF;
-	else if (iy0 < -0x8000) iy0 = -0x8000;
-	if (ix1 > 0x7FFF) ix1 = 0x7FFF;
-	else if (ix1 < -0x8000) ix1 = -0x8000;
-	if (iy1 > 0x7FFF) iy1 = 0x7FFF;
-	else if (iy1 < -0x8000) iy1 = -0x8000;
-
-	ENTER_XLIB();
-	if ((ix0 == ix1) && (iy0 == iy1)) {
-	    /* little bit shorter X-lib message (better with slow connections...) */
-	    XDrawPoint(dpy, win, gc, ix0, iy0);
-	} else {
-	    XDrawLine(dpy, win, gc, ix0, iy0, ix1, iy1);
-	}
-	LEAVE_XLIB();
-	RETURN ( self );
+        Display *dpy = myDpy;
+        int ix0, iy0, ix1, iy1;
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+
+        ix0 = __intVal(x0);
+        iy0 = __intVal(y0);
+        ix1 = __intVal(x1);
+        iy1 = __intVal(y1);
+
+        /* attention: coordinates in X are shorts and wrap; clamp here. */
+        if (ix0 > 0x7FFF) ix0 = 0x7FFF;
+        else if (ix0 < -0x8000) ix0 = -0x8000;
+        if (iy0 > 0x7FFF) iy0 = 0x7FFF;
+        else if (iy0 < -0x8000) iy0 = -0x8000;
+        if (ix1 > 0x7FFF) ix1 = 0x7FFF;
+        else if (ix1 < -0x8000) ix1 = -0x8000;
+        if (iy1 > 0x7FFF) iy1 = 0x7FFF;
+        else if (iy1 < -0x8000) iy1 = -0x8000;
+
+        ENTER_XLIB();
+        if ((ix0 == ix1) && (iy0 == iy1)) {
+            /* little bit shorter X-lib message (better with slow connections...) */
+            XDrawPoint(dpy, win, gc, ix0, iy0);
+        } else {
+            XDrawLine(dpy, win, gc, ix0, iy0, ix1, iy1);
+        }
+        LEAVE_XLIB();
+        RETURN ( self );
     }
 %}.
     "badGC, badDrawable or coordinates not integer"
@@ -3576,15 +3603,15 @@
     |noY|
 
     (noY := yValues size) < 2 ifTrue:[
-	^ self
+        ^ self
     ].
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
     OBJ      yA, t;
@@ -3600,109 +3627,109 @@
     if (ISCONNECTED
      && __isExternalAddress(aGCId)
      && __isExternalAddress(aDrawableId) ) {
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-
-	if( __isSmallInteger(scaleY) )
-	    sY = (float) __intVal( scaleY );
-	else if (__isFloat(scaleY))
-	    sY = __floatVal( scaleY );
-	else if (__isShortFloat(scaleY))
-	    sY = __shortFloatVal( scaleY );
-	else {
-	    t = __SSEND0(scaleY, @symbol(asFloat), 0);
-	    if (! __isFloat(t)) goto fail;
-	    sY = __floatVal( t );
-	}
-
-	if( __isSmallInteger(transY) )
-	    tY = (float) __intVal( transY );
-	else if (__isFloat(transY))
-	    tY = __floatVal( transY );
-	else if (__isShortFloat(transY))
-	    tY = __shortFloatVal( transY );
-	else {
-	    t = __SSEND0(transY, @symbol(asFloat), 0);
-	    if (! __isFloat(t)) goto fail;
-	    tY = __floatVal( t );
-	}
-
-	if( __isSmallInteger(startX) )
-	    x = (float) __intVal( startX );
-	else if (__isFloat(startX))
-	    x = __floatVal( startX );
-	else if (__isShortFloat(startX))
-	    x = __shortFloatVal( startX );
-	else {
-	    t = __SSEND0(startX, @symbol(asFloat), 0);
-	    if (! __isFloat(t)) goto fail;
-	    x = __floatVal( t );
-	}
-
-	if( __isSmallInteger(stepX) )
-	    step = (float) __intVal( stepX );
-	else if (__isFloat(stepX))
-	    step = __floatVal( stepX );
-	else if (__isShortFloat(stepX))
-	    step = __shortFloatVal( stepX );
-	else {
-	    t = __SSEND0(stepX, @symbol(asFloat), 0);
-	    if (! __isFloat(t)) goto fail;
-	    step = __floatVal( t );
-	}
-
-	num = __intVal( noY );
-	if( num > 200 ) {
-	    if( ! (points = (XPoint *) malloc ( sizeof(XPoint) * num )) )
-		goto fail;
-	    mustFree = 1;
-	} else {
-	    points = qPoints;
-	}
-	for( i = 0; i < num; ++i ) {
-	    int px, py;
-
-	    yA  = __AT_(yValues, __MKSMALLINT(i+1) );
-
-	    if( __isFloat(yA) )
-		y = __floatVal( yA );
-	    else if( __isSmallInteger(yA) )
-		y = (float) __intVal( yA );
-	    else if( __isShortFloat( yA) )
-		y = __shortFloatVal( yA );
-	    else {
-		t = __SSEND0(yA, @symbol(asFloat), 0);
-		if (! __isFloat(t)) goto fail;
-		y = __floatVal( t );
-	    }
-
-	    px = (int) (x + 0.5);
-	    py = (int) ((y * sY) + tY + 0.5);
-
-	    /* attention: coordinates in X are shorts and wrap; clamp here. */
-	    if (px > 0x7FFF) px = 0x7FFF;
-	    else if (px < -0x8000) px = -0x8000;
-	    if (py > 0x7FFF) py = 0x7FFF;
-	    else if (py < -0x8000) py = -0x8000;
-
-	    points[i].x = px;
-	    points[i].y = py;
-	    x = x + step;
-	}
-
-	ENTER_XLIB();
-	XDrawLines(myDpy, win, gc, points, num, CoordModeOrigin);
-	LEAVE_XLIB();
-
-	if( mustFree ) {
-	    free( points );
-	}
-	RETURN ( self );
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+
+        if( __isSmallInteger(scaleY) )
+            sY = (float) __intVal( scaleY );
+        else if (__isFloat(scaleY))
+            sY = __floatVal( scaleY );
+        else if (__isShortFloat(scaleY))
+            sY = __shortFloatVal( scaleY );
+        else {
+            t = __SSEND0(scaleY, @symbol(asFloat), 0);
+            if (! __isFloat(t)) goto fail;
+            sY = __floatVal( t );
+        }
+
+        if( __isSmallInteger(transY) )
+            tY = (float) __intVal( transY );
+        else if (__isFloat(transY))
+            tY = __floatVal( transY );
+        else if (__isShortFloat(transY))
+            tY = __shortFloatVal( transY );
+        else {
+            t = __SSEND0(transY, @symbol(asFloat), 0);
+            if (! __isFloat(t)) goto fail;
+            tY = __floatVal( t );
+        }
+
+        if( __isSmallInteger(startX) )
+            x = (float) __intVal( startX );
+        else if (__isFloat(startX))
+            x = __floatVal( startX );
+        else if (__isShortFloat(startX))
+            x = __shortFloatVal( startX );
+        else {
+            t = __SSEND0(startX, @symbol(asFloat), 0);
+            if (! __isFloat(t)) goto fail;
+            x = __floatVal( t );
+        }
+
+        if( __isSmallInteger(stepX) )
+            step = (float) __intVal( stepX );
+        else if (__isFloat(stepX))
+            step = __floatVal( stepX );
+        else if (__isShortFloat(stepX))
+            step = __shortFloatVal( stepX );
+        else {
+            t = __SSEND0(stepX, @symbol(asFloat), 0);
+            if (! __isFloat(t)) goto fail;
+            step = __floatVal( t );
+        }
+
+        num = __intVal( noY );
+        if( num > 200 ) {
+            if( ! (points = (XPoint *) malloc ( sizeof(XPoint) * num )) )
+                goto fail;
+            mustFree = 1;
+        } else {
+            points = qPoints;
+        }
+        for( i = 0; i < num; ++i ) {
+            int px, py;
+
+            yA  = __AT_(yValues, __MKSMALLINT(i+1) );
+
+            if( __isFloat(yA) )
+                y = __floatVal( yA );
+            else if( __isSmallInteger(yA) )
+                y = (float) __intVal( yA );
+            else if( __isShortFloat( yA) )
+                y = __shortFloatVal( yA );
+            else {
+                t = __SSEND0(yA, @symbol(asFloat), 0);
+                if (! __isFloat(t)) goto fail;
+                y = __floatVal( t );
+            }
+
+            px = (int) (x + 0.5);
+            py = (int) ((y * sY) + tY + 0.5);
+
+            /* attention: coordinates in X are shorts and wrap; clamp here. */
+            if (px > 0x7FFF) px = 0x7FFF;
+            else if (px < -0x8000) px = -0x8000;
+            if (py > 0x7FFF) py = 0x7FFF;
+            else if (py < -0x8000) py = -0x8000;
+
+            points[i].x = px;
+            points[i].y = py;
+            x = x + step;
+        }
+
+        ENTER_XLIB();
+        XDrawLines(myDpy, win, gc, points, num, CoordModeOrigin);
+        LEAVE_XLIB();
+
+        if( mustFree ) {
+            free( points );
+        }
+        RETURN ( self );
     }
 
 fail:
     if( mustFree )
-	free( points );
+        free( points );
 %}.
     ^ super displayLinesFromX:startX step:stepX yValues:yValues scaleY:scaleY transY:transY in:aDrawableId with:aGCId
 
@@ -3715,11 +3742,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3730,20 +3757,20 @@
      && __isExternalAddress(aGCId)
      && __isExternalAddress(aDrawableId)
      && __bothSmallInteger(x, y)) {
-	int px, py;
-
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-	px = __intVal(x);
-	py = __intVal(y);
-	if (px > 0x7FFF) px = 0x7FFF;
-	else if (px < -0x8000) px = -0x8000;
-	if (py > 0x7FFF) py = 0x7FFF;
-	else if (py < -0x8000) py = -0x8000;
-	ENTER_XLIB();
-	XDrawPoint(myDpy, win, gc, px, py);
-	LEAVE_XLIB();
-	RETURN ( self );
+        int px, py;
+
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+        px = __intVal(x);
+        py = __intVal(y);
+        if (px > 0x7FFF) px = 0x7FFF;
+        else if (px < -0x8000) px = -0x8000;
+        if (py > 0x7FFF) py = 0x7FFF;
+        else if (py < -0x8000) py = -0x8000;
+        ENTER_XLIB();
+        XDrawPoint(myDpy, win, gc, px, py);
+        LEAVE_XLIB();
+        RETURN ( self );
     }
 %}.
     "badGC, badDrawable or x/y not integer"
@@ -3760,11 +3787,11 @@
     |numberOfPoints newPoints|
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
     numberOfPoints := aPolygon size.
 %{
@@ -3780,53 +3807,53 @@
      && __isExternalAddress(aGCId)
      && __isExternalAddress(aDrawableId)
      && __isSmallInteger(numberOfPoints)) {
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-	num = __intVal(numberOfPoints);
-	/*
-	 * avoid a (slow) malloc, if the number of points is small
-	 */
-	if (num > 100) {
-	    points = (XPoint *)malloc(sizeof(XPoint) * num);
-	    if (! points) goto fail;
-	    mustFree = 1;
-	} else
-	    points = qPoints;
-
-	for (i=0; i<num; i++) {
-	    int px, py;
-
-	    point = __AT_(aPolygon, __MKSMALLINT(i+1));
-	    if (! __isPoint(point)) goto fail;
-	    x = _point_X(point);
-	    y = _point_Y(point);
-	    if (! __bothSmallInteger(x, y))
-		goto fail;
-
-	    px = __intVal(x);
-	    py = __intVal(y);
-
-	    /* attention: coordinates in X are shorts and wrap; clamp here. */
-	    if (px > 0x7FFF) px = 0x7FFF;
-	    else if (px < -0x8000) px = -0x8000;
-	    if (py > 0x7FFF) py = 0x7FFF;
-	    else if (py < -0x8000) py = -0x8000;
-
-	    points[i].x = px;
-	    points[i].y = py;
-	}
-
-	ENTER_XLIB();
-	XDrawLines(myDpy, win, gc, points, num, CoordModeOrigin);
-	LEAVE_XLIB();
-
-	if (mustFree)
-	    free(points);
-	RETURN ( self );
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+        num = __intVal(numberOfPoints);
+        /*
+         * avoid a (slow) malloc, if the number of points is small
+         */
+        if (num > 100) {
+            points = (XPoint *)malloc(sizeof(XPoint) * num);
+            if (! points) goto fail;
+            mustFree = 1;
+        } else
+            points = qPoints;
+
+        for (i=0; i<num; i++) {
+            int px, py;
+
+            point = __AT_(aPolygon, __MKSMALLINT(i+1));
+            if (! __isPoint(point)) goto fail;
+            x = _point_X(point);
+            y = _point_Y(point);
+            if (! __bothSmallInteger(x, y))
+                goto fail;
+
+            px = __intVal(x);
+            py = __intVal(y);
+
+            /* attention: coordinates in X are shorts and wrap; clamp here. */
+            if (px > 0x7FFF) px = 0x7FFF;
+            else if (px < -0x8000) px = -0x8000;
+            if (py > 0x7FFF) py = 0x7FFF;
+            else if (py < -0x8000) py = -0x8000;
+
+            points[i].x = px;
+            points[i].y = py;
+        }
+
+        ENTER_XLIB();
+        XDrawLines(myDpy, win, gc, points, num, CoordModeOrigin);
+        LEAVE_XLIB();
+
+        if (mustFree)
+            free(points);
+        RETURN ( self );
     }
 fail: ;
     if (mustFree)
-	free(points);
+        free(points);
 %}.
     "badGC, badDrawable or coordinates not integer"
     self primitiveFailedOrClosedConnection
@@ -3838,11 +3865,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3855,31 +3882,31 @@
      && __isExternalAddress(aDrawableId)
      && __bothSmallInteger(x, y)
      && __bothSmallInteger(width, height)) {
-	int px, py;
-
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-	w = __intVal(width);
-	h = __intVal(height);
-
-	/*
-	 * need this check here: some servers simply dump core with bad args
-	 */
-	if ((w >= 0) && (h >= 0)) {
-	    px = __intVal(x);
-	    py = __intVal(y);
-
-	    /* attention: coordinates in X are shorts and wrap; clamp here. */
-	    if (px > 0x7FFF) px = 0x7FFF;
-	    else if (px < -0x8000) px = -0x8000;
-	    if (py > 0x7FFF) py = 0x7FFF;
-	    else if (py < -0x8000) py = -0x8000;
-
-	    ENTER_XLIB();
-	    XDrawRectangle(myDpy, win, gc, px, py, w, h);
-	    LEAVE_XLIB();
-	}
-	RETURN ( self );
+        int px, py;
+
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+        w = __intVal(width);
+        h = __intVal(height);
+
+        /*
+         * need this check here: some servers simply dump core with bad args
+         */
+        if ((w >= 0) && (h >= 0)) {
+            px = __intVal(x);
+            py = __intVal(y);
+
+            /* attention: coordinates in X are shorts and wrap; clamp here. */
+            if (px > 0x7FFF) px = 0x7FFF;
+            else if (px < -0x8000) px = -0x8000;
+            if (py > 0x7FFF) py = 0x7FFF;
+            else if (py < -0x8000) py = -0x8000;
+
+            ENTER_XLIB();
+            XDrawRectangle(myDpy, win, gc, px, py, w, h);
+            LEAVE_XLIB();
+        }
+        RETURN ( self );
     }
 %}.
     "badGC, badDrawable or coordinates not integer"
@@ -3894,11 +3921,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -3916,173 +3943,173 @@
      && __isNonNilObject(aString)
      && __bothSmallInteger(index1, index2)
      && __bothSmallInteger(x, y)) {
-	int lMax = __intVal(@global(MaxStringLength));
-	Display *dpy = myDpy;
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-
-	i1 = __intVal(index1) - 1;
-	if (i1 >= 0) {
-	    OBJ cls;
-
-	    i2 = __intVal(index2) - 1;
-	    if (i2 < i1) {
-		RETURN (self);
-	    }
-	    cp = (char *) __stringVal(aString);
-	    l = i2 - i1 + 1;
-
-	    if (__isStringLike(aString)) {
-		n = __stringSize(aString);
-		if (i2 < n) {
-		    cp += i1;
-		    if (l > lMax) l = lMax;
-		    ENTER_XLIB();
-		    if (opaque == true)
-			XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
-		    else
-			XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
-		    LEAVE_XLIB();
-		    RETURN ( self );
-		}
-	    }
-
-	    cls = __qClass(aString);
-	    nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
-	    cp += nInstBytes;
-
-	    if (__isBytes(aString)) {
-		n = __byteArraySize(aString) - nInstBytes - 1;
-
-		if (i2 < n) {
-		    cp += i1;
-		    if (l > lMax) l = lMax;
-		    ENTER_XLIB();
-		    if (opaque == true)
-			XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
-		    else
-			XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
-		    LEAVE_XLIB();
-		    RETURN ( self );
-		}
-	    }
-
-	    /* TWOBYTESTRINGS */
-	    if (__isWords(aString)) {
-		n = (__byteArraySize(aString) - nInstBytes) / 2;
-		if (i2 < n) {
-		    union {
-			char b[2];
-			unsigned short s;
-		    } u;
-		    int i;
-		    XChar2b *cp2 = (XChar2b *)0;
-		    int mustFree = 0;
-
-		    cp += (i1 * 2);
-		    if (l > lMax) l = lMax;
+        int lMax = __intVal(@global(MaxStringLength));
+        Display *dpy = myDpy;
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+
+        i1 = __intVal(index1) - 1;
+        if (i1 >= 0) {
+            OBJ cls;
+
+            i2 = __intVal(index2) - 1;
+            if (i2 < i1) {
+                RETURN (self);
+            }
+            cp = (char *) __stringVal(aString);
+            l = i2 - i1 + 1;
+
+            if (__isStringLike(aString)) {
+                n = __stringSize(aString);
+                if (i2 < n) {
+                    cp += i1;
+                    if (l > lMax) l = lMax;
+                    ENTER_XLIB();
+                    if (opaque == true)
+                        XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+                    else
+                        XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+                    LEAVE_XLIB();
+                    RETURN ( self );
+                }
+            }
+
+            cls = __qClass(aString);
+            nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+            cp += nInstBytes;
+
+            if (__isBytes(aString)) {
+                n = __byteArraySize(aString) - nInstBytes - 1;
+
+                if (i2 < n) {
+                    cp += i1;
+                    if (l > lMax) l = lMax;
+                    ENTER_XLIB();
+                    if (opaque == true)
+                        XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+                    else
+                        XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, l);
+                    LEAVE_XLIB();
+                    RETURN ( self );
+                }
+            }
+
+            /* TWOBYTESTRINGS */
+            if (__isWords(aString)) {
+                n = (__byteArraySize(aString) - nInstBytes) / 2;
+                if (i2 < n) {
+                    union {
+                        char b[2];
+                        unsigned short s;
+                    } u;
+                    int i;
+                    XChar2b *cp2 = (XChar2b *)0;
+                    int mustFree = 0;
+
+                    cp += (i1 * 2);
+                    if (l > lMax) l = lMax;
 
 #if defined(MSBFIRST) || defined(__MSBFIRST)
-		    /*
-		     * chars already in correct order
-		     */
+                    /*
+                     * chars already in correct order
+                     */
 #else
 # if ! (defined(LSBFIRST) || defined(__LSBFIRST))
-		    /*
-		     * ST/X TwoByteStrings store the asciiValue in native byteOrder;
-		     * X expects them MSB first
-		     * convert as required
-		     */
-		    u.s = 0x1234;
-		    if (u.b[0] != 0x12)
+                    /*
+                     * ST/X TwoByteStrings store the asciiValue in native byteOrder;
+                     * X expects them MSB first
+                     * convert as required
+                     */
+                    u.s = 0x1234;
+                    if (u.b[0] != 0x12)
 # endif
-		    {
-			if (l <= NLOCALBUFFER) {
-			    cp2 = xlatebuffer;
-			} else {
-			    cp2 = (XChar2b *)(malloc(l * 2));
-			    mustFree = 1;
-			}
-			for (i=0; i<l; i++) {
-			    cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
-			    cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
-			}
-			cp = (char *) cp2;
-		    }
-#endif
-		    ENTER_XLIB();
-		    if (opaque == true)
-			XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
-		    else
-			XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
-		    LEAVE_XLIB();
-
-		    if (mustFree) {
-			free(cp2);
-		    }
-
-		    RETURN ( self );
-		}
-	    }
-
-	    /* FOURBYTESTRINGS */
-	    if (__isLongs(aString)) {
-		n = (__byteArraySize(aString) - nInstBytes) / 4;
-		if (i2 < n) {
-		    union {
-			char b[2];
-			unsigned short s;
-		    } u;
-		    int i;
-		    XChar2b *cp2 = (XChar2b *)0;
-		    int32 *ip;
-		    int mustFree = 0;
-
-		    cp += (i1 * 4);
-		    if (l > lMax) l = lMax;
-
-		    /*
-		     * all codePoints <= 16rFFFF are draw; above 16bit range are drawn as 16rFFFF.
-		     */
-		    if (l <= NLOCALBUFFER) {
-			cp2 = xlatebuffer;
-		    } else {
-			cp2 = (XChar2b *)(malloc(l * 2));
-			mustFree = 1;
-		    }
-		    for (i=0; i<l; i++) {
-			int32 codePoint = ((int32 *)cp)[i];
-
-			if (codePoint > 0xFFFF) {
-			    codePoint = 0xFFFF;
-			}
-			cp2[i].byte1 = (codePoint >> 8) & 0xFF;
-			cp2[i].byte2 = codePoint & 0xFF;
-		    }
-		    cp = (char *) cp2;
-
-		    ENTER_XLIB();
-		    if (opaque == true)
-			XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
-		    else
-			XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
-		    LEAVE_XLIB();
-
-		    if (mustFree) {
-			free(cp2);
-		    }
-
-		    RETURN ( self );
-		}
-	    }
-	}
+                    {
+                        if (l <= NLOCALBUFFER) {
+                            cp2 = xlatebuffer;
+                        } else {
+                            cp2 = (XChar2b *)(malloc(l * 2));
+                            mustFree = 1;
+                        }
+                        for (i=0; i<l; i++) {
+                            cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
+                            cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
+                        }
+                        cp = (char *) cp2;
+                    }
+#endif
+                    ENTER_XLIB();
+                    if (opaque == true)
+                        XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
+                    else
+                        XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
+                    LEAVE_XLIB();
+
+                    if (mustFree) {
+                        free(cp2);
+                    }
+
+                    RETURN ( self );
+                }
+            }
+
+            /* FOURBYTESTRINGS */
+            if (__isLongs(aString)) {
+                n = (__byteArraySize(aString) - nInstBytes) / 4;
+                if (i2 < n) {
+                    union {
+                        char b[2];
+                        unsigned short s;
+                    } u;
+                    int i;
+                    XChar2b *cp2 = (XChar2b *)0;
+                    int32 *ip;
+                    int mustFree = 0;
+
+                    cp += (i1 * 4);
+                    if (l > lMax) l = lMax;
+
+                    /*
+                     * all codePoints <= 16rFFFF are draw; above 16bit range are drawn as 16rFFFF.
+                     */
+                    if (l <= NLOCALBUFFER) {
+                        cp2 = xlatebuffer;
+                    } else {
+                        cp2 = (XChar2b *)(malloc(l * 2));
+                        mustFree = 1;
+                    }
+                    for (i=0; i<l; i++) {
+                        int32 codePoint = ((int32 *)cp)[i];
+
+                        if (codePoint > 0xFFFF) {
+                            codePoint = 0xFFFF;
+                        }
+                        cp2[i].byte1 = (codePoint >> 8) & 0xFF;
+                        cp2[i].byte2 = codePoint & 0xFF;
+                    }
+                    cp = (char *) cp2;
+
+                    ENTER_XLIB();
+                    if (opaque == true)
+                        XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
+                    else
+                        XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, l);
+                    LEAVE_XLIB();
+
+                    if (mustFree) {
+                        free(cp2);
+                    }
+
+                    RETURN ( self );
+                }
+            }
+        }
     }
 #undef NLOCALBUFFER
 %}.
     (aString isString and:[aString bitsPerCharacter > 16]) ifTrue:[
-	self displayString:(TwoByteString new:aString size withAll:16rFFFF asCharacter)
-	     from:index1 to:index2 x:x y:y in:aDrawableId with:aGCId opaque:opaque.
-	^ self.
+        self displayString:(TwoByteString new:aString size withAll:16rFFFF asCharacter)
+             from:index1 to:index2 x:x y:y in:aDrawableId with:aGCId opaque:opaque.
+        ^ self.
     ].
 
     "x/y not integer, badGC or drawable, or not a string"
@@ -4097,11 +4124,11 @@
     <context: #return>
 
     operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
     ].
 %{
 
@@ -4119,10 +4146,9050 @@
      && __isExternalAddress(aDrawableId)
      && __isNonNilObject(aString)
      && __bothSmallInteger(x, y)) {
-	int lMax = __intVal(@global(MaxStringLength));
-	Display *dpy = myDpy;
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
+        int lMax = __intVal(@global(MaxStringLength));
+        Display *dpy = myDpy;
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+
+        cp = (char *) __stringVal(aString);
+
+        if (__isStringLike(aString)) {
+            n = __stringSize(aString);
+            if (n > lMax) n = lMax;
+            ENTER_XLIB();
+            if (opaque == true)
+                XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, n);
+            else
+                XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, n);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+
+        cls = __qClass(aString);
+        nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+        cp += nInstBytes;
+
+        if (__isBytes(aString)) {
+            n = __byteArraySize(aString) - nInstBytes - 1;
+
+            if (n > lMax) n = lMax;
+            ENTER_XLIB();
+            if (opaque == true)
+                XDrawImageString(dpy, win, gc, __intVal(x), __intVal(y), cp, n);
+            else
+                XDrawString(dpy, win, gc, __intVal(x), __intVal(y), cp, n);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+
+        /* TWOBYTESTRINGS */
+        if (__isWords(aString)) {
+            union {
+                char b[2];
+                unsigned short s;
+            } u;
+            int i;
+            XChar2b *cp2;
+            int mustFree = 0;
+
+            n = (__byteArraySize(aString) - nInstBytes) / 2;
+            if (n > lMax) n = lMax;
+
+#if defined(MSBFIRST) || defined(__MSBFIRST)
+            /*
+             * chars already in correct order
+             */
+#else
+# if ! (defined(LSBFIRST) || defined(__LSBFIRST))
+            /*
+             * ST/X TwoByteStrings store the asciiValue in native byteOrder;
+             * X expects them MSB first
+             * convert as required
+             */
+            u.s = 0x1234;
+            if (u.b[0] != 0x12)
+# endif
+            {
+                if (n <= NLOCALBUFFER) {
+                    cp2 = xlatebuffer;
+                } else {
+                    cp2 = (XChar2b *)(malloc(n * 2));
+                    mustFree = 1;
+                }
+
+                for (i=0; i<n; i++) {
+                    cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
+                    cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
+                }
+                cp = (char *) cp2;
+            }
+#endif
+            ENTER_XLIB();
+            if (opaque == true)
+                XDrawImageString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, n);
+            else
+                XDrawString16(dpy, win, gc, __intVal(x), __intVal(y), (XChar2b *)cp, n);
+            LEAVE_XLIB();
+
+            if (mustFree) {
+                free(cp2);
+            }
+
+            RETURN ( self );
+        }
+    }
+#undef NLOCALBUFFER
+%}.
+    ^ super displayString:aString x:x y:y in:aDrawableId with:aGCId opaque:opaque
+!
+
+drawBits:givenBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:givenPadding
+        width:imageWidth height:imageHeight
+        x:srcx y:srcy
+        into:aDrawableId
+        x:dstx y:dsty
+        width:w height:h
+        with:aGCId
+
+    "draw a bitImage which has depth id, width iw and height ih into
+     the drawable. draw a region of w/h pixels from srcx/srcy to dstx/dsty.
+     Individual source pixels have bitsPerPixel bits, allowing to draw
+     depth and pixel-units to be different.
+     It has to be checked elsewhere, that the server can do it with the given
+     depth - otherwise, primitive failure will be signalled.
+     Also it is assumed, that the colormap is setup correctly and the
+     colors are allocated - otherwise the colors may be wrong."
+
+    |fmt padding bits wantedPadding|
+
+    padding := givenPadding.
+    bits := givenBits.
+
+    "/ the XF86_VGA16 server seems to report an error when we pass it an
+    "/ 8-bit padded image. (it wants it 32bit padded).
+    "/ as a workaround, repad it here (although, the server and/or Xlib should
+    "/ care for that.
+
+    ((imageDepth == 4) and:[depth == 4]) ifTrue:[
+        fmt := self supportedImageFormatForDepth:4.
+        fmt isNil ifTrue:[
+            self primitiveFailed. "/ cannot represent this image
+            ^ nil
+        ].
+        wantedPadding := fmt at:#padding.
+        wantedPadding > givenPadding ifTrue:[
+            bits := self
+                            repadBits:givenBits
+                            width:imageWidth
+                            height:imageHeight
+                            depth:imageDepth
+                            from:givenPadding
+                            to:wantedPadding.
+            padding := wantedPadding.
+        ]
+    ].
+
+
+    operationsUntilFlush notNil ifTrue:[
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
+    ].
+    "
+     sorry; I had to separate it into 2 methods, since XPutImage needs
+     an unlimited stack, and thus cannot send primitiveFailed
+    "
+    (self
+        primDrawBits:bits
+        bitsPerPixel:bitsPerPixel
+        depth:imageDepth
+        msb:true
+        padding:padding
+        width:imageWidth height:imageHeight
+        x:srcx y:srcy
+        into:aDrawableId
+        x:dstx y:dsty
+        width:w height:h
+        with:aGCId)
+    ifFalse:[
+        "
+         also happens, if a segmentation violation occurs in the
+         XPutImage ...
+        "
+        self primitiveFailedOrClosedConnection
+    ].
+!
+
+fillArcX:x y:y width:width height:height from:startAngle angle:angle
+               in:aDrawableId with:aGCId
+    "fill an arc. If any coordinate is not integer, an error is triggered.
+     The angles may be floats or integer - they are given in degrees."
+
+    <context: #return>
+
+    operationsUntilFlush notNil ifTrue:[
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
+    ].
+%{
+
+    GC gc;
+    Window win;
+    int w, h, angle1, angle2;
+    double f;
+
+    if (__isSmallInteger(startAngle))
+        angle1 = __intVal(startAngle) * 64;
+    else if (__isFloat(startAngle)) {
+        f = __floatVal(startAngle);
+        angle1 = f * 64;
+    } else if (__isShortFloat(startAngle)) {
+        f = __shortFloatVal(startAngle);
+        angle1 = f * 64;
+    } else goto bad;
+
+    if (__isSmallInteger(angle))
+        angle2 = __intVal(angle) * 64;
+    else if (__isFloat(angle)) {
+        f = __floatVal(angle);
+        angle2 = f * 64;
+    } else if (__isShortFloat(angle)) {
+        f = __shortFloatVal(angle);
+        angle2 = f * 64;
+    } else goto bad;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aGCId)
+     && __isExternalAddress(aDrawableId)
+     && __bothSmallInteger(x, y)
+     && __bothSmallInteger(width, height)) {
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+        w = __intVal(width);
+        h = __intVal(height);
+        /*
+         * need this check here: some servers simply dump core with bad args
+         */
+        if ((w >= 0) && (h >= 0) && (angle1 >= 0) && (angle2 >= 0)) {
+            ENTER_XLIB();
+            XFillArc(myDpy, win, gc, __intVal(x), __intVal(y),
+                                   w, h, angle1, angle2);
+            LEAVE_XLIB();
+        }
+        RETURN ( self );
+    }
+    bad: ;
+%}.
+    "badGC, badDrawable or coordinates not integer
+     or non float angle(s)"
+
+    self primitiveFailedOrClosedConnection
+!
+
+fillPolygon:aPolygon in:aDrawableId with:aGCId
+    "fill a polygon given by its points.
+     If any coordinate is not integer, an error is triggered."
+
+    <context: #return>
+
+    |numberOfPoints|
+
+    operationsUntilFlush notNil ifTrue:[
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
+    ].
+    numberOfPoints := aPolygon size.
+%{
+    GC gc;
+    Window win;
+    OBJ point, x, y;
+    int i, num;
+    XPoint *points;
+    XPoint qPoints[100];
+    int mustFree = 0;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aGCId)
+     && __isExternalAddress(aDrawableId)
+     && __isSmallInteger(numberOfPoints)) {
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+        num = __intVal(numberOfPoints);
+        if (num < 3) {
+            RETURN ( self );
+        }
+        /*
+         * avoid (slow) malloc, if not many points
+         */
+        if (num > 100) {
+            points = (XPoint *) malloc(sizeof(XPoint) * num);
+            if (! points) goto fail;
+            mustFree = 1;
+        } else
+            points = qPoints;
+        for (i=0; i<num; i++) {
+            point = __AT_(aPolygon, __MKSMALLINT(i+1));
+            if (! __isPoint(point)) goto fail;
+            x = _point_X(point);
+            y = _point_Y(point);
+            if (! __bothSmallInteger(x, y))
+                goto fail;
+            points[i].x = __intVal(x);
+            points[i].y = __intVal(y);
+        }
+        ENTER_XLIB();
+        XFillPolygon(myDpy, win, gc, points, num, Complex, CoordModeOrigin);
+        LEAVE_XLIB();
+        if (mustFree)
+            free(points);
+        RETURN ( self );
+
+fail: ;
+        if (mustFree)
+            free(points);
+    }
+%}.
+    "badGC, badDrawable or coordinates not integer"
+    self primitiveFailedOrClosedConnection
+!
+
+fillRectangleX:x y:y width:width height:height in:aDrawableId with:aGCId
+    "fill a rectangle. If any coordinate is not integer, an error is triggered."
+
+    <context: #return>
+
+    operationsUntilFlush notNil ifTrue:[
+        operationsUntilFlush <= 0 ifTrue:[
+            self flush.
+        ] ifFalse:[
+            operationsUntilFlush := operationsUntilFlush - 1.
+        ].
+    ].
+%{
+
+    int w, h;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aGCId)
+     && __isExternalAddress(aDrawableId)
+     && __bothSmallInteger(x, y)
+     && __bothSmallInteger(width, height)) {
+        w = __intVal(width);
+        h = __intVal(height);
+        /*
+         * need this check here: some servers simply dump core with bad args
+         */
+        if ((w >= 0) && (h >= 0)) {
+            ENTER_XLIB();
+            XFillRectangle(myDpy,
+                           __DrawableVal(aDrawableId), __GCVal(aGCId),
+                           __intVal(x), __intVal(y), w, h);
+            LEAVE_XLIB();
+        }
+        RETURN ( self );
+    }
+%}.
+    "badGC, badDrawable or coordinates not integer"
+    self primitiveFailedOrClosedConnection
+!
+
+primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth msb:msb masks:maskArray padding:bitPadding
+                             extent:imageExtent sourceOrigin:srcOrg
+                               into:aDrawableId
+                  destinationOrigin:dstOrg extent:dstExtent
+                               with:aGCId
+
+    <context: #return>
+
+    |imageWidth imageHeight rm gm bm srcx srcy dstx dsty w h|
+
+    imageWidth := imageExtent x.
+    imageHeight := imageExtent y.
+    rm := maskArray at:1.
+    gm := maskArray at:2.
+    bm := maskArray at:3.
+    srcx := srcOrg x.
+    srcy := srcOrg y.
+    dstx := dstOrg x.
+    dsty := dstOrg y.
+    w := dstExtent x.
+    h := dstExtent y.
+
+    "since XPutImage may allocate huge amount of stack space
+     (some implementations use alloca), this must run with unlimited stack."
+
+%{  /* UNLIMITEDSTACK */
+
+    /*
+     * need unlimited stack, since some Xlibs do a huge alloca in
+     * XPutImage
+     */
+    GC gc;
+    Window win;
+    XImage image;
+    int imgWdth;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aGCId)
+     && __isExternalAddress(aDrawableId)
+     && __bothSmallInteger(srcx, srcy)
+     && __bothSmallInteger(dstx, dsty)
+     && __bothSmallInteger(w, h)
+     && __bothSmallInteger(imageWidth, imageHeight)
+     && __bothSmallInteger(imageDepth, bitsPerPixel)
+     && __isSmallInteger(bitPadding)
+     && __bothSmallInteger(rm, gm)
+     && __isSmallInteger(bm)
+     && __isByteArrayLike(imageBits)) {
+        Display *dpy = myDpy;
+        int pad = __intVal(bitPadding);
+
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+        if (! gc || !win)
+            goto fail;
+#ifdef ARGDEBUG
+        console_printf("args ok\n");
+#endif
+        image.data = (char *)__ByteArrayInstPtr(imageBits)->ba_element;
+        image.width = imgWdth = __intVal(imageWidth);
+        image.height = __intVal(imageHeight);
+        image.xoffset = 0;
+        image.format = ZPixmap;
+        image.byte_order = (msb == true) ? MSBFirst : LSBFirst;
+        image.bitmap_unit = 8;
+        image.bitmap_bit_order = MSBFirst;
+        image.bitmap_pad = pad;
+        image.depth = __intVal(imageDepth);
+        image.bits_per_pixel = __intVal(bitsPerPixel);
+        image.red_mask = __intVal(rm);
+        image.green_mask = __intVal(gm);
+        image.blue_mask = __intVal(bm);
+
+        image.bytes_per_line = ((((imgWdth * image.bits_per_pixel) + (pad-1)) / pad) * pad) / 8;
+
+        switch (image.bits_per_pixel) {
+            case 1:
+            case 2:
+            case 4:
+            case 8:
+            case 16:
+            case 24:
+            case 32:
+                break;
+
+            default:
+#ifdef ARGDEBUG
+                console_printf("bits_per_pixel=%d\n",image.bits_per_pixel);
+#endif
+                goto fail;
+        }
+
+        /* ENTER_XLIB(); */
+        XPutImage(dpy, win, gc, &image, __intVal(srcx), __intVal(srcy),
+                                        __intVal(dstx), __intVal(dsty),
+                                        __intVal(w), __intVal(h));
+        /* LEAVE_XLIB(); */
+
+        RETURN ( true );
+    }
+#ifdef ARGDEBUG
+    if (!! __isExternalAddress(aGCId)) console_printf("GC\n");
+    if (!! __isExternalAddress(aDrawableId)) console_printf("aDrawableId\n");
+    if (!! __isSmallInteger(srcx)) console_printf("srcx\n");
+    if (!! __isSmallInteger(srcy)) console_printf("srcy\n");
+    if (!! __isSmallInteger(dstx)) console_printf("dstx\n");
+    if (!! __isSmallInteger(dsty)) console_printf("dsty\n");
+    if (!! __isSmallInteger(w)) console_printf("w\n");
+    if (!! __isSmallInteger(h)) console_printf("h\n");
+    if (!! __isSmallInteger(imageWidth)) console_printf("imageWidth\n");
+    if (!! __isSmallInteger(imageHeight)) console_printf("imageHeight\n");
+    if (!! __isSmallInteger(imageDepth)) console_printf("imageDepth\n");
+    if (!! __isSmallInteger(bitsPerPixel)) console_printf("bitsPerPixel\n");
+    if (!! __isByteArrayLike(imageBits)) console_printf("imageBits\n");
+#endif
+
+fail: ;
+%}
+.
+    ^ false
+!
+
+primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth msb:msb padding:bitPadding
+                              width:imageWidth height:imageHeight
+                                  x:srcx y:srcy
+                               into:aDrawableId
+                                  x:dstx y:dsty
+                              width:w height:h
+                               with:aGCId
+
+    <context: #return>
+
+    "since XPutImage may allocate huge amount of stack space
+     (some implementations use alloca), this must run with unlimited stack."
+
+%{  /* UNLIMITEDSTACK */
+
+    /*
+     * need unlimited stack, since some Xlibs do a huge alloca in
+     * XPutImage
+     */
+    GC gc;
+    Window win;
+    XImage image;
+    int imgWdth;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aGCId)
+     && __isExternalAddress(aDrawableId)
+     && __bothSmallInteger(srcx, srcy)
+     && __bothSmallInteger(dstx, dsty)
+     && __bothSmallInteger(w, h)
+     && __bothSmallInteger(imageWidth, imageHeight)
+     && __bothSmallInteger(imageDepth, bitsPerPixel)
+     && __isSmallInteger(bitPadding)
+     && __isByteArrayLike(imageBits)) {
+        Display *dpy = myDpy;
+        int pad = __intVal(bitPadding);
+
+        gc = __GCVal(aGCId);
+        win = __WindowVal(aDrawableId);
+        if (! gc || !win)
+            goto fail;
+#ifdef ARGDEBUG
+        console_printf("args ok\n");
+#endif
+        image.data = (char *)__ByteArrayInstPtr(imageBits)->ba_element;
+        image.width = imgWdth = __intVal(imageWidth);
+        image.height = __intVal(imageHeight);
+        image.xoffset = 0;
+        image.format = ZPixmap;
+        image.byte_order = (msb == true) ? MSBFirst : LSBFirst;
+        image.bitmap_unit = 8;
+        image.bitmap_bit_order = MSBFirst;
+        image.bitmap_pad = pad;
+        image.depth = __intVal(imageDepth);
+        image.bits_per_pixel = __intVal(bitsPerPixel);
+
+        /*
+        image.bytes_per_line = ((((imgWdth * image.depth) + (pad-1)) / pad) * pad) / 8;
+        */
+        image.bytes_per_line = ((((imgWdth * image.bits_per_pixel) + (pad-1)) / pad) * pad) / 8;
+
+        switch (image.bits_per_pixel) {
+            case 1:
+            case 2:
+            case 4:
+            case 8:
+            case 16:
+            case 24:
+            case 32:
+                break;
+
+            default:
+#ifdef ARGDEBUG
+                console_printf("bits_per_pixel=%d\n",image.bits_per_pixel);
+#endif
+                goto fail;
+        }
+
+        image.red_mask = 0xFFFF;
+        image.green_mask = 0xFFFF;
+        image.blue_mask = 0xFFFF;
+
+        /* ENTER_XLIB(); */
+        XPutImage(dpy, win, gc, &image, __intVal(srcx), __intVal(srcy),
+                                        __intVal(dstx), __intVal(dsty),
+                                        __intVal(w), __intVal(h));
+        /* LEAVE_XLIB(); */
+
+        RETURN ( true );
+    }
+#ifdef ARGDEBUG
+    if (!! __isExternalAddress(aGCId)) console_printf("GC\n");
+    if (!! __isExternalAddress(aDrawableId)) console_printf("aDrawableId\n");
+    if (!! __isSmallInteger(srcx)) console_printf("srcx\n");
+    if (!! __isSmallInteger(srcy)) console_printf("srcy\n");
+    if (!! __isSmallInteger(dstx)) console_printf("dstx\n");
+    if (!! __isSmallInteger(dsty)) console_printf("dsty\n");
+    if (!! __isSmallInteger(w)) console_printf("w\n");
+    if (!! __isSmallInteger(h)) console_printf("h\n");
+    if (!! __isSmallInteger(imageWidth)) console_printf("imageWidth\n");
+    if (!! __isSmallInteger(imageHeight)) console_printf("imageHeight\n");
+    if (!! __isSmallInteger(imageDepth)) console_printf("imageDepth\n");
+    if (!! __isSmallInteger(bitsPerPixel)) console_printf("bitsPerPixel\n");
+    if (!! __isByteArrayLike(imageBits)) console_printf("imageBits\n");
+#endif
+
+fail: ;
+%}
+.
+    ^ false
+! !
+
+!XWorkstation methodsFor:'event forwarding'!
+
+buttonMotion:view state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a buttonMotion event for some view"
+
+    lastEventTime := time.
+    self buttonMotion:state x:x y:y view:view
+!
+
+buttonPress:view button:button state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a buttonPress event for some view"
+
+    |logicalButton|
+
+    lastEventTime := time.
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    eventRootX := rX.
+    eventRootY := rY.
+
+    "/ physical to logical button translation
+    logicalButton := buttonTranslation at:button ifAbsent:button.
+
+    "/ special for mouse-wheel implementation
+    (logicalButton == #wheelFwd or:[logicalButton == #wheelBwd]) ifTrue:[
+      self mouseWheelMotion:state x:x y:y amount:(logicalButton == #wheelFwd ifTrue:[10] ifFalse:[-10]) deltaTime:10 view:view.
+      ^ self.
+    ].
+
+    logicalButton isInteger ifTrue:[
+        buttonsPressed := buttonsPressed bitOr:(1 bitShift:logicalButton-1).
+    ].
+
+    (multiClickTimeDelta notNil and:[lastButtonPressTime notNil]) ifTrue:[
+        time < (lastButtonPressTime + multiClickTimeDelta) ifTrue:[
+            lastButtonPressTime := time.
+            self buttonMultiPress:logicalButton x:x y:y view:view.
+            ^ self.
+        ].
+    ].
+    lastButtonPressTime := time.
+
+    view isNil ifTrue:[
+        "/ event arrived, after I destroyed it myself
+        ^ self
+    ].
+    logicalButton == 1 ifTrue:[
+        activateOnClick == true ifTrue:[
+            "/ dont raise above an active popup view.
+            (activeKeyboardGrab isNil and:[activePointerGrab isNil]) ifTrue:[
+                view topView raise.
+            ]
+        ].
+    ].
+    super buttonPress:logicalButton x:x y:y view:view
+!
+
+buttonRelease:view button:button state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a buttonPress event for some view"
+
+    |logicalButton|
+
+    lastEventTime := time.
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    eventRootX := rX.
+    eventRootY := rY.
+
+    "/ physical to logical button translation
+    logicalButton := buttonTranslation at:button ifAbsent:button.
+
+    "/ special for HPs mouse-wheel implementation
+    (logicalButton == #wheelFwd or:[logicalButton == #wheelBwd]) ifTrue:[
+      ^ self
+    ].
+
+    logicalButton isInteger ifTrue:[
+        buttonsPressed := buttonsPressed bitClear:(1 bitShift:logicalButton-1).
+    ].
+    self buttonRelease:logicalButton x:x y:y view:view
+!
+
+clientMessage:targetView type:typeAtom format:format data:data
+    |sensor|
+
+    targetView isNil ifTrue:[
+        "targetView is gone? Anyway, cannot do anything with this event..."
+        ^ self.
+    ].
+
+    "DND drag&drop protocol"
+    (format == 32 and:[typeAtom == (self atomIDOf:#DndProtocol)]) ifTrue:[
+        self dndMessage:nil data:data view:targetView.
+        ^ self.
+    ].
+
+    sensor := targetView sensor.
+    "not posted, if there is no sensor ..."
+    sensor notNil ifTrue:[
+        sensor clientMessage:typeAtom format:format eventData:data view:targetView
+    ].
+
+    "Created: 4.4.1997 / 17:49:26 / cg"
+!
+
+configure:view relativeTo:anotherViewId x:x y:y width:w height:h borderWidth:borderWidth above:aboveViewId overrideRedirect:overrideBool
+    "forward a size-change event for some view"
+
+"/    anotherViewId notNil ifTrue:[
+"/        |parentViewOrSelf|
+"/        parentViewOrSelf := self viewFromId:anotherViewId.
+"/        parentViewOrSelf notNil ifTrue:[
+"/        ].
+"/     ].
+    self configureX:x y:y width:w height:h view:view.
+    aboveViewId notNil ifTrue:[
+        |aboveView|
+        aboveView := self viewFromId:aboveViewId.
+        aboveView notNil ifTrue:[
+            "view is now on the top of the window stack"
+            self coveredBy:view view:aboveView.
+        ].
+     ].
+!
+
+createWindow:view x:x y:y width:w height:h
+
+    view isNil ifTrue:[
+        "/ event arrived, after I destroyed it myself
+        ^ self
+    ].
+    view sensor createWindow:view x:x y:y width:w height:h
+
+    "Created: / 30-05-2011 / 16:05:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 30-05-2011 / 19:00:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+dndMessage:event data:data view:targetView
+    "handle a drag&drop protocol message"
+
+    |sensor property dropType dropValue names i1 i2 propertyType|
+
+    dropType := data doubleWordAt:1.
+
+    "/ see def's in DragAndDropTypes.h
+    dropType := (self dndDropTypes) at:dropType+1 ifAbsent:#DndNotDnd.
+
+    property := self
+        getProperty:(self atomIDOf:#DndSelection)
+        from:rootId
+        delete:false.
+
+    propertyType := property key.
+    dropValue := property value.
+
+    "/ preconvert into a collection
+    "/ of fileNames, string or byteArray
+    "/ Notice: we do not yet convert into dropObjects
+    "/ here, to allow arbitrary data to be handled by
+    "/ redefined dropMessage methods in applications.
+    "/ Conversion is done for some well known types
+    "/ in the default dropMessage handling of SimpleView.
+
+    dropType == #DndFiles ifTrue:[
+        "/ actually, a list of fileNames
+        propertyType ~~ stringAtom ifTrue:[
+            'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
+            ^ self
+        ].
+
+        names := OrderedCollection new.
+        i1 := 1.
+        [i1 ~~ 0] whileTrue:[
+            i2 := dropValue indexOf:(Character value:0) startingAt:i1.
+            i2 ~~ 0 ifTrue:[
+                names add:(dropValue copyFrom:i1 to:(i2-1)).
+                i1 := i2 + 1.
+            ] ifFalse:[
+                i1 := i2
+            ].
+        ].
+        dropValue := names.
+        dropValue := dropValue collect:[:nm | nm asFilename].
+        dropType := #files.
+    ] ifFalse:[ (dropType == #DndFile) ifTrue:[
+        propertyType ~~ stringAtom ifTrue:[
+            'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
+            ^ self
+        ].
+        dropValue := dropValue asFilename.
+        dropType := #file.
+    ] ifFalse:[ (dropType == #DndDir) ifTrue:[
+        propertyType ~~ stringAtom ifTrue:[
+            'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
+            ^ self
+        ].
+        dropValue := dropValue asFilename.
+        dropType := #directory.
+    ] ifFalse:[ (dropType == #DndText) ifTrue:[
+        propertyType ~~ stringAtom ifTrue:[
+            'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
+            ^ self
+        ].
+        dropType := #text.
+    ] ifFalse:[ (dropType == #DndExe) ifTrue:[
+        propertyType ~~ stringAtom ifTrue:[
+            'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
+            ^ self
+        ].
+        dropType := #executable.
+    ] ifFalse:[ (dropType == #DndLink) ifTrue:[
+        propertyType ~~ stringAtom ifTrue:[
+            'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
+            ^ self
+        ].
+        dropType := #link.
+    ] ifFalse:[ (dropType == #DndRawData) ifTrue:[
+        dropType := #rawData.
+    ] ifFalse:[
+        'XWorkstation [info]: unsupported dropType: ' infoPrint. dropType infoPrintCR.
+        'XWorkstation [info]: data: ' infoPrint. dropValue infoPrintCR.
+        dropType := #unknown.
+    ]]]]]]].
+
+    sensor := targetView sensor.
+    "not posted, if there is no sensor ..."
+    sensor notNil ifTrue:[
+        sensor dropMessage:dropType data:dropValue view:targetView position:nil handle:nil
+    ].
+
+    "Created: 4.4.1997 / 17:59:37 / cg"
+!
+
+expose:view x:x y:y width:w height:h count:count
+    "forward an expose event for some view"
+
+    self exposeX:x y:y width:w height:h view:view.
+
+
+
+
+!
+
+focusIn:view mode:mode detail:detail
+    "a view got the keyboard focus"
+
+    mode ~~ 1 "NotifyGrab" ifTrue:[
+        "mode NotifyGrab is set for pseudo-focus-changes, when a view grabs the keyboard"
+        self focusInView:view
+    ].
+!
+
+focusOut:view mode:mode detail:detail
+    "a view lost the keyboard focus"
+
+    mode ~~ 1 "NotifyGrab" ifTrue:[
+        "mode NotifyGrab is set for pseudo-focus-changes, when a view grabs the keyboard"
+        self focusOutView:view
+    ].
+!
+
+graphicsExpose:view x:x y:y width:w height:h count:count
+    "forward a graphics-expose event for some view"
+
+    self graphicsExposeX:x y:y width:w height:h final:(count==0) view:view
+
+
+
+
+!
+
+keyPress:view key:key code:keyCode state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a key-press event for some view"
+
+    |commonKey|
+
+    lastEventTime := time.
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+    key isNil ifTrue:[
+        "/ happens sometimes on some systems
+        "/ (alt-graph on sun has no keysym)
+        ^ self
+    ].
+    eventRootX := rX.
+    eventRootY := rY.
+
+    "very low-level mapping of X11 event symbols to common ST/X event symbols"
+    commonKey := rawKeySymTranslation at:key ifAbsent:key.
+
+    self keyPress:commonKey x:x y:y view:view.
+!
+
+keyRelease:view key:key code:keyCode state:state x:x y:y rootX:rX rootY:rY time:time
+    "forward a key-release event for some view"
+
+    |commonKey|
+
+    lastEventTime := time.
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    key isNil ifTrue:[
+        "/ happens sometimes on some systems
+        "/ (alt-graph on sun has no keysym)
+        ^ self
+    ].
+    eventRootX := rX.
+    eventRootY := rY.
+
+    "very low-level mapping of X11 event symbols to common ST/X event symbols"
+    commonKey := rawKeySymTranslation at:key ifAbsent:key.
+
+    self keyRelease:commonKey x:x y:y view:view.
+!
+
+mappingNotify:view request:what event:eB
+    "One of Keyboard-, Modifier- or PointerMap has changed, probably by xmodmap.
+     Tell xlib about the fact."
+
+    (what == #mappingKeyboard or:[what == #mappingModifier]) ifTrue:[
+        self refreshKeyboardMapping:eB.
+        "Maybe some of our modifiers have been changed"
+        self initializeModifierMappings.
+    ].
+
+!
+
+pointerEnter:view x:x y:y rootX:rX rootY:rY state:state mode:mode detail:detail time:time
+    "forward a pointer enter event for some view"
+
+    lastEventTime := time.
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    eventRootX := rX.
+    eventRootY := rY.
+    self pointerEnter:state x:x y:y view:view
+!
+
+pointerLeave:view x:x y:y rootX:rX rootY:rY state:state mode:mode detail:detail time:time
+    "forward a pointer leave event for some view"
+
+    lastEventTime := time.
+    altDown := state bitTest:altModifierMask.
+    metaDown := state bitTest:metaModifierMask.
+    shiftDown := state bitTest:(self shiftModifierMask).
+    ctrlDown := state bitTest:(self ctrlModifierMask).
+
+    eventRootX := rX.
+    eventRootY := rY.
+    self pointerLeave:state view:view
+!
+
+propertyChange:aView property:propertyId state:aSymbol time:time
+    "sent when an X property changes.
+     This is a very X-specific mechanism."
+
+    |selectionFetcher|
+
+    lastEventTime := time.
+    aView isNil ifTrue:[
+        "event arrived, after aView has been destroyed"
+        ^ self
+    ].
+
+"/    'propertyChange ' infoPrint. (self atomName:propertyId) print. ': ' print. aSymbol printCR.
+"/    aView propertyChange:atom state:aSymbol.
+
+    "JV@2011-01-06: Forward this event to views, they may
+     be interested (for now, only XEmbedSiteView is)"
+
+    aView sensor propertyChange:aView property:propertyId state:aSymbol time:time.
+
+    aSymbol ~~ #newValue ifTrue:[
+        "I am not interested in delete notifications"
+        ^ self.
+    ].
+    selectionFetcher := self findSelectionFetcher:aView id.
+    selectionFetcher notNil ifTrue:[
+        selectionFetcher message:thisContext message.
+    ].
+
+    "Modified: / 01-06-2011 / 13:40:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+selectionClear:aView selection:selectionID time:time
+    "sent when another X-client has created a selection.
+     This is a very X-specific mechanism."
+
+    |selectionFetcher|
+
+    lastEventTime := time.
+
+    selectionHandlers notNil ifTrue:[
+        selectionHandlers do:[:eachHandler |
+            eachHandler selectionClear:selectionID
+        ]
+    ].
+
+    aView isNil ifTrue:[
+        "event arrived, after aView has been destroyed"
+        ^ self
+    ].
+    selectionFetcher := self findSelectionFetcher:aView id.
+    selectionFetcher notNil ifTrue:[
+        selectionFetcher message:thisContext message.
+    ].
+!
+
+selectionNotify:aView selection:selectionID target:targetID property:propertyID requestor:requestorID time:time
+    "This event is sent by the selection owner as a response to our request for a selection.
+     This is a very X-specific mechanism."
+
+    |selectionFetcher|
+
+"/    Transcript show:'seletionNotify selID:'.
+"/    Transcript show:selectionID; show:' ('; show:(self atomName:selectionID); show:') '.
+"/    Transcript show:' targetID:'.
+"/    Transcript show:targetID; show:' ('; show:(self atomName:targetID); show:') '.
+"/    Transcript show:' propertyID:'.
+"/    Transcript show:propertyID; show:' ('; show:(self atomName:propertyID); show:') '.
+"/    Transcript showCR:''.
+"/    Transcript endEntry.
+
+    lastEventTime := time.
+
+    aView isNil ifTrue:[
+        "event arrived, after aView has been destroyed"
+        ^ self
+    ].
+    selectionFetcher := self findSelectionFetcher:aView id.
+    selectionFetcher notNil ifTrue:[
+        selectionFetcher message:thisContext message.
+    ].
+!
+
+selectionRequest:aView requestor:requestorID selection:selectionID target:targetID property:propertyID time:time
+    "sent by some other X-client to ask for the selection.
+     This is a very X-specific mechanism."
+
+    |selection property bufferGetSelector responseTargetID selectionTime|
+
+"/'Selection: ' print. (self atomName:selectionID) printCR. ' TargetId: ' print. (self atomName:targetID) printCR.
+"/' Property: ' print. (self atomName:propertyID) printCR. ' Requestor: ' print. requestorID printCR.
+
+    lastEventTime := time.
+
+    "JV@2012-03-27: Support both PRIMARY and CLIPBOARD selections"
+    selectionID == primaryAtom ifTrue:[
+        bufferGetSelector := #getPrimaryBuffer.
+        selectionTime := primarySelectionTime.
+    ] ifFalse:[
+        bufferGetSelector := #getCopyBuffer.
+        selectionTime := clipboardSelectionTime.
+    ].
+
+    (targetID == (self atomIDOf:#TIMESTAMP)) ifTrue:[
+        "the other view wants to know when we acquired ownership of the selection"
+        responseTargetID := self atomIDOf:#INTEGER.
+        selection := selectionTime.
+    ] ifFalse:[(targetID == (self atomIDOf:#TARGETS)) ifTrue:[
+        "the other view wants to know which targets we support"
+        responseTargetID := self atomIDOf:#ATOM.
+        selection := self supportedTargetAtoms.
+    ] ifFalse:[
+        selection := self selectionBuffer:bufferGetSelector as:targetID.
+        responseTargetID := selection key.
+        selection := selection value.
+    ]].
+
+"/'Send selection: ' print. selection printCR.
+
+    property := propertyID.
+
+    selection isNil ifTrue:[
+        "sending property None tells the client,
+         that I could not convert"
+"/        ('XWorkstation: unsupported selection target ', (self atomName:targetID)) errorPrintCR.
+        property := nil.
+        responseTargetID := targetID.
+    ] ifFalse:[
+        property == 0 ifTrue:[
+            "Support old (obsolete) clients requesting a None property.
+             Set the propertyID to the targetID"
+            property := responseTargetID.
+        ].
+        self setProperty:property
+             type:responseTargetID
+             value:selection
+             for:requestorID.
+    ].
+
+    self sendNotifySelection:selectionID
+         property:property
+         target:responseTargetID
+         time:time
+         to:requestorID.
+
+    "Modified: / 27-03-2012 / 15:22:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+visibilityNotify:aView state:how
+
+    aView notNil ifTrue:[
+        aView visibilityChange:how
+    ]
+! !
+
+!XWorkstation methodsFor:'event forwarding-ignored events'!
+
+circulateNotify:aView place:aSymbol
+    "sent, when the stacking order changes.
+     ignored for now."
+
+!
+
+circulateRequest:aView place:aSymbol
+    "sent, when the stacking order is about to change.
+     ignored for now."
+!
+
+colorMapNotify:aView state:aBoolean
+    "sent, when another colormap is installed.
+     This is a very X-specific mechanism."
+
+    aView isNil ifTrue:[
+        "/ event arrived, after I destroyed it myself
+        ^ self
+    ].
+    "/ not yet implemented
+    "/ aView colorMapChange
+!
+
+configureRequest:view x:x y:y width:w height:h above:above detail:detail
+    "ignored for now"
+
+    "/ view configureRequest
+!
+
+gravityNotify:aView x:x y:y
+    "ignored for now"
+
+    "/ aView gravityNotify
+!
+
+keymapNotify:aView
+    "ignore for now"
+
+!
+
+mapRequest:aView
+    "ignored for now"
+
+    "/ aView mapRequest
+!
+
+reparentedView:aView parentId:parentId x:x y:y
+    "ignored for now"
+
+    "/ aView reparented
+!
+
+resizeRequest:aView width:width height:height
+    "ignored for now"
+
+    "/ aView resizeRequest
+! !
+
+!XWorkstation methodsFor:'event handling'!
+
+defaultEventMask
+    "return a mask to enable some events by default."
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT( ExposureMask | StructureNotifyMask |
+                         KeyPressMask | KeyReleaseMask |
+                         PointerMotionMask |
+                         EnterWindowMask | LeaveWindowMask |
+                         ButtonPressMask | ButtonMotionMask | ButtonReleaseMask |
+                         PropertyChangeMask ));
+%}
+!
+
+dispatchEvent:evArray
+    |viewId view evType arguments|
+
+    viewId := evArray at:1.
+    viewId notNil ifTrue:[
+        viewId = lastId ifTrue:[
+            view := lastView
+        ] ifFalse:[
+            view := self viewFromId:viewId
+        ].
+    ].
+
+    evType := evArray at:3.
+
+    (self respondsTo:evType) ifTrue:[
+        arguments := evArray copyFrom:3 to:(3 + evType numArgs - 1).
+        arguments at:1 put:view.
+
+        self perform:evType withArguments:arguments.
+        ^ true.
+    ].
+'********** unhandled event:' errorPrintCR.
+evType errorPrintCR. (evArray at:2) errorPrintCR.
+'********** see dispatchEvent' errorPrintCR.
+    ^ false
+!
+
+dispatchEventFor:aViewIdOrNil withMask:eventMask
+    "central event handling method:
+     get next event and send appropriate message to the sensor or view.
+     If the argument aViewIdOrNil is nil, events for any view are processed,
+     otherwise only events for the view with given id are processed.
+     If the argument aMask is nonNil, only events for this eventMask are
+     handled.
+     WARNING: this may block to wait for an event - you better check for a
+              pending event before calling this."
+
+    |eventArray|
+
+    eventArray := Array new:13.
+
+    (self getEventFor:aViewIdOrNil withMask:eventMask into:eventArray) ifTrue:[
+        AbortOperationRequest handle:[:ex |
+            ex return
+        ] do:[
+            self dispatchEvent:eventArray.
+        ]
+    ].
+
+    "Modified: 19.8.1997 / 17:10:42 / cg"
+!
+
+dispatchExposeEventFor:aViewIdOrNil
+    "get next expose event and send appropriate message to the sensor or view.
+     If the argument aViewIdOrNil is nil, events for any view are processed,
+     otherwise only events for the view with given id are processed.
+     WARNING: this may block to wait for an event - you better check for a
+              pending event before calling this."
+
+    self dispatchEventFor:aViewIdOrNil withMask:(self eventMaskFor:#expose)
+
+    "Modified: 19.8.1997 / 17:10:26 / cg"
+!
+
+dispatchLoop
+    preWaitAction := [self flush].
+    Processor addPreWaitAction:preWaitAction.
+    [
+        super dispatchLoop
+    ] ensure:[
+        Processor removePreWaitAction:preWaitAction.
+        preWaitAction := nil.
+    ].
+!
+
+dispatchPendingEvents
+    "central event handling method for modal operation.
+     (i.e. this is now only used in the modal debugger)
+     Dispatch any pending events; return when no more are pending.
+     This code is somewhat special, since X has a concept of graphic
+     expose events (which are sent after a bitblt). After such a bitblt,
+     we only handle exposes until the graphicsExpose arrives.
+     Other systems may not need such a kludge"
+
+    "interested in exposes only ?"
+
+    |eventArray|
+
+    dispatchingExpose notNil ifTrue:[
+        [self exposeEventPendingFor:dispatchingExpose withSync:false] whileTrue:[
+            self dispatchExposeEventFor:dispatchingExpose
+        ].
+        ^ self
+    ].
+
+    [self eventPendingWithSync:false] whileTrue:[
+        eventArray isNil ifTrue:[
+            eventArray := Array new:13.
+        ].
+        (self getEventFor:nil withMask:nil into:eventArray) ifTrue:[
+            AbortOperationRequest handle:[:ex |
+                ex return
+            ] do:[
+                self dispatchEvent:eventArray.
+                "/ multi-screen config: give others a chance
+                "/ (needed because we run at high (non-timesliced) prio)
+                Processor yield.
+            ]
+        ].
+    ]
+
+    "Modified: 19.8.1997 / 17:11:18 / cg"
+!
+
+disposeEventsWithMask:aMask for:aWindowIdOrNil
+    "dispose (throw away) specific events. If aWindowId is nil,
+     events matching the mask are thrown away regardless of which
+     view they are for. Otherwise, only matching events for that
+     view are flushed."
+
+    <context: #return>
+%{ /* UNLIMITEDSTACK */
+
+    XEvent ev;
+    Window win;
+
+    if (ISCONNECTED
+     && __isSmallInteger(aMask)) {
+        Display *dpy = myDpy;
+
+        ENTER_XLIB();
+        if (__isExternalAddress(aWindowIdOrNil)) {
+            win = __WindowVal(aWindowIdOrNil);
+            while (XCheckWindowEvent(dpy, win, __intVal(aMask), &ev)) ;;
+        } else {
+            while (XCheckMaskEvent(dpy, __intVal(aMask), &ev)) ;;
+        }
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+eventMaskFor:anEventSymbol
+    "return the eventMask bit-constant corresponding to an event symbol"
+
+%{  /* NOCONTEXT */
+
+    int m = 0;
+
+    if (anEventSymbol == @symbol(keyPress)) m = KeyPressMask;
+    else if (anEventSymbol == @symbol(keyRelease)) m = KeyReleaseMask;
+    else if (anEventSymbol == @symbol(buttonPress)) m = ButtonPressMask;
+    else if (anEventSymbol == @symbol(buttonRelease)) m = ButtonReleaseMask;
+    else if (anEventSymbol == @symbol(buttonMotion)) m = ButtonMotionMask;
+    else if (anEventSymbol == @symbol(pointerMotion)) m = PointerMotionMask;
+    else if (anEventSymbol == @symbol(expose)) m = ExposureMask;
+    else if (anEventSymbol == @symbol(focusChange)) m = FocusChangeMask;
+    else if (anEventSymbol == @symbol(enter)) m = EnterWindowMask;
+    else if (anEventSymbol == @symbol(leave)) m = LeaveWindowMask;
+    else if (anEventSymbol == @symbol(keymapState)) m = KeymapStateMask;
+    else if (anEventSymbol == @symbol(visibilityChange)) m = VisibilityChangeMask;
+    else if (anEventSymbol == @symbol(structureNotify)) m = StructureNotifyMask;
+    else if (anEventSymbol == @symbol(resizeRedirect)) m = ResizeRedirectMask;
+    else if (anEventSymbol == @symbol(propertyChange)) m = PropertyChangeMask;
+    else if (anEventSymbol == @symbol(colormapChange)) m = ColormapChangeMask;
+    else if (anEventSymbol == @symbol(substructureNotify)) m = SubstructureNotifyMask;
+    else if (anEventSymbol == @symbol(substructureRedirect)) m = SubstructureRedirectMask;
+    RETURN (__MKSMALLINT(m));
+%}
+!
+
+eventPending
+    "return true, if any event is pending.
+     This looks for both the internal queue and the display connection."
+
+    "/ ConservativeSync is required for some Xlib implementation,
+    "/ where eventPending returns wrong if we do not flush the buffer.
+    "/ (especially Win32 & Xlib)
+
+    ConservativeSync == true ifTrue:[self sync].
+
+    dispatchingExpose notNil ifTrue:[
+        ^ self exposeEventPendingFor:dispatchingExpose withSync:false
+    ].
+    ^ self eventPendingWithSync:false
+
+    "Modified: / 28.4.1999 / 11:08:12 / cg"
+!
+
+eventPending:anEventSymbol for:aWindowIdOrNil
+    "return true, if a specific event is pending"
+
+    ^ self eventsPending:(self eventMaskFor:anEventSymbol) for:aWindowIdOrNil withSync:false
+!
+
+eventPending:anEventMask for:aWindowIdOrNil withSync:doSync
+    "return true, if any of the masked events is pending"
+
+    <context: #return>
+%{  /* UNLIMITEDSTACK */
+
+    XEvent ev;
+    Window win;
+    int thereIsOne;
+    OBJ rslt = false;
+
+    if (ISCONNECTED && __isSmallInteger(anEventMask)) {
+        Display *dpy = myDpy;
+
+        ENTER_XLIB();
+        if (doSync == true) {
+            XSync(dpy, 0);      /* make certain everything is flushed */
+        }
+        if (__isExternalAddress(aWindowIdOrNil)) {
+            win = __WindowVal(aWindowIdOrNil);
+            thereIsOne = XCheckWindowEvent(dpy, win, __intVal(anEventMask), &ev);
+        } else {
+            thereIsOne = XCheckMaskEvent(dpy, __intVal(anEventMask), &ev);
+        }
+        if (thereIsOne) {
+            XPutBackEvent(dpy, &ev);
+            rslt = true;
+        }
+        LEAVE_XLIB();
+    }
+    RETURN ( rslt );
+%}
+!
+
+eventPendingWithSync:doSync
+    "return true, if any event is pending.
+     If doSync is true, do a sync output buffer (i.e. send all to the display and wait until its processed)
+     before checking."
+
+    <context: #return>
+%{  /* UNLIMITEDSTACK */
+    OBJ rslt = false;
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        if (XEventsQueued(dpy, QueuedAlready)) {
+            RETURN (true);
+        }
+
+        ENTER_XLIB();
+        if (doSync == true) {
+            XSync(dpy, 0);      /* make certain everything is flushed */
+        }
+        if (XPending(dpy)) {
+            rslt = true;
+        }
+        LEAVE_XLIB();
+    }
+    RETURN ( rslt );
+%}
+!
+
+eventQueued
+    "return true, if any event is queued"
+
+    dispatchingExpose notNil ifTrue:[
+        ^ self exposeEventPendingFor:dispatchingExpose withSync:false
+    ].
+    ^ self eventQueuedAlready
+
+    "Created: 12.12.1995 / 21:43:00 / stefan"
+!
+
+eventQueuedAlready
+    "return true, if any event is queued internally.
+     (i.e. in X's internal event queue, which is both filled by explicit
+      nextEvent calls AND whenever drawing is done and events are pending on
+      the display connection)."
+
+%{  /* UNLIMITEDSTACK */
+    OBJ rslt = false;
+
+    if (ISCONNECTED) {
+        /* ENTER ... LEAVE not needed; XEventsQueued will not block */
+        /* ENTER_XLIB(); */
+        if (XEventsQueued(myDpy, QueuedAlready)) {
+            rslt = true;
+        }
+        /* LEAVE_XLIB(); */
+    }
+    RETURN ( rslt );
+%}
+!
+
+exposeEventPendingFor:aWindowIdOrNil withSync:doSync
+    "return true, if any expose event is pending for a specific view,
+     or any view (if the arg is nil).
+     This is an X specific, only required after a scroll operation."
+
+    <context: #return>
+
+%{  /* UNLIMITEDSTACK */
+
+    XEvent ev;
+    Window win;
+    int thereIsOne;
+    OBJ rslt = false;
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        ENTER_XLIB();
+        if (doSync == true) {
+            XSync(dpy, 0);      /* make certain everything is flushed */
+        }
+        if (__isExternalAddress(aWindowIdOrNil)) {
+            win = __WindowVal(aWindowIdOrNil);
+            thereIsOne = XCheckWindowEvent(dpy, win, ExposureMask, &ev);
+        } else {
+            thereIsOne = XCheckMaskEvent(dpy, ExposureMask, &ev);
+        }
+        if (thereIsOne) {
+            XPutBackEvent(dpy, &ev);
+            rslt = true;
+        }
+        LEAVE_XLIB();
+    }
+    RETURN ( rslt );
+%}
+!
+
+getEventFor:aViewIdOrNil withMask:eventMask into:anEventArray
+    "read next event if there is one and put events data into anEventArray.
+     If aViewIdOrNil is nil, events for any view are fetched;
+     otherwise only events for that specific view will be fetched.
+     Returns true, if there was an event, false otherwise.
+     This method may block - so you better check for pending events
+     before calling for it.
+
+     The event fields are placed them into anEventArray (must be at least size 13):
+     the fields are:
+        1:      windowID
+        2:      eventType-ID
+        3:      eventTypeSymbol
+
+        4..     args
+
+     Sorry I had to split dispatch into this fetch method and a separate
+     handler method to allow UNLIMITEDSTACK here.
+     (some Xlibs do a big alloca there which cannot be done in
+      #dispatchEvent:, since it dispatches out into ST-methods).
+    "
+
+%{  /* UNLIMITEDSTACK */
+
+    Display *dpy;
+    Window win, wWanted;
+    int evMask, returnValue;
+    XEvent ev;
+    OBJ eB;
+    KeySym keySym;
+    unsigned char buffer[64];
+    int i, nchars;
+    char *keySymString;
+    OBJ arg, sym, t, windowID;
+
+    if (! ISCONNECTED) {
+        RETURN (false);
+    }
+
+    dpy = myDpy;
+
+    ev.type = 0;
+
+    if (__isSmallInteger(eventMask)) {
+        evMask = __intVal(eventMask);
+    } else {
+        evMask = ~0;
+    }
+
+    if (__isExternalAddress(aViewIdOrNil)) {
+        wWanted = __WindowVal(aViewIdOrNil);
+        returnValue = XCheckWindowEvent(dpy, wWanted, evMask, &ev);
+    } else {
+        if (evMask == ~0) {
+            XNextEvent(dpy, &ev);
+            returnValue = 1;
+        } else {
+            returnValue = XCheckMaskEvent(dpy, evMask, &ev);
+        }
+    }
+    if (!returnValue) {
+        /* there is no event */
+        RETURN (false);
+    }
+
+    if (anEventArray == nil) {
+        /* sender is not interested in the event */
+        RETURN(true);
+    }
+
+    if (!__isArray(anEventArray)) {
+        console_fprintf(stderr, "XWorkstation: bad argument [%d]\n", __LINE__);
+        RETURN (false);
+    }
+    if (__arraySize(anEventArray) < 11) {
+        console_fprintf(stderr, "XWorkstation: bad argument [%d]\n", __LINE__);
+        RETURN (false);
+    }
+
+#   define ANYBUTTON   (Button1MotionMask | Button2MotionMask | Button3MotionMask)
+
+#   define ae ((XAnyEvent *)&ev)
+#   define ee ((XExposeEvent *)&ev)
+#   define ke ((XKeyPressedEvent *)&ev)
+#   define be ((XButtonPressedEvent *)&ev)
+#   define ce ((XConfigureEvent *)&ev)
+#   define cr ((XConfigureRequestEvent *)&ev)
+#   define me ((XMotionEvent *)&ev)
+#   define ele ((XCrossingEvent *)&ev)
+#   define de ((XDestroyWindowEvent *)&ev)
+#   define ve ((XVisibilityEvent *)&ev)
+#   define fe ((XFocusChangeEvent *)&ev)
+#   define cre ((XCreateWindowEvent *)&ev)
+#   define mape ((XMappingEvent *)&ev)
+#   define gre ((XGravityEvent *)&ev)
+#   define rr ((XResizeRequestEvent *)&ev)
+#   define rpe ((XReparentEvent *)&ev)
+#   define cie ((XCirculateEvent *)&ev)
+#   define pe ((XPropertyEvent *)&ev)
+#   define sce ((XSelectionClearEvent *)&ev)
+#   define cme ((XColormapEvent *)&ev)
+
+    if (((t = __INST(lastId)) != nil)
+         && __isExternalAddress(t)
+         && (__WindowVal(t) == ae->window)) {
+        windowID = t;
+    } else {
+        windowID = __MKEXTERNALADDRESS(ae->window);
+    }
+
+    __ArrayInstPtr(anEventArray)->a_element[0] = windowID; __STORE(anEventArray, windowID);
+    __ArrayInstPtr(anEventArray)->a_element[1] = __MKSMALLINT(ev.type);
+
+    switch (ev.type) {
+        case KeyRelease:
+            sym = @symbol(keyRelease:key:code:state:x:y:rootX:rootY:time:);
+            goto keyPressAndRelease;
+
+        case KeyPress:
+            sym = @symbol(keyPress:key:code:state:x:y:rootX:rootY:time:);
+            /* FALL INTO */
+
+        keyPressAndRelease:
+            arg = nil;
+            nchars = XLookupString(ke, (char *)buffer, sizeof(buffer), &keySym, NULL);
+            if (nchars == 1 && (((buffer[0] >= ' ') && (buffer[0] <= '~'))
+                || (buffer[0] >= 0x80))) {
+                arg = __MKCHARACTER(buffer[0]);
+//            } else if (nchars > 2) {
+//                arg = __MKSTRING_L(buffer, nchars);
+            } else {
+                keySymString = XKeysymToString(keySym);
+                if (keySymString) {
+                    arg = __MKSYMBOL(keySymString, 0);
+                }
+            }
+
+#ifdef IGNORE_UNKNOWN_KEYCODES
+            if (arg == nil) {
+                /* happens sometimes (alt-graph on sun has no keysym) */
+                RETURN (false);
+            }
+#endif
+            __ArrayInstPtr(anEventArray)->a_element[2] = sym;
+
+            __ArrayInstPtr(anEventArray)->a_element[3] = arg; __STORE(anEventArray, arg);
+            t = __MKUINT(ke->keycode); __ArrayInstPtr(anEventArray)->a_element[4] = t; __STORE(anEventArray, t);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(ke->state);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(ke->x);
+            __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(ke->y);
+            __ArrayInstPtr(anEventArray)->a_element[8] = __mkSmallInteger(ke->x_root);
+            __ArrayInstPtr(anEventArray)->a_element[9] = __mkSmallInteger(ke->y_root);
+            t = __MKUINT(ke->time); __ArrayInstPtr(anEventArray)->a_element[10] = t; __STORE(anEventArray, t);
+            break;
+
+        case ButtonPress:
+            sym = @symbol(buttonPress:button:state:x:y:rootX:rootY:time:);
+            goto buttonPressAndRelease;
+
+        case ButtonRelease:
+            sym = @symbol(buttonRelease:button:state:x:y:rootX:rootY:time:);
+            /* fall into */
+
+        buttonPressAndRelease:
+            __ArrayInstPtr(anEventArray)->a_element[2] = sym;
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(be->button);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(ke->state);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(be->x);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(be->y);
+            __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(be->x_root);
+            __ArrayInstPtr(anEventArray)->a_element[8] = __mkSmallInteger(be->y_root);
+            t = __MKUINT(be->time); __ArrayInstPtr(anEventArray)->a_element[9] = t; __STORE(anEventArray, t);
+            break;
+
+        case MotionNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(buttonMotion:state:x:y:rootX:rootY:time:);
+
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(me->state);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(me->x);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(me->y);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(me->x_root);
+            __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(me->y_root);
+            t = __MKUINT(me->time); __ArrayInstPtr(anEventArray)->a_element[8] = t; __STORE(anEventArray, t);
+            break;
+
+        case FocusIn:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(focusIn:mode:detail:);
+            goto focusInOut;
+
+        case FocusOut:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(focusOut:mode:detail:);
+            /* fall into */
+
+        focusInOut:
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(fe->mode);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(fe->detail);
+            break;
+
+        case EnterNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(pointerEnter:x:y:rootX:rootY:state:mode:detail:time:);
+            goto enterLeave;
+
+        case LeaveNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(pointerLeave:x:y:rootX:rootY:state:mode:detail:time:);
+            /* fall into */
+
+        enterLeave:
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(ele->x);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(ele->y);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(ele->x_root);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(ele->y_root);
+            __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(ele->state);
+            __ArrayInstPtr(anEventArray)->a_element[8] = __mkSmallInteger(ele->mode);
+            __ArrayInstPtr(anEventArray)->a_element[9] = __mkSmallInteger(ele->detail);
+            t = __MKUINT(ele->time); __ArrayInstPtr(anEventArray)->a_element[10] = t; __STORE(anEventArray, t);
+            break;
+
+        case Expose:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(expose:x:y:width:height:count:);
+            goto expose;
+
+        case GraphicsExpose:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(graphicsExpose:x:y:width:height:count:);
+            /* fall into */
+
+        expose:
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(ee->x);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(ee->y);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(ee->width);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(ee->height);
+            __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(ee->count);
+            break;
+
+        case NoExpose:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(noExposeView:);
+            break;
+
+        case VisibilityNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(visibilityNotify:state:);
+            switch (ve->state) {
+                case VisibilityUnobscured:
+                    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(unobscured);
+                    break;
+                case VisibilityPartiallyObscured:
+                    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(partiallyObscured);
+                    break;
+                case VisibilityFullyObscured:
+                    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(fullyObscured);
+                    break;
+                default:
+                    __ArrayInstPtr(anEventArray)->a_element[3] = __MKSMALLINT(ve->state);
+                    break;
+            }
+            break;
+
+        case CreateNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(createWindow:x:y:width:height:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(cre->x);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(cre->y);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(cre->width);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(cre->height);
+            break;
+
+        case DestroyNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(destroyedView:);
+            break;
+
+        case UnmapNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(unmappedView:);
+            break;
+
+        case MapNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(mappedView:);
+            break;
+
+        case ConfigureNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(configure:relativeTo:x:y:width:height:borderWidth:above:overrideRedirect:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = nil;
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(ce->x);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(ce->y);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(ce->width);
+            __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(ce->height);
+            __ArrayInstPtr(anEventArray)->a_element[8] = __mkSmallInteger(ce->border_width); 
+           __ArrayInstPtr(anEventArray)->a_element[9] = nil;
+            __ArrayInstPtr(anEventArray)->a_element[10] = ce->override_redirect ? true : false;
+            if (ce->event != None) {
+                t = __MKEXTERNALADDRESS(ce->event); __ArrayInstPtr(anEventArray)->a_element[3] = t; __STORE(anEventArray, t);
+            }
+            if (ce->above != None) {
+                t = __MKEXTERNALADDRESS(ce->above); __ArrayInstPtr(anEventArray)->a_element[9] = t; __STORE(anEventArray, t);
+            }
+            break;
+
+        case GravityNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(gravityNotify:x:y:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(gre->x);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(gre->y);
+            break;
+
+        case ResizeRequest:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(resizeRequest:width:height:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(rr->width);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(rr->height);
+            break;
+
+        case ConfigureRequest:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(configureRequest:x:y:width:height:above:detail:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(cr->x);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(cr->y);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(cr->width);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(cr->height);
+            __ArrayInstPtr(anEventArray)->a_element[7] = nil;
+            if (cr->above != None) {
+                t = __MKEXTERNALADDRESS(cr->above); __ArrayInstPtr(anEventArray)->a_element[7] = t; __STORE(anEventArray, t);
+            }
+            switch (cr->detail) {
+                case Above:
+                    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(above);
+                    break;
+                case Below:
+                    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(below);
+                    break;
+                case TopIf:
+                    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(topIf);
+                    break;
+                case BottomIf:
+                    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(bottomIf);
+                    break;
+                case Opposite:
+                    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(opposite);
+                    break;
+                default:
+                    __ArrayInstPtr(anEventArray)->a_element[8] = __MKSMALLINT(cr->detail);
+                    break;
+            }
+            break;
+
+        case CirculateNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(circulateNotify:place:);
+            goto circulate;
+
+        case CirculateRequest:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(circulateRequest:place:);
+            /* fall into */
+        circulate:
+            switch (cie->place) {
+                case PlaceOnTop:
+                    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(placeOnTop);
+                    break;
+                case PlaceOnBottom:
+                    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(placeOnBottom);
+                    break;
+                default:
+                    __ArrayInstPtr(anEventArray)->a_element[3] = __MKSMALLINT(cie->place);
+                    break;
+            }
+            break;
+
+        case PropertyNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(propertyChange:property:state:time:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = __MKATOMOBJ(pe->atom);
+            switch (pe->state) {
+                case PropertyNewValue:
+                    __ArrayInstPtr(anEventArray)->a_element[4] = @symbol(newValue);
+                    break;
+                case PropertyDelete:
+                    __ArrayInstPtr(anEventArray)->a_element[4] = @symbol(deleted);
+                    break;
+                default:
+                    __ArrayInstPtr(anEventArray)->a_element[4] = __MKSMALLINT(pe->state);
+                    break;
+            }
+            t = __MKUINT(pe->time); __ArrayInstPtr(anEventArray)->a_element[5] = t; __STORE(anEventArray, t);
+            break;
+
+        case SelectionClear:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(selectionClear:selection:time:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = __MKATOMOBJ(sce->selection);
+            t = __MKUINT(sce->time); __ArrayInstPtr(anEventArray)->a_element[4] = t; __STORE(anEventArray, t);
+            break;
+
+        case SelectionRequest:
+            /*
+             * someone wants the selection
+             */
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(selectionRequest:requestor:selection:target:property:time:);
+            t = __MKEXTERNALADDRESS(ev.xselectionrequest.requestor); __ArrayInstPtr(anEventArray)->a_element[3] = t; __STORE(anEventArray, t);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __MKATOMOBJ(ev.xselectionrequest.selection);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __MKATOMOBJ(ev.xselectionrequest.target);
+            __ArrayInstPtr(anEventArray)->a_element[6] = __MKATOMOBJ(ev.xselectionrequest.property);
+            t = __MKUINT(ev.xselectionrequest.time); __ArrayInstPtr(anEventArray)->a_element[7] = t; __STORE(anEventArray, t);
+            break;
+
+        case SelectionNotify:
+            /*
+             * returned selection value (answer from SelectionRequest)
+             */
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(selectionNotify:selection:target:property:requestor:time:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = __MKATOMOBJ(ev.xselection.selection);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __MKATOMOBJ(ev.xselection.target);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __MKATOMOBJ(ev.xselection.property);
+            t = __MKEXTERNALADDRESS(ev.xselection.requestor); __ArrayInstPtr(anEventArray)->a_element[6] = t; __STORE(anEventArray, t);
+            t = __MKUINT(ev.xselection.time); __ArrayInstPtr(anEventArray)->a_element[7] = t; __STORE(anEventArray, t);
+            break;
+
+        case ColormapNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(colormapNotify:state:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = cme->state == ColormapInstalled ? true : false;
+            break;
+
+        case ClientMessage:
+            if (ev.xclient.message_type == (int) __AtomVal(__INST(protocolsAtom))) {
+                if ((ev.xclient.data.l[0] == (int) __AtomVal(__INST(quitAppAtom)))
+                 || (ev.xclient.data.l[0] == (int) __AtomVal(__INST(deleteWindowAtom)))) {
+                    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(terminateView:);
+                    break;
+                }
+                if (ev.xclient.data.l[0] == (int) __AtomVal(__INST(saveYourselfAtom))) {
+                    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(saveAndTerminateView:);
+                    break;
+                }
+            }
+            /*
+             * any other client message
+             */
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(clientMessage:type:format:data:);
+            __ArrayInstPtr(anEventArray)->a_element[3] = __MKATOMOBJ(ev.xclient.message_type);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __MKSMALLINT(ev.xclient.format);
+            t = __MKBYTEARRAY(&ev.xclient.data, sizeof(ev.xclient.data)); __ArrayInstPtr(anEventArray)->a_element[5] = t; __STORE(anEventArray, t);
+            break;
+
+        case MappingNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(mappingNotify:request:event:);
+            switch(mape->request) {
+                case MappingModifier:
+                    arg = @symbol(mappingModifier);
+                    break;
+                case MappingKeyboard:
+                    arg = @symbol(mappingKeyboard);
+                    break;
+                case MappingPointer:
+                    arg = @symbol(mappingPointer);
+                    break;
+                default:
+                    arg = __MKSMALLINT(mape->request);
+                    break;
+            }
+            __ArrayInstPtr(anEventArray)->a_element[3] = arg;
+            t = __MKBYTEARRAY(&ev, sizeof(*mape)); __ArrayInstPtr(anEventArray)->a_element[4] = t;
+            __STORE(anEventArray, t);
+            break;
+
+        case KeymapNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(keymapNotify:);
+            break;
+
+        case MapRequest:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(mapRequest:);
+            break;
+
+        case ReparentNotify:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(reparentedView:parentId:x:y:);
+            t = __MKEXTERNALADDRESS(rpe->parent);
+            __ArrayInstPtr(anEventArray)->a_element[3] = t; __STORE(anEventArray, t);
+            __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(rpe->x);
+            __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(rpe->y);
+            break;
+
+        default:
+            __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(unknownX11Event);
+            break;
+    }
+#undef ae
+#undef ee
+#undef ke
+#undef be
+#undef ce
+#undef cr
+#undef cre
+#undef cle
+#undef gre
+#undef me
+#undef ewe
+#undef ele
+#undef lwe
+#undef de
+#undef mape
+#undef ve
+#undef fe
+#undef rr
+#undef rpe
+#undef pe
+#undef cie
+#undef sce
+#undef cme
+
+%}.
+
+    ^ true
+!
+
+handleAllEvents
+    "from now on, handle any kind of event"
+
+    dispatchingExpose := nil
+!
+
+handleExposeOnlyFor:aView
+    "from now on, handle expose events only"
+
+    dispatchingExpose := aView id
+!
+
+registerHotKeyForWindow:aDrawableId withId:anId modifiers:aModifier virtualKeyCode:aVirtualKeyCode
+    "Defines a system-wide hot key."
+    <resource: #todo>
+
+    "no-op until implemented"
+
+    ^ false.
+!
+
+setEventMask:aMask in:aWindowId
+    "tell X that we are only interested in events from aMask, which
+     is the bitwise or of the eventMask bits (see 'eventMaskFor:')"
+
+    <context: #return>
+%{
+
+    int mask;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __isSmallInteger(aMask)) {
+        mask = __intVal(aMask);
+
+#ifdef OLD
+        /* these may not be disabled */
+        mask |= ExposureMask | StructureNotifyMask |
+                KeyPressMask | KeyReleaseMask |
+                EnterWindowMask | LeaveWindowMask |
+                ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
+#endif
+
+        ENTER_XLIB();
+        XSelectInput(myDpy, __WindowVal(aWindowId), mask);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+startDispatch
+    "redefined to clear dispatchingExpose, which is a special X feature"
+
+    (dispatchProcess notNil and:[dispatchProcess isDead not]) ifTrue:[^ self].
+    dispatchingExpose := nil.
+    super startDispatch.
+!
+
+unregisterHotKeyForWindow:aDrawableId withId:anId
+    "Release a system-wide hot key."
+    <resource: #todo>
+
+    "no-op until implemented. Since we never registered anything, the unregister succeeds"
+
+    ^ true.
+!
+
+viewIsRelevantInCheckForEndOfDispatch:aView
+    aView == windowGroupWindow ifTrue:[^ false].
+    ^ super viewIsRelevantInCheckForEndOfDispatch:aView
+! !
+
+!XWorkstation methodsFor:'event handling-old dispatch'!
+
+buttonPress:button x:x y:y view:aView
+    "forward a button-press event for some view"
+
+    aView isNil ifTrue:[
+        "/ event arrived, after I destroyed it myself
+        ^ self
+    ].
+    button == 1 ifTrue:[
+        activateOnClick == true ifTrue:[
+            "/ dont raise above an active popup view.
+            (activeKeyboardGrab isNil and:[activePointerGrab isNil]) ifTrue:[
+                aView topView raise.
+"/            ] ifFalse:[
+"/                activeKeyboardGrab printCR.
+"/                activePointerGrab printCR.
+            ]
+        ].
+    ].
+    super buttonPress:button x:x y:y view:aView
+
+
+
+! !
+
+!XWorkstation methodsFor:'event sending'!
+
+sendClientEvent:msgType format:msgFormat to:targetWindowID propagate:propagate eventMask:eventMask window:windowID data1:d1 data2:d2 data3:d3 data4:d4 data5:d5
+    "send a ClientMessage to some other (possibly: non-ST/X) view.
+     The client message gets message_type and msgFormat as specified by
+     the arguments. The additional data arguments specify up to
+     5 longWords of user data; each may be an integer or nil.
+     It is passed transparently in the events data field.
+     See XProtocol specification for more details."
+
+    "/ Event.xclient.type              = ClientMessage;
+    "/ Event.xclient.display           = dpy;
+    "/ Event.xclient.message_type      = msgType;
+    "/ Event.xclient.format            = msgFormat;
+    "/ Event.xclient.window            = windowID;
+    "/ Event.xclient.data.l[0]         = d1
+    "/ Event.xclient.data.l[1]         = d2
+    "/ Event.xclient.data.l[2]         = d3
+    "/ Event.xclient.data.l[3]         = d4
+    "/ Event.xclient.data.l[4]         = d5
+    "/
+    "/ XSendEvent(dpy, targetWindowID, propagate, eventMask, &Event);
+
+    <context: #return>
+%{
+    int type;
+    int state;
+    int __eventMask;
+
+    if (ISCONNECTED
+     && __isInteger(msgType)
+     && __isInteger(msgFormat)
+     && (eventMask == nil || __isInteger(eventMask))
+     && (__isExternalAddress(windowID) || __isInteger(windowID))
+     && (__isExternalAddress(targetWindowID) || __isInteger(targetWindowID))) {
+        Display *dpy = myDpy;
+        XEvent ev;
+        Status result;
+        Window targetWindow;
+
+        if (__isInteger(d1)) {
+            ev.xclient.data.l[0] = __longIntVal(d1);
+        } else {
+            if (__isExternalAddress(d1)) {
+                ev.xclient.data.l[0] = (INT)__externalAddressVal(d1);
+            } else {
+                ev.xclient.data.l[0] = 0;
+            }
+        }
+        if (__isInteger(d2)) {
+            ev.xclient.data.l[1] = __longIntVal(d2);
+        } else {
+            if (__isExternalAddress(d2)) {
+                ev.xclient.data.l[1] = (INT)__externalAddressVal(d2);
+            } else {
+                ev.xclient.data.l[1] = 0;
+            }
+        }
+        if (__isInteger(d3)) {
+            ev.xclient.data.l[2] = __longIntVal(d3);
+        } else {
+            if (__isExternalAddress(d3)) {
+                ev.xclient.data.l[2] = (INT)__externalAddressVal(d3);
+            } else {
+                ev.xclient.data.l[2] = 0;
+            }
+        }
+        if (__isInteger(d4)) {
+            ev.xclient.data.l[3] = __longIntVal(d4);
+        } else {
+            if (__isExternalAddress(d4)) {
+                ev.xclient.data.l[3] = (INT)__externalAddressVal(d4);
+            } else {
+                ev.xclient.data.l[3] = 0;
+            }
+        }
+        if (__isInteger(d5)) {
+            ev.xclient.data.l[4] = __longIntVal(d5);
+        } else {
+            if (__isExternalAddress(d5)) {
+                ev.xclient.data.l[4] = (INT)__externalAddressVal(d5);
+            } else {
+                ev.xclient.data.l[4] = 0;
+            }
+        }
+
+        if (__isExternalAddress(windowID)) {
+            ev.xclient.window = __WindowVal(windowID);
+        } else {
+            ev.xclient.window = (Window)__longIntVal(windowID);
+        }
+
+        if (__isExternalAddress(targetWindowID)) {
+            targetWindow = __WindowVal(targetWindowID);
+        } else {
+            targetWindow = (Window)__longIntVal(targetWindowID);
+        }
+
+        ev.xclient.type              = ClientMessage;
+        ev.xclient.display           = dpy;
+        ev.xclient.message_type      = __longIntVal(msgType);
+        ev.xclient.format            = __longIntVal(msgFormat);
+
+        if (eventMask == nil) {
+            __eventMask = NoEventMask;
+        } else {
+            __eventMask = __longIntVal(eventMask);
+        }
+
+        ENTER_XLIB();
+        result = XSendEvent(dpy, targetWindow, (propagate == true ? True : False), __eventMask , &ev);
+        LEAVE_XLIB();
+
+        if ((result == BadValue) || (result == BadWindow)) {
+            DPRINTF(("bad status in sendClientEvent\n"));
+            RETURN ( false )
+        }
+        RETURN (true)
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false
+!
+
+sendKeyOrButtonEvent:typeSymbol x:xPos y:yPos keyOrButton:keySymCodeOrButtonNr state:stateMask toViewId:targetId
+    "send a keyPress/Release or buttonPress/Release event to some (possibly alien) view.
+     TypeSymbol must be one of: #keyPress, #keyRelease, #buttonPress , #buttonRelease.
+     For buttonEvents, the keySymCodeOrButtonNr must be the buttons number (1, 2 ...);
+     for key events, it can be either a symbol (as listen in X's keySyms)
+     or a numeric keysym code. If state is nil, the modifier bits (shift & control)
+     are computed from the keyboardMap - if non-nil, these are passed as modifierbits.
+     The non-nil case is the lowlevel entry, where state must include any shift/ctrl information
+     (not very user friendly)"
+
+    <context: #return>
+%{
+    int type;
+    int state;
+
+    if (__isSmallInteger(stateMask)) {
+        state = __intVal(stateMask);
+    } else {
+        state = 0;
+    }
+
+    if (ISCONNECTED
+     && __isSmallInteger(xPos) && __isSmallInteger(yPos)
+     && (__isSmallInteger(keySymCodeOrButtonNr) || __isStringLike(keySymCodeOrButtonNr))
+     && (__isExternalAddress(targetId) || __isInteger(targetId))) {
+        Display *dpy = myDpy;
+
+        XEvent ev;
+        Window target;
+        Status result;
+        KeySym keySym, *syms;
+        int screen = __intVal(__INST(screen));
+        char s[2];
+        int nSyms;
+
+        if ((typeSymbol == @symbol(keyPress))
+         || (typeSymbol == @symbol(keyRelease))) {
+            if (__isStringLike(keySymCodeOrButtonNr)) {
+                keySym = XStringToKeysym(__stringVal(keySymCodeOrButtonNr));
+            } else {
+                if (__isCharacter(keySymCodeOrButtonNr)) {
+                    s[0] = __intVal(__characterVal(keySymCodeOrButtonNr));
+                    s[1] = '\0';
+                    keySym = XStringToKeysym(s);
+                } else {
+                    keySym = (KeySym) __intVal(keySymCodeOrButtonNr);
+                }
+            }
+            ev.xkey.keycode = XKeysymToKeycode(dpy, keySym);
+
+            if (stateMask == nil) {
+                /*
+                 * get the modifier from the keySym
+                 */
+                nSyms = 0;
+                syms = XGetKeyboardMapping(dpy, ev.xkey.keycode, 1, &nSyms);
+                if (syms) {
+                    int i;
+
+                    for (i=0; i<nSyms; i++) {
+                        if (syms[i] == keySym) {
+#ifdef MODIFIERDEBUG
+                            console_printf("modifier-index is %d\n", i);
+#endif
+                            if (i) state = (1 << (i-1));
+                            break;
+                        }
+                    }
+                    XFree(syms);
+                }
+            }
+        } else {
+            if ((typeSymbol == @symbol(buttonPress))
+             || (typeSymbol == @symbol(buttonRelease))) {
+                if (__isSmallInteger(keySymCodeOrButtonNr)) {
+                    ev.xbutton.button = __intVal(keySymCodeOrButtonNr);
+                } else {
+                    ev.xbutton.button = 1;
+                }
+            } else {
+                DPRINTF(("invalid sendEvent typeSymbol\n"));
+                RETURN (false);
+            }
+        }
+
+        if (typeSymbol == @symbol(keyPress))
+            ev.xany.type = KeyPress;
+        else if (typeSymbol == @symbol(keyRelease))
+            ev.xany.type = KeyRelease;
+        else if (typeSymbol == @symbol(buttonPress))
+            ev.xany.type = ButtonPress;
+        else if (typeSymbol == @symbol(buttonRelease))
+            ev.xany.type = ButtonRelease;
+
+        if (__isExternalAddress(targetId)) {
+            target = __WindowVal(targetId);
+        } else {
+            target = (Window) __longIntVal(targetId);
+        }
+        ev.xkey.window = target;
+        ev.xkey.same_screen = 1;
+        ev.xkey.subwindow = 0;
+        ev.xkey.root = RootWindow(dpy, screen);
+        ev.xkey.x = __intVal(xPos);
+        ev.xkey.y = __intVal(yPos);
+        ev.xkey.state = state;
+        ev.xkey.time = CurrentTime;
+
+        ENTER_XLIB();
+        result = XSendEvent(dpy, target, False, 0 , &ev);
+        LEAVE_XLIB();
+        if ((result == BadValue) || (result == BadWindow)) {
+            DPRINTF(("bad status\n"));
+            RETURN ( false )
+        }
+        RETURN (true)
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false
+! !
+
+!XWorkstation methodsFor:'font stuff'!
+
+createFontFor:aFontName
+    "a basic method for X-font allocation; this method allows
+     any font to be aquired (even those not conforming to
+     standard naming conventions, such as cursor, fixed or k14)"
+
+    <context: #return>
+
+%{  /* STACK: 100000 */
+    /*** UNLIMITEDSTACK */
+
+    XFontStruct *newFont;
+
+    if (ISCONNECTED
+     && __isStringLike(aFontName)) {
+
+        ENTER_XLIB();
+        newFont = XLoadQueryFont(myDpy, (char *)__stringVal(aFontName));
+        LEAVE_XLIB();
+#ifdef COUNT_RESOURCES
+        if (newFont)
+            __cnt_font++;
+#endif
+
+        RETURN ( newFont ? __MKEXTERNALADDRESS(newFont) : nil );
+    }
+%}.
+    "/ --- disabled due to UNLIMITEDSTACK -- self primitiveFailedOrClosedConnection.
+    ^ nil
+!
+
+decomposeXFontName:aString into:aBlock
+    "extract family, face, style and size from an
+     X-font name
+     1 2     3      4    5     6         7 8      9    10   11   12 13 14       15
+      -brand-family-face-style-moreStyle- -height-size-resX-resY-??-??-registry-encoding;
+     evaluate aBlock with these"
+
+    |family face style moreStyle fheight size
+     resX resY registry encoding coding fields|
+
+    aString isNil ifTrue:[^ false].
+    fields := aString asCollectionOfSubstringsSeparatedBy:$-.
+    fields size == 3 ifTrue:[
+        "take care of old font names: family-style-size"
+        family := fields at:1.
+        style := fields at:2.
+        size := Number readFromString:(fields at:3) onError:[^ false].
+    ] ifFalse:[fields size == 2 ifTrue:[
+        "take care of old font names: family-size"
+        family := fields at:1.
+        size := Number readFromString:(fields at:2) onError:[^ false].
+    ] ifFalse:[fields size >= 15 ifTrue:[
+        family := fields at:3.
+        face := fields at:4.
+        style := fields at:5.
+        style = 'o' ifTrue:[
+            style := 'oblique'
+        ] ifFalse:[style = 'i' ifTrue:[
+             style := 'italic'
+        ] ifFalse:[style = 'r' ifTrue:[
+             style := 'roman'
+        ]]].
+        moreStyle := fields at:6.
+        (moreStyle ~= 'normal' and:[moreStyle size > 1]) ifTrue:[
+            style := style, '-', moreStyle.
+        ].
+        fheight := fields at:8.
+        size := (Number readFromString:(fields at:9) onError:[^ false]) / 10.
+        resX := fields at:10.
+        resY := fields at:11.
+        registry := fields at:14.
+        encoding := fields at:15.
+        coding := registry , '-' , encoding.
+    ] ifFalse:[
+        ^ false
+    ]]].
+    aBlock value:family value:face value:style value:size value:coding.
+    ^ true
+!
+
+encodingOf:aFontId
+    "the fonts encoding - if the font does not provide that info,
+     return nil (and assume #ascii, which is a subset of #iso8859-1)."
+
+    |props reg enc coll|
+
+    props := self fontPropertiesOf:aFontId.
+    reg := props at:#'CHARSET_REGISTRY' ifAbsent:nil.
+    enc := props at:#'CHARSET_ENCODING' ifAbsent:nil.
+    coll := props at:#'CHARSET_COLLECTIONS' ifAbsent:nil.
+
+    reg notNil ifTrue:[ reg := self atomName:reg].
+    enc notNil ifTrue:[ enc := self atomName:enc].
+    coll notNil ifTrue:[ coll := self atomName:coll].
+
+    ^ self extractEncodingFromRegistry:reg encoding:enc charSetCollections:coll
+
+     "
+       Screen current encodingOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
+     "
+!
+
+extentsOf:aString from:index1 to:index2 inFont:aFontId into:anArray
+
+    <context: #return>
+
+%{  /* UNLIMITEDSTACK */
+
+    XFontStruct *f;
+    char *cp;
+    int len, n, i1, i2, l;
+#   define NLOCALBUFFER 200
+    XChar2b xlatebuffer[NLOCALBUFFER];
+    int nInstBytes;
+    int directionReturn, fontAscentReturn, fontDescentReturn;
+    XCharStruct overAllReturn;
+    OBJ *resultArray;
+
+    if (ISCONNECTED
+         && __bothSmallInteger(index1, index2)
+         && __isExternalAddress(aFontId)
+         && __isNonNilObject(aString)) {
+        int lMax = __intVal(@global(MaxStringLength));
+        f = __FontVal(aFontId);
+        if (! f) goto fail;
+
+        if (__isArray(anArray) && __arraySize(anArray) > 0) {
+            resultArray = __arrayVal(anArray);
+        } else {
+            resultArray = 0;
+        }
+
+        i1 = __intVal(index1) - 1;
+
+        if (i1 >= 0) {
+            OBJ cls;
+
+            i2 = __intVal(index2) - 1;
+            if (i2 < i1) {
+                RETURN ( __MKSMALLINT(0) );
+            }
+
+            cp = (char *) __stringVal(aString);
+            l = i2 - i1 + 1;
+
+            if (__isStringLike(aString)) {
+                n = __stringSize(aString);
+                if (i2 >= n) goto fail;
+                cp += i1;
+                len = XTextExtents(f, cp, l,
+                                        &directionReturn, &fontAscentReturn, &fontDescentReturn,
+                                        &overAllReturn);
+            } else {
+                cls = __qClass(aString);
+                nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+                cp += nInstBytes;
+                n = __byteArraySize(aString) - nInstBytes;
+
+                if (__isBytes(aString)) {
+                    if (i2 >= n) goto fail;
+
+                    cp += i1;
+                    len = XTextExtents(f, cp, l,
+                                            &directionReturn, &fontAscentReturn, &fontDescentReturn,
+                                            &overAllReturn);
+                } else  if (__isWords(aString)) { /* TWOBYTESTRINGS */
+                    union {
+                        char b[2];
+                        unsigned short s;
+                    } u;
+                    int i;
+                    XChar2b *cp2 = (XChar2b *)0;
+                    int mustFree = 0;
+
+                    n = n / 2;
+                    if (i2 >= n) goto fail;
+
+                    cp += (i1 * 2);
+                    if (l > lMax) l = lMax;
+
+                    /*
+                     * ST/X TwoByteStrings store the asciiValue in native byteOrder;
+                     * X expects them MSB first
+                     * convert as required
+                     */
+
+                    u.s = 0x1234;
+                    if (u.b[0] != 0x12) {
+                        if (l <= NLOCALBUFFER) {
+                            cp2 = xlatebuffer;
+                        } else {
+                            cp2 = (XChar2b *)(malloc(l * 2));
+                            mustFree = 1;
+                        }
+                        for (i=0; i<l; i++) {
+                            cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
+                            cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
+                        }
+                        cp = (char *) cp2;
+                    }
+
+                    len = XTextExtents16(f, (XChar2b *)cp, l,
+                                            &directionReturn, &fontAscentReturn, &fontDescentReturn,
+                                            &overAllReturn);
+
+                    if (mustFree) {
+                        free(cp2);
+                    }
+                } else if (__isLongs(aString)) { /* FOURBYTESTRINGS */
+                    union {
+                        char b[2];
+                        unsigned short s;
+                    } u;
+                    int i;
+                    XChar2b *cp2 = (XChar2b *)0;
+                    int mustFree = 0;
+
+                    n = n / 4;
+                    if (i2 >= n) goto fail;
+
+                    cp += (i1 * 4);
+                    if (l > lMax) l = lMax;
+
+                    /*
+                     * For now: X does not support 32bit characters without the new 32Unicode extensions.
+                     * For now, treat chars above 0xFFFF as 0xFFFF (should we use default-char ?).
+                     */
+                    if (l <= NLOCALBUFFER) {
+                        cp2 = xlatebuffer;
+                    } else {
+                        cp2 = (XChar2b *)(malloc(l * 2));
+                        mustFree = 1;
+                    }
+                    for (i=0; i<l; i++) {
+                        int codePoint;
+
+                        codePoint = ((unsigned int32 *)cp)[i];
+                        if (codePoint > 0xFFFF) {
+                            codePoint = 0xFFFF;
+                        }
+                        cp2[i].byte1 = codePoint & 0xFF;
+                        cp2[i].byte2 = (codePoint >> 8) & 0xFF;;
+                    }
+                    cp = (char *) cp2;
+
+                    len = XTextExtents16(f, (XChar2b *)cp, l,
+                                            &directionReturn, &fontAscentReturn, &fontDescentReturn,
+                                            &overAllReturn);
+                    if (mustFree) {
+                        free(cp2);
+                    }
+                } else
+                    goto fail;      /*unknown string class */
+            }
+            if (resultArray) {
+                switch (__arraySize(anArray)) {
+                default:
+                case 8:
+                    resultArray[7] = __MKSMALLINT(directionReturn);
+                case 7:
+                    resultArray[6] = __MKSMALLINT(fontDescentReturn);
+                case 6:
+                    resultArray[5] = __MKSMALLINT(fontAscentReturn);
+                case 5:
+                    resultArray[4] = __MKSMALLINT(overAllReturn.descent);
+                case 4:
+                    resultArray[3] = __MKSMALLINT(overAllReturn.ascent);
+                case 3:
+                    resultArray[2] = __MKSMALLINT(overAllReturn.width);
+                case 2:
+                    resultArray[1] = __MKSMALLINT(overAllReturn.rbearing);
+                case 1:
+                    resultArray[0] = __MKSMALLINT(overAllReturn.lbearing);
+                case 0:
+                    break;
+                }
+            }
+            RETURN ( __MKSMALLINT(overAllReturn.width) );
+        }
+    }
+#undef NLOCALBUFFER
+fail: ;
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ 0
+
+    "
+      |result|
+      result := Array new:8.
+      Screen current
+        extentsOf:'hello World' from:1 to:11
+        inFont:(Screen current  getFontWithFoundry:'*'
+                    family:'courier new'
+                    weight:'medium'
+                    slant:'r'
+                    spacing:nil
+                    pixelSize:nil
+                    size:10
+                    encoding:#'iso10646-1'
+            )
+        into:result.
+
+      result
+    "
+!
+
+extractEncodingFromRegistry:registry encoding:encoding charSetCollections:charSetCollections
+    "given registry and encoding as returned by X11,
+     generate a single symbol naming the ST/X encoding.
+     I.e. from registry='ISO8859' and encoding='1', generate #'iso8859-1'.
+     This is pure magic ..."
+
+    |enc charSets|
+
+    (registry size ~~ 0) ifTrue:[
+        enc := registry asLowercase.
+        encoding size ~~ 0 ifTrue:[
+           enc := enc, '-', encoding asLowercase.
+        ].
+        enc := enc asSymbol.
+    ] ifFalse:[
+        (encoding size ~~ 0) ifTrue:[
+            enc := encoding asLowercase asSymbol
+        ] ifFalse:[
+            charSets := charSetCollections.
+            (charSets notEmptyOrNil) ifTrue:[
+                charSets := charSets asUppercase asCollectionOfWords.
+                (charSets includes:'ISO8859-1') ifTrue:[
+                    enc := #'iso8859-1'
+                ] ifFalse:[
+                    (charSets includes:'ISO8859') ifTrue:[
+                        enc := #iso8859
+                    ] ifFalse:[
+                        (charSets includes:'ASCII') ifTrue:[
+                            enc := #ascii
+                        ] ifFalse:[
+                            (charSets includes:'ADOBE-STANDARD') ifTrue:[
+                                enc := #iso8859
+                            ]
+                        ]
+                    ]
+                ]
+            ]
+        ]
+    ].
+    ^  enc
+
+    "Created: 17.4.1996 / 14:57:06 / cg"
+    "Modified: 17.4.1996 / 17:22:35 / cg"
+!
+
+flushListOfAvailableFonts
+    "flush the cached list of all available fonts on this display.
+     Required if new fonts have been added on the display server."
+
+    listOfXFonts := nil.
+    XftFontDescription notNil ifTrue:[
+        XftFontDescription flushListOfAvailableFonts.
+    ].
+
+    "
+     Display flushListOfAvailableFonts.
+     Display listOfAvailableFonts
+    "
+
+    "Modified: 27.9.1995 / 10:54:47 / stefan"
+    "Created: 20.2.1996 / 22:55:52 / cg"
+!
+
+fontDescriptionFromXFontName:aFontNameString
+    "extract family, face, style and size from an
+     X-font name
+     1 2     3      4    5     6         7 8      9    10   11   12 13 14       15
+      -brand-family-face-style-moreStyle- -pxlSize-size-resX-resY-??-??-registry-encoding;
+     evaluate aBlock with these"
+
+    |family face style moreStyle size
+     resX resY registry encoding coding fields|
+
+    aFontNameString isNil ifTrue:[^ nil].
+
+    Error handle:[:ex |
+        family := nil.
+    ] do:[
+        fields := aFontNameString asCollectionOfSubstringsSeparatedBy:$-.
+        fields size == 3 ifTrue:[
+            "take care of old font names: family-style-size"
+            family := fields at:1.
+            style := fields at:2.
+            size := Number readFromString:(fields at:3).
+        ] ifFalse:[
+            fields size == 2 ifTrue:[
+                "take care of old font names: family-size"
+                family := fields at:1.
+                size := Number readFromString:(fields at:2).
+            ] ifFalse:[
+                fields size >= 15 ifTrue:[
+                    family := fields at:3.
+                    face := fields at:4.
+                    style := fields at:5.
+                    style = 'o' ifTrue:[
+                        style := 'oblique'
+                    ] ifFalse:[style = 'i' ifTrue:[
+                         style := 'italic'
+                    ] ifFalse:[style = 'r' ifTrue:[
+                         style := 'roman'
+                    ]]].
+                    moreStyle := fields at:6.
+                    (moreStyle ~= 'normal' and:[moreStyle size > 1]) ifTrue:[
+                        style := style, '-', moreStyle.
+                    ].
+"/                    pxlSize := (Integer readFromString:(fields at:8)).
+                    size := (Number readFromString:(fields at:9)) / 10.
+                    resX := fields at:10.
+                    resY := fields at:11.
+                    registry := fields at:14.
+                    encoding := fields at:15.
+                    coding := registry , '-' , encoding.
+                ] ifFalse:[
+                    "/ very old name (such as cursor, 5x7 etc)
+                ]
+            ]
+        ].
+    ].
+
+    family notNil ifTrue:[
+       ^ FontDescription family:family face:face style:style size:size sizeUnit:#pt encoding:coding.
+    ].
+    ^ FontDescription name:aFontNameString
+
+    "
+     Screen current fontDescriptionFromXFontName:'-arabic-newspaper-medium-r-normal--32-246-100-100-p-137-iso10646-1'
+    "
+!
+
+fontMetricsOf:fontId
+    "return a fonts metrics info object"
+
+    <context: #return>
+
+    |info avgAscent avgDescent minCode maxCode dir
+     maxAscent maxDescent minWidth maxWidth avgWidth|
+
+%{  /* UNLIMITEDSTACK */
+    XFontStruct *f;
+    int len;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(fontId)) {
+            f = __FontVal(fontId);
+            if (f) {
+                minCode = __MKUINT((f->min_byte1<<8) + f->min_char_or_byte2);
+                maxCode = __MKUINT((f->max_byte1<<8) + f->max_char_or_byte2);
+
+                if (f->direction == FontLeftToRight) {
+                    dir = @symbol(LeftToRight);
+                } else if (f->direction == FontRightToLeft) {
+                    dir = @symbol(RightToLeft);
+                }
+                avgAscent = __MKSMALLINT(f->ascent);
+                avgDescent = __MKSMALLINT(f->descent);
+                maxAscent = __MKSMALLINT(f->max_bounds.ascent);
+                maxDescent = __MKSMALLINT(f->max_bounds.descent);
+                minWidth = __MKSMALLINT(f->min_bounds.width);
+                maxWidth = __MKSMALLINT(f->max_bounds.width);
+
+                ENTER_XLIB();
+                len = XTextWidth(f, "n", 1);
+                LEAVE_XLIB();
+
+                avgWidth = __MKSMALLINT( len );
+            }
+        }
+    }
+%}.
+    avgAscent == nil ifTrue:[
+        self primitiveFailedOrClosedConnection.
+        ^ nil
+    ].
+
+    "DingBats font returns 0 for maxAscent/maxDescent"
+    maxAscent := maxAscent max:avgAscent.
+    maxDescent := maxDescent max:avgDescent.
+
+    info := DeviceWorkstation::DeviceFontMetrics new.
+    info
+      ascent:avgAscent
+      descent:avgDescent
+      maxAscent:maxAscent
+      maxDescent:maxDescent
+      minWidth:minWidth
+      maxWidth:maxWidth
+      avgWidth:avgWidth
+      minCode:minCode
+      maxCode:maxCode
+      direction:dir.
+    ^ info
+
+    "
+     Screen current fontMetricsOf:(View defaultFont onDevice:Screen current) fontId
+     CharacterSetView openOn:(View defaultFont onDevice:Screen current)
+
+     Screen current fontMetricsOf:(MenuView defaultFont onDevice:Screen current) fontId
+     CharacterSetView openOn:(MenuView defaultFont onDevice:Screen current)
+    "
+!
+
+fontProperties:propertyNames of:aFontId
+    "Answer an array with selected property values of a font.
+     This is X11-Specific.
+     PropertyNames is an array with property names (symbols or strings).
+     Nonexistant properties are returned as nil"
+
+    |props|
+
+    props := self fontPropertiesOf:aFontId.
+    ^ propertyNames collect:[:propName | props at:propName ifAbsent:nil].
+
+    "
+     Screen current
+        fontProperties:#(#'PIXEL_SIZE' #'POINT_SIZE' RESOLUTION notExistant)
+        of:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
+    "
+!
+
+fontPropertiesOf:aFontId
+    "Answer an array with all the properties of a font.
+     This is X11-Specific.
+     Odd indices contain the property name (atom)
+     Even indices contain the property value (atom)
+
+     Answer nil, if there are no properties"
+
+    |propsArray result|
+
+%{
+    XFontStruct *f;
+    XFontProp *prop;
+    int n, i;
+    OBJ x;
+
+    if (__isExternalAddress(aFontId)) {
+        f = __FontVal(aFontId);
+        if (f && (prop = f->properties) != 0) {
+            n = f->n_properties;
+            propsArray = __ARRAY_NEW_INT(n*2);
+            for (i = 0; n; n--, prop++) {
+                x = __MKUINT(prop->name); __ArrayInstPtr(propsArray)->a_element[i++] = x; __STORE(propsArray, x);
+                x = __MKUINT(prop->card32); __ArrayInstPtr(propsArray)->a_element[i++] = x; __STORE(propsArray, x);
+            }
+        }
+    }
+%}.
+    result := Dictionary new.
+    propsArray notNil ifTrue:[
+        propsArray pairWiseDo:[:n :v | result at:(self atomName:n) put:v].
+    ].
+    ^ result
+
+    "
+     Screen current fontPropertiesOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
+     Dictionary withKeysAndValues:(Screen current fontPropertiesOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1'))
+
+     |d|
+     d := Dictionary new.
+     (Screen current fontPropertiesOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')) keysAndValuesDo:[:name :value|
+          d at:name put:((Screen current atomName:value) ? value)
+     ].
+     d
+    "
+!
+
+fontResolutionOf:fontId
+    "return the resolution (as dpiX @ dpiY) of the font - this is usually the displays resolution,
+     but due to errors in some XServer installations, some use 75dpi fonts on higher
+     resolution displays and vice/versa."
+
+    |props res resX resY|
+
+    props := self fontProperties:#(#'RESOLUTION_X' #'RESOLUTION_Y' RESOLUTION) of:fontId.
+    resX := props at:1.
+    resY := props at:2.
+    (resX notNil and:[resY notNil]) ifTrue:[
+        ^ resX @ resY
+    ].
+    res := props at:3.
+    res notNil ifTrue:[
+        ^ res @ res
+    ].
+    ^ self resolution
+
+    "
+      Screen current fontResolutionOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
+    "
+!
+
+fullFontNameOf:aFontId
+    "the fonts fullName - this is very device specific and should only be
+     used for user feed-back (for example: in the fontPanel).
+     If the display/font does not provide that info, return nil."
+
+    |props fullName|
+
+    props := self fontPropertiesOf:aFontId.
+    #('FONT' 'FONT_NAME' 'FULL_NAME' 'FULLNAME' ) do:[:try |
+        |fullNameID|
+
+        fullNameID := props at:try ifAbsent:nil.
+        fullNameID notNil ifTrue:[
+            fullName := self atomName:fullNameID.
+            fullName notEmptyOrNil ifTrue:[
+                ^ fullName
+            ].
+        ]
+    ].
+
+    ^ nil.
+
+    "
+     Screen current fullFontNameOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
+    "
+!
+
+getAvailableFontsMatching:pattern
+    "return an Array filled with font names matching aPattern"
+
+    <context: #return>
+
+%{  /* UNLIMITEDSTACK */
+
+    int nnames = 30000;
+    int available = nnames + 1;
+    char **fonts;
+    OBJ arr, str;
+    int i;
+
+    if (ISCONNECTED) {
+        if (__isStringLike(pattern)) {
+            for (;;) {
+                ENTER_XLIB();
+                fonts = XListFonts(myDpy, __stringVal(pattern), nnames, &available);
+                LEAVE_XLIB();
+                if (fonts == 0) RETURN(nil);
+                if (available < nnames) break;
+                XFreeFontNames(fonts);
+                nnames = available * 2;
+            }
+
+            /*
+             * now, that we know the number of font names,
+             * create the array ...
+             */
+            arr = __ARRAY_NEW_INT(available);
+            if (arr != nil) {
+                /*
+                 * ... and fill it
+                 */
+                for (i=0; i<available; i++) {
+                    __PROTECT__(arr);
+                    str = __MKSTRING(fonts[i]);
+                    __UNPROTECT__(arr);
+                    __ArrayInstPtr(arr)->a_element[i] = str; __STORE(arr, str);
+                }
+            }
+            XFreeFontNames(fonts);
+            RETURN (arr);
+        }
+    }
+%}.
+    ^ nil
+
+    "
+      Screen current getAvailableFontsMatching:'*'
+    "
+!
+
+getDefaultFontWithEncoding:encoding
+    "return a default font id - used when class Font cannot
+     find anything usable"
+
+    |id|
+
+    id := self createFontFor:'-misc-fixed-*-*-*-*-*-*-*-*-*-*-', encoding.
+    id isNil ifTrue:[
+        id := self createFontFor:'fixed'
+    ].
+    ^ id.
+
+     "
+       Screen current getDefaultFontWithEncoding:#'iso10646-1'
+     "
+!
+
+getFontWithFamily:familyString face:faceString
+            style:styleArgString size:sizeArgOrNil sizeUnit:sizeUnit encoding:encoding
+
+    "try to get the specified font, if not available, try next smaller
+     font. Access to X-fonts by name is possible, by passing the X font name
+     as family and the other parameters as nil. For example, the cursor font
+     can be aquired that way."
+
+    |styleString theName theId xlatedStyle
+     id spacing encodingMatch idx roundedSize pixelSize pointSize|
+
+    styleString := styleArgString.
+
+    sizeArgOrNil notNil ifTrue:[
+        roundedSize := sizeArgOrNil rounded asInteger.
+        sizeUnit == #px ifTrue:[
+            pixelSize := roundedSize.
+        ] ifFalse:[
+            pointSize := roundedSize.
+        ].
+    ].
+
+    "special: if face is nil, allow access to X-fonts"
+    faceString isNil ifTrue:[
+        roundedSize notNil ifTrue:[
+            theName := familyString , '-' , roundedSize printString
+        ] ifFalse:[
+            theName := familyString
+        ].
+        theName notNil ifTrue:[
+            theId := self createFontFor:theName.
+        ].
+        theId isNil ifTrue:[
+            theId := self getDefaultFontWithEncoding:encoding
+        ].
+        ^ theId
+    ].
+
+    "/ spacing other than 'normal' is contained as last component
+    "/ in style
+
+    (styleString notNil
+     and:[(styleString endsWith:'-narrow')
+          or:[styleString endsWith:'-semicondensed']]) ifTrue:[
+        |i|
+        i := styleString lastIndexOf:$-.
+        spacing := styleString copyFrom:(i+1).
+        styleString := styleString copyTo:(i-1).
+    ] ifFalse:[
+        spacing := 'normal'.
+    ].
+
+    xlatedStyle := styleString.
+    xlatedStyle notNil ifTrue:[
+        xlatedStyle := xlatedStyle first asString
+    ].
+
+    encoding isNil ifTrue:[
+        encodingMatch := '*-*'.
+    ] ifFalse:[
+        idx := encoding indexOf:$-.
+        idx ~~ 0 ifTrue:[
+            encodingMatch := encoding
+        ] ifFalse:[
+            encodingMatch := encoding , '-*'.
+        ].
+    ].
+
+    id := self
+            getFontWithFoundry:'*'
+            family:familyString asLowercase
+            weight:faceString
+            slant:xlatedStyle
+            spacing:spacing
+            pixelSize:pixelSize
+            size:pointSize
+            encoding:encodingMatch.
+
+    id isNil ifTrue:[
+        (encodingMatch notNil and:[encodingMatch ~= '*']) ifTrue:[
+            "/ too stupid: registries come in both cases
+            "/ and X does not ignore case
+            "/
+            id := self
+                    getFontWithFoundry:'*'
+                    family:familyString asLowercase
+                    weight:faceString
+                    slant:xlatedStyle
+                    spacing:spacing
+                    pixelSize:nil
+                    size:roundedSize
+                    encoding:encodingMatch asUppercase.
+            id isNil ifTrue:[
+                id := self
+                        getFontWithFoundry:'*'
+                        family:familyString asLowercase
+                        weight:faceString
+                        slant:xlatedStyle
+                        spacing:spacing
+                        pixelSize:nil
+                        size:roundedSize
+                        encoding:encodingMatch asLowercase.
+            ]
+        ]
+    ].
+    ^ id
+
+    "Modified: 4.7.1996 / 11:38:47 / stefan"
+    "Modified: 10.4.1997 / 19:20:06 / cg"
+!
+
+getFontWithFoundry:foundry family:family weight:weight
+              slant:slant spacing:spc pixelSize:pSize size:size
+              encoding:encoding
+
+    "get the specified font, if not available, return nil.
+     Individual attributes can be left empty (i.e. '') or nil to match any.
+
+     foundry: 'adobe', 'misc', 'dec', 'schumacher' ... usually '*'
+     family:  'helvetica' 'courier' 'times' ...
+     weight:  'bold' 'medium' 'demi' ...
+     slant:   'r(oman)' 'i(talic)' 'o(blique)'
+     spacing: 'narrow' 'normal' semicondensed' ... usually '*'
+     pixelSize: 16,18 ... usually left empty
+     size:      size in point (1/72th of an inch)
+     encoding:  iso8859-*, iso8859-1, iso10646-1 ... '*'
+    "
+
+    |theName sizeMatch
+     foundryMatch familyMatch weightMatch slantMatch spcMatch
+     pSizeMatch encodingMatch|
+
+    "this works only on 'Release >= 3' - X-servers"
+    "name is:
+        -foundry-family    -weight -slant-
+         sony    helvetica bold     r
+         adobe   courier   medium   i
+         msic    fixed              o
+         ...     ...
+    "
+
+    size isNil ifTrue:[
+        sizeMatch := '*'
+    ] ifFalse:[
+        sizeMatch := size printString , '0'
+    ].
+    foundry isNil ifTrue:[
+        foundryMatch := '*'
+    ] ifFalse:[
+        foundryMatch := foundry
+    ].
+    family isNil ifTrue:[
+        familyMatch := '*'
+    ] ifFalse:[
+        familyMatch := family
+    ].
+    weight isNil ifTrue:[
+        weightMatch := '*'
+    ] ifFalse:[
+        weightMatch := weight
+    ].
+    slant isNil ifTrue:[
+        slantMatch := '*'
+    ] ifFalse:[
+        slantMatch := slant
+    ].
+    spc isNil ifTrue:[
+        spcMatch := '*'
+    ] ifFalse:[
+        spcMatch := spc
+    ].
+    pSize isNil ifTrue:[
+        pSizeMatch := '*'
+    ] ifFalse:[
+        pSizeMatch := pSize printString
+    ].
+    encoding isNil ifTrue:[
+        encodingMatch := '*'
+    ] ifFalse:[
+        encodingMatch := encoding
+    ].
+
+    theName := ('-' , foundryMatch,
+                '-' , familyMatch,
+                '-' , weightMatch ,
+                '-' , slantMatch ,
+                '-' , spcMatch ,
+                '-*' ,
+                '-' , pSizeMatch ,
+                '-' , sizeMatch ,
+                '-*-*-*-*' ,
+                '-' , encodingMatch).
+
+"/  Transcript showCR:theName; endEntry.
+
+    ^ self createFontFor:theName.
+
+
+    "
+     Display
+        getFontWithFoundry:'*'
+        family:'courier'
+        weight:'medium'
+        slant:'r'
+        spacing:nil
+        pixelSize:nil
+        size:13
+        encoding:#'iso8859-1'.
+
+     Display
+        getFontWithFoundry:'*'
+        family:'courier'
+        weight:'medium'
+        slant:'r'
+        spacing:nil
+        pixelSize:nil
+        size:13
+        encoding:#'iso10646-1'
+    "
+
+    "Modified: 10.4.1997 / 19:15:44 / cg"
+!
+
+heightOf:aString from:index1 to:index2 inFont:aFontId
+    |resultArray|
+
+    resultArray := Array new:5.
+    self extentsOf:aString from:index1 to:index2 inFont:aFontId into:resultArray.
+    ^ (resultArray at:4) + (resultArray at:5).
+
+    "
+      Screen current
+        heightOf:'hello world' from:1 to:10
+        inFont:(Screen current  getFontWithFoundry:'*'
+                    family:'courier new'
+                    weight:'medium'
+                    slant:'r'
+                    spacing:nil
+                    pixelSize:nil
+                    size:13
+                    encoding:#'iso10646-1'
+            ).
+
+      Screen current
+        heightOf:'hello World gggÖÜ' from:1 to:15
+        inFont:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
+    "
+!
+
+listOfAvailableFonts
+    "return a list with all available fonts on this display.
+     Since this takes some time, keep the result of the query for the
+     next time. The elements of the returned collection are instances of
+     FontDescription."
+
+    |names|
+
+    listOfXFonts isNil ifTrue:[
+        names := self getAvailableFontsMatching:'*'.
+        names isNil ifTrue:[
+            "no names returned ..."
+            ^ nil
+        ].
+        listOfXFonts := names collect:[:aName | self fontDescriptionFromXFontName:aName].
+        listOfXFonts := FontDescription genericFonts, listOfXFonts.
+    ].
+
+    (XftFontDescription notNil
+            and:[ XftFontDescription isLoaded
+            and:[ true "self queryXftLibrary" ]]
+    ) ifTrue:[
+        UserPreferences current useXftFontsOnly ifTrue:[
+            ^ (XftFontDescription listOfAvailableFonts)
+        ].
+        ^ listOfXFonts , (XftFontDescription listOfAvailableFonts).
+    ].
+    ^ listOfXFonts
+
+    "
+     Display flushListOfAvailableFonts.
+     Display listOfAvailableFonts.
+
+     Display getAvailableFontsMatching:'*'.
+     Display getAvailableFontsMatching:'fixed'.
+     Display fontsInFamily:'fixed' filtering:nil.
+    "
+
+    "Modified: 27.9.1995 / 10:54:47 / stefan"
+    "Modified: 17.4.1996 / 15:27:57 / cg"
+!
+
+pixelSizesInFamily:aFamilyName face:aFaceName style:aStyleName filtering:filter
+    "return a set of all available font sizes in aFamily/aFace/aStyle
+     on this display.
+     Redefined to handle X's special case of 0-size (which stands for any)"
+
+    |sizes|
+
+    sizes := super pixelSizesInFamily:aFamilyName face:aFaceName style:aStyleName filtering:filter.
+    (sizes notNil and:[sizes isEmpty or:[sizes includes:0]]) ifTrue:[
+        "special: in X11R5 and above, size 0 means:
+         there are scaled versions in all sizes available"
+
+        ^ #(4 5 6 7 8 9 10 11 12 14 16 18 20 22 24 28 32 48 64 72 96 144 192 288)
+    ].
+    ^ sizes
+
+    "
+     Display pixelSizesInFamily:'courier' face:'bold' style:'roman' filtering:nil
+    "
+
+    "Created: 27.2.1996 / 01:38:15 / cg"
+!
+
+releaseFont:aFontId
+
+    <context: #return>
+%{
+    XFontStruct *f;
+
+    /*
+     * ignore closed connection
+     */
+    if (! ISCONNECTED) {
+        RETURN ( self );
+    }
+
+    if (__isExternalAddress(aFontId)) {
+        f = __FontVal(aFontId);
+        if (f) {
+
+            ENTER_XLIB();
+            XFreeFont(myDpy, f);
+            LEAVE_XLIB();
+#ifdef COUNT_RESOURCES
+            __cnt_font--;
+#endif
+        }
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailed
+!
+
+sizesInFamily:aFamilyName face:aFaceName style:aStyleName filtering:filter
+    "return a set of all available font sizes in aFamily/aFace/aStyle
+     on this display.
+     Redefined to handle X's special case of 0-size (which stands for any)"
+
+    |sizes|
+
+    sizes := super sizesInFamily:aFamilyName face:aFaceName style:aStyleName filtering:filter.
+    (sizes notNil and:[sizes includes:0]) ifTrue:[
+	"special: in X11R5 and above, size 0 means:
+	 there are scaled versions in all sizes available"
+
+	^ #(4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 22 24 28 32 48 64 72 96 144 192 288)
+    ].
+    ^ sizes
+
+    "
+     Display sizesInFamily:'courier' face:'bold' style:'roman' filtering:nil
+    "
+
+    "Created: 27.2.1996 / 01:38:15 / cg"
+!
+
+widthOf:aString from:index1 to:index2 inFont:aFontId
+
+    <context: #return>
+
+%{  /* UNLIMITEDSTACK */
+
+    XFontStruct *f;
+    char *cp;
+    int len, n, i1, i2, l;
+#   define NLOCALBUFFER 200
+    XChar2b xlatebuffer[NLOCALBUFFER];
+    int nInstBytes;
+    int directionReturn, fontAscentReturn, fontDescentReturn;
+    XCharStruct overAllReturn;
+
+    if (ISCONNECTED) {
+        if (__bothSmallInteger(index1, index2)
+         && __isExternalAddress(aFontId)
+         && __isNonNilObject(aString)) {
+            int lMax = __intVal(@global(MaxStringLength));
+            f = __FontVal(aFontId);
+            if (! f) goto fail;
+
+            i1 = __intVal(index1) - 1;
+
+            if (i1 >= 0) {
+                OBJ cls;
+
+                i2 = __intVal(index2) - 1;
+                if (i2 < i1) {
+                    RETURN ( __MKSMALLINT(0) );
+                }
+
+                cp = (char *) __stringVal(aString);
+                l = i2 - i1 + 1;
+
+                if (__isStringLike(aString)) {
+                    n = __stringSize(aString);
+                    if (i2 < n) {
+                        cp += i1;
+
+#if 1
+                        len = XTextExtents(f, cp, l,
+                                                &directionReturn, &fontAscentReturn, &fontDescentReturn,
+                                                &overAllReturn);
+                        //console_printf("lBear:%d rBear:%d width:%d\n", overAllReturn.lbearing, overAllReturn.rbearing, overAllReturn.width);
+                        RETURN ( __MKSMALLINT(overAllReturn.width) );
+#else
+                        ENTER_XLIB();
+                        len = XTextWidth(f, cp, l);
+                        LEAVE_XLIB();
+                        RETURN ( __MKSMALLINT(len) );
+#endif
+                    }
+                }
+
+                cls = __qClass(aString);
+                nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+                cp += nInstBytes;
+
+                if (__isBytes(aString)) {
+                    n = __byteArraySize(aString) - nInstBytes;
+                    if (i2 < n) {
+                        cp += i1;
+
+#if 1
+                        len = XTextExtents(f, cp, l,
+                                                &directionReturn, &fontAscentReturn, &fontDescentReturn,
+                                                &overAllReturn);
+                        RETURN ( __MKSMALLINT(overAllReturn.width) );
+#else
+                        ENTER_XLIB();
+                        len = XTextWidth(f, cp, l);
+                        LEAVE_XLIB();
+                        RETURN ( __MKSMALLINT(len) );
+#endif
+                    }
+                }
+
+                /* TWOBYTESTRINGS */
+                if (__isWords(aString)) {
+                    n = (__byteArraySize(aString) - nInstBytes) / 2;
+
+                    if (i2 < n) {
+                        union {
+                            char b[2];
+                            unsigned short s;
+                        } u;
+                        int i;
+                        XChar2b *cp2 = (XChar2b *)0;
+                        int mustFree = 0;
+
+                        cp += (i1 * 2);
+                        if (l > lMax) l = lMax;
+
+                        /*
+                         * ST/X TwoByteStrings store the asciiValue in native byteOrder;
+                         * X expects them MSB first
+                         * convert as required
+                         */
+
+                        u.s = 0x1234;
+                        if (u.b[0] != 0x12) {
+                            if (l <= NLOCALBUFFER) {
+                                cp2 = xlatebuffer;
+                            } else {
+                                cp2 = (XChar2b *)(malloc(l * 2));
+                                mustFree = 1;
+                            }
+                            for (i=0; i<l; i++) {
+                                cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
+                                cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
+                            }
+                            cp = (char *) cp2;
+                        }
+
+#if 1
+                        len = XTextExtents16(f, (XChar2b *)cp, l,
+                                                &directionReturn, &fontAscentReturn, &fontDescentReturn,
+                                                &overAllReturn);
+                        len = overAllReturn.width;
+#else
+                        ENTER_XLIB();
+                        len = XTextWidth16(f, (XChar2b *)cp, l);
+                        LEAVE_XLIB();
+#endif
+
+                        if (mustFree) {
+                            free(cp2);
+                        }
+
+                        RETURN ( __MKSMALLINT(len) );
+                    }
+                }
+                /* FOURBYTESTRINGS */
+                if (__isLongs(aString)) {
+                    int i;
+                    XChar2b *cp2;
+                    int mustFree = 0;
+
+                    n = (__byteArraySize(aString) - nInstBytes) / 4;
+                    if (i2 < n) {
+                        union {
+                            char b[2];
+                            unsigned short s;
+                        } u;
+                        int i;
+                        XChar2b *cp2 = (XChar2b *)0;
+                        int mustFree = 0;
+
+                        cp += (i1 * 4);
+                        if (l > lMax) l = lMax;
+
+                        /*
+                         * For now: X does not support 32bit characters without the new 32Unicode extensions.
+                         * For now, treat chars above 0xFFFF as 0xFFFF (should we use default-char ?).
+                         */
+                        if (l <= NLOCALBUFFER) {
+                            cp2 = xlatebuffer;
+                        } else {
+                            cp2 = (XChar2b *)(malloc(l * 2));
+                            mustFree = 1;
+                        }
+                        for (i=0; i<l; i++) {
+                            int codePoint;
+
+                            codePoint = ((unsigned int32 *)cp)[i];
+                            if (codePoint > 0xFFFF) {
+                                codePoint = 0xFFFF;
+                            }
+                            cp2[i].byte1 = codePoint & 0xFF;
+                            cp2[i].byte2 = (codePoint >> 8) & 0xFF;;
+                        }
+                        cp = (char *) cp2;
+
+#if 1
+                        len = XTextExtents16(f, (XChar2b *)cp, l,
+                                                &directionReturn, &fontAscentReturn, &fontDescentReturn,
+                                                &overAllReturn);
+                        len = overAllReturn.width;
+#else
+                        ENTER_XLIB();
+                        len = XTextWidth16(f, (XChar2b *)cp, l);
+                        LEAVE_XLIB();
+#endif
+
+                        if (mustFree) {
+                            free(cp2);
+                        }
+
+                        RETURN ( __MKSMALLINT(len) );
+                    }
+                }
+            }
+        }
+    }
+#undef NLOCALBUFFER
+fail: ;
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ 0
+! !
+
+!XWorkstation methodsFor:'grabbing'!
+
+allowEvents:mode
+    <context: #return>
+%{
+
+    int _mode, ok = 1;
+
+    if (mode == @symbol(asyncPointer))
+        _mode = AsyncPointer;
+    else if (mode == @symbol(syncPointer))
+        _mode = SyncPointer;
+    else if (mode == @symbol(asyncKeyboard))
+        _mode = AsyncKeyboard;
+    else if (mode == @symbol(syncKeyboard))
+        _mode = SyncKeyboard;
+    else if (mode == @symbol(syncBoth))
+        _mode = SyncBoth;
+    else if (mode == @symbol(asyncBoth))
+        _mode = AsyncBoth;
+    else if (mode == @symbol(replayPointer))
+        _mode = ReplayPointer;
+    else if (mode == @symbol(replayKeyboard))
+        _mode = ReplayKeyboard;
+    else
+        ok = 0;
+
+    if (ok
+     && ISCONNECTED) {
+        ENTER_XLIB();
+        XAllowEvents(myDpy, _mode, CurrentTime);
+        LEAVE_XLIB();
+
+        RETURN (self);
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+grabKeyboardIn:aWindowId
+    "grab the keyboard"
+
+    <context: #return>
+%{
+    int result, ok;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aWindowId)) {
+
+            ENTER_XLIB();
+            result = XGrabKeyboard(myDpy,
+                                   __WindowVal(aWindowId),
+                                   True /* False */,
+                                   GrabModeAsync,
+                                   GrabModeAsync,
+                                   CurrentTime);
+            LEAVE_XLIB();
+
+            ok = 0;
+            switch(result) {
+                case AlreadyGrabbed:
+                    if (@global(ErrorPrinting) == true) {
+                        console_fprintf(stderr, "XWorkstation [warning]: grab keyboard: AlreadyGrabbed\n");
+                    }
+                    break;
+                case GrabNotViewable:
+                    if (@global(ErrorPrinting) == true) {
+                        console_fprintf(stderr, "XWorkstation [warning]: grab keyboard: GrabNotViewable\n");
+                    }
+                    break;
+                case GrabInvalidTime:
+                    if (@global(ErrorPrinting) == true) {
+                        console_fprintf(stderr, "XWorkstation [warning]: grab keyboard: InvalidTime\n");
+                    }
+                    break;
+                case GrabFrozen:
+                    if (@global(ErrorPrinting) == true) {
+                        console_fprintf(stderr, "XWorkstation [warning]: grab keyboard: Frozen\n");
+                    }
+                    break;
+                default:
+                    ok = 1;
+                    break;
+            }
+            if (! ok) {
+                ENTER_XLIB();
+                XUngrabKeyboard(myDpy, CurrentTime);
+                LEAVE_XLIB();
+                RETURN (false);
+            }
+
+            RETURN ( true );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false
+!
+
+grabPointerIn:aWindowId withCursor:aCursorId eventMask:eventMask pointerMode:pMode keyboardMode:kMode confineTo:confineId
+    "grap the pointer - return true if ok"
+
+    <context: #return>
+%{
+
+    int result, ok, evMask;
+    Window confineWin;
+    Cursor curs;
+    int pointer_mode, keyboard_mode;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aWindowId)) {
+            if (__isExternalAddress(confineId))
+                confineWin = __WindowVal(confineId);
+            else
+                confineWin = (Window) None;
+
+            if (__isExternalAddress(aCursorId))
+                curs = __CursorVal(aCursorId);
+            else
+                curs = (Cursor) None;
+
+            if (pMode == @symbol(sync))
+                pointer_mode = GrabModeSync;
+            else
+                pointer_mode = GrabModeAsync;
+
+            if (kMode == @symbol(sync))
+                keyboard_mode = GrabModeSync;
+            else
+                keyboard_mode = GrabModeAsync;
+
+            if (__isSmallInteger(eventMask))
+                evMask = __intVal(eventMask);
+            else
+                evMask = ButtonPressMask | ButtonMotionMask | PointerMotionMask | ButtonReleaseMask;
+
+
+/*
+            ENTER_XLIB();
+*/
+            result = XGrabPointer(myDpy,
+                                  __WindowVal(aWindowId),
+                                  False,
+                                  evMask,
+                                  pointer_mode, keyboard_mode,
+                                  confineWin,
+                                  curs,
+                                  CurrentTime);
+/*
+            LEAVE_XLIB();
+*/
+
+
+            ok = 0;
+            switch (result) {
+                case AlreadyGrabbed:
+                    if (@global(ErrorPrinting) == true) {
+                        console_fprintf(stderr, "XWorkstation [warning]: grab pointer: AlreadyGrabbed\n");
+                    }
+                    break;
+                case GrabNotViewable:
+                    if (@global(ErrorPrinting) == true) {
+                        console_fprintf(stderr, "XWorkstation [warning]: grab pointer: GrabNotViewable\n");
+                    }
+                    break;
+                case GrabInvalidTime:
+                    if (@global(ErrorPrinting) == true) {
+                        console_fprintf(stderr, "XWorkstation [warning]: grab pointer: InvalidTime\n");
+                    }
+                    break;
+                case GrabFrozen:
+                    if (@global(ErrorPrinting) == true) {
+                        console_fprintf(stderr, "XWorkstation [warning]: grab pointer: Frozen\n");
+                    }
+                    break;
+                default:
+                    ok = 1;
+                    break;
+            }
+
+            if (! ok) {
+/*
+                ENTER_XLIB();
+*/
+                XUngrabPointer(myDpy, CurrentTime);
+/*
+                LEAVE_XLIB();
+*/
+                RETURN (false);
+            }
+            RETURN ( true );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false
+!
+
+grabPointerIn:aWindowId withCursor:aCursorId pointerMode:pMode keyboardMode:kMode confineTo:confineId
+    "grap the pointer - return true if ok"
+
+    ^ self
+        grabPointerIn:aWindowId
+        withCursor:aCursorId
+        eventMask:nil
+        pointerMode:pMode
+        keyboardMode:kMode
+        confineTo:confineId
+
+    "Modified: / 28.7.1998 / 02:47:51 / cg"
+!
+
+primUngrabKeyboard
+    "release the keyboard"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        ENTER_XLIB();
+        XUngrabKeyboard(dpy, CurrentTime);
+        XSync(dpy, 0);
+        LEAVE_XLIB();
+
+    }
+%}.
+!
+
+primUngrabPointer
+    "release the pointer"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        ENTER_XLIB();
+        XUngrabPointer(dpy, CurrentTime);
+        XSync(dpy, 0);
+        LEAVE_XLIB();
+
+    }
+%}.
+!
+
+ungrabKeyboard
+    "release the keyboard"
+
+    activeKeyboardGrab notNil ifTrue:[
+        activeKeyboardGrab := nil.
+        self primUngrabKeyboard.
+    ]
+!
+
+ungrabPointer
+    "release the pointer"
+
+    activePointerGrab notNil ifTrue:[
+        activePointerGrab := nil.
+        self primUngrabPointer.
+    ]
+! !
+
+!XWorkstation methodsFor:'graphic context stuff'!
+
+noClipIn:aDrawableId gc:aGCId
+    "disable clipping rectangle"
+
+    <context: #return>
+%{
+
+    XGCValues gcv;
+    GC gc;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)) {
+            gc = __GCVal(aGCId);
+            gcv.clip_mask = None;
+            ENTER_XLIB();
+            XChangeGC(myDpy, gc, GCClipMask, &gcv);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setBackground:bgColorIndex in:aGCId
+    "set background color to be drawn with"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)
+         && __isSmallInteger(bgColorIndex)) {
+            ENTER_XLIB();
+            XSetBackground(myDpy, __GCVal(aGCId), __intVal(bgColorIndex));
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setBitmapMask:aBitmapId in:aGCId
+    "set or clear the drawing mask - a bitmap mask using current fg/bg"
+
+    <context: #return>
+%{
+
+    GC gc;
+    Pixmap bitmap;
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        if (__isExternalAddress(aGCId)) {
+            gc = __GCVal(aGCId);
+            if (__isExternalAddress(aBitmapId)) {
+                bitmap = __PixmapVal(aBitmapId);
+                ENTER_XLIB();
+                XSetStipple(dpy, gc, bitmap);
+                XSetFillStyle(dpy, gc, FillOpaqueStippled);
+                LEAVE_XLIB();
+                RETURN ( self );
+            }
+            if (aBitmapId == nil) {
+                ENTER_XLIB();
+                XSetFillStyle(dpy, gc, FillSolid);
+                LEAVE_XLIB();
+                RETURN ( self );
+            }
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setClipByChildren:aBool in:aDrawableId gc:aGCId
+    "enable/disable drawing into child views"
+
+    <context: #return>
+%{
+
+    XGCValues gcv;
+    GC gc;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)) {
+            gc = __GCVal(aGCId);
+            if (aBool == true)
+                gcv.subwindow_mode = ClipByChildren;
+            else
+                gcv.subwindow_mode = IncludeInferiors;
+
+            ENTER_XLIB();
+            XChangeGC(myDpy, gc, GCSubwindowMode, &gcv);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setClipX:clipX y:clipY width:clipWidth height:clipHeight in:drawableId gc:aGCId
+    "clip to a rectangle"
+
+    <context: #return>
+%{
+
+    XRectangle r;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)
+         && __bothSmallInteger(clipX, clipY)
+         && __bothSmallInteger(clipWidth, clipHeight)) {
+            r.x = __intVal(clipX);
+            r.y = __intVal(clipY);
+            r.width = __intVal(clipWidth);
+            r.height = __intVal(clipHeight);
+            ENTER_XLIB();
+            XSetClipRectangles(myDpy, __GCVal(aGCId), 0, 0, &r, 1, Unsorted);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setDashes:dashList dashOffset:offset in:aGCId
+    "set line attributes"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)
+         && __isSmallInteger(offset)
+         && __isByteArrayLike(dashList)) {
+            ENTER_XLIB();
+            XSetDashes(myDpy, __GCVal(aGCId),
+                       __intVal(offset),
+                       __ByteArrayInstPtr(dashList)->ba_element,
+                       __byteArraySize(dashList));
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+bad: ;
+%}.
+    "
+     either aGCId is invalid,
+     and/or dashList is not a byteArray
+     and/or offset is not a smallInteger
+    "
+    self primitiveFailedOrClosedConnection
+!
+
+setFont:aFontId in:aGCId
+    "set font to be drawn in"
+
+    <context: #return>
+%{
+
+    XFontStruct *f;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aFontId)
+         && __isExternalAddress(aGCId)) {
+            f = (XFontStruct *) __FontVal(aFontId);
+            ENTER_XLIB();
+            XSetFont(myDpy, __GCVal(aGCId), f->fid);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    "
+     aGCId and/or aFontId are invalid
+    "
+    self primitiveFailedOrClosedConnection
+!
+
+setForeground:fgColorIndex background:bgColorIndex in:aGCId
+    "set foreground and background colors to be drawn with"
+
+    <context: #return>
+%{
+
+    GC gc;
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+        if (__bothSmallInteger(fgColorIndex, bgColorIndex)
+         && __isExternalAddress(aGCId)) {
+            gc = __GCVal(aGCId);
+
+            ENTER_XLIB();
+            XSetForeground(dpy, gc, __intVal(fgColorIndex));
+            XSetBackground(dpy, gc, __intVal(bgColorIndex));
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setForeground:fgColorIndex in:aGCId
+    "set foreground color to be drawn with"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)
+         && __isSmallInteger(fgColorIndex)) {
+            ENTER_XLIB();
+            XSetForeground(myDpy, __GCVal(aGCId), __intVal(fgColorIndex));
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setFunction:aFunctionSymbol in:aGCId
+    "set alu function to be drawn with"
+
+    <context: #return>
+%{
+
+    GC gc;
+    int fun = -1;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)) {
+            gc = __GCVal(aGCId);
+            if (aFunctionSymbol == @symbol(copy)) fun = GXcopy;
+            else if (aFunctionSymbol == @symbol(copyInverted)) fun = GXcopyInverted;
+            else if (aFunctionSymbol == @symbol(xor)) fun = GXxor;
+            else if (aFunctionSymbol == @symbol(and)) fun = GXand;
+            else if (aFunctionSymbol == @symbol(andReverse)) fun = GXandReverse;
+            else if (aFunctionSymbol == @symbol(andInverted)) fun = GXandInverted;
+            else if (aFunctionSymbol == @symbol(or)) fun = GXor;
+            else if (aFunctionSymbol == @symbol(orReverse)) fun = GXorReverse;
+            else if (aFunctionSymbol == @symbol(orInverted)) fun = GXorInverted;
+            else if (aFunctionSymbol == @symbol(invert)) fun = GXinvert;
+            else if (aFunctionSymbol == @symbol(clear)) fun = GXclear;
+            else if (aFunctionSymbol == @symbol(set)) fun = GXset;
+            else if (aFunctionSymbol == @symbol(noop)) fun = GXnoop;
+            else if (aFunctionSymbol == @symbol(equiv)) fun = GXequiv;
+            else if (aFunctionSymbol == @symbol(nand)) fun = GXnand;
+            if (fun != -1) {
+                ENTER_XLIB();
+                XSetFunction(myDpy, gc, fun);
+                LEAVE_XLIB();
+                RETURN ( self );
+            }
+        }
+    }
+%}.
+    "
+     either aGCId is not an integer, or an invalid symbol
+     was passed ... valid functions are #copy, #copyInverted, #xor, #and, #andReverse,
+     #andInverted, #or, #orReverse, #orInverted. See Xlib documentation for more details.
+    "
+    self primitiveFailedOrClosedConnection
+!
+
+setGraphicsExposures:aBoolean in:aGCId
+    "set or clear the graphics exposures flag"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)) {
+            ENTER_XLIB();
+            XSetGraphicsExposures(myDpy, __GCVal(aGCId), (aBoolean==true)?1:0);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setLineWidth:aNumber style:lineStyle cap:capStyle join:joinStyle in:aGCId
+    "set line attributes;
+     lineStyle must be one of #solid, #dashed or #doubleDashed;
+     capStyle one of: #notLast, #butt, #round or #projecting;
+     joinStyle one of: #miter, #bevel or #round."
+
+    <context: #return>
+%{
+
+    int x_style, x_cap, x_join;
+    static char dashList[2] = { 4,4 };
+    static char dotList[2]  = { 1,1 };
+    static char dashDotList[4]    = { 4,1 , 1,1 };
+    static char dashDotDotList[6] = { 4,1 , 1,1 , 1,1 };
+    char *x_dashes = 0;
+    int x_nDash;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aGCId)
+         && __isSmallInteger(aNumber)) {
+            Display *dpy = myDpy;
+
+            if (lineStyle == @symbol(solid)) {
+                x_dashes = (char *)0;
+                x_style = LineSolid;
+            } else if (lineStyle == @symbol(dashed)) {
+                x_dashes = dashList;
+                x_nDash = sizeof(dashList);
+                x_style = LineOnOffDash;
+            } else if (lineStyle == @symbol(doubleDashed)) {
+                x_dashes = dashList;
+                x_nDash = sizeof(dashList);
+                x_style = LineDoubleDash;
+            } else if (lineStyle == @symbol(dotted)) {
+                x_dashes = dotList;
+                x_nDash = sizeof(dotList);
+                x_style = LineOnOffDash;
+            } else if (lineStyle == @symbol(dashDot)) {
+                x_dashes = dashDotList;
+                x_nDash = sizeof(dashDotList);
+                x_style = LineOnOffDash;
+            } else if (lineStyle == @symbol(dashDotDot)) {
+                x_dashes = dashDotDotList;
+                x_nDash = sizeof(dashDotDotList);
+                x_style = LineOnOffDash;
+            } else goto bad;
+
+            if (capStyle == @symbol(notLast)) x_cap = CapNotLast;
+            else if (capStyle == @symbol(butt)) x_cap = CapButt;
+            else if (capStyle == @symbol(round)) x_cap  = CapRound;
+            else if (capStyle == @symbol(projecting)) x_cap  = CapProjecting;
+            else goto bad;
+
+            if (joinStyle == @symbol(miter)) x_join = JoinMiter;
+            else if (joinStyle == @symbol(bevel)) x_join = JoinBevel;
+            else if (joinStyle == @symbol(round)) x_join  = JoinRound;
+            else goto bad;
+
+            ENTER_XLIB();
+            if (x_dashes) {
+                XSetDashes(dpy, __GCVal(aGCId), 0, x_dashes, x_nDash);
+            }
+            XSetLineAttributes(dpy,
+                               __GCVal(aGCId), __intVal(aNumber),
+                               x_style, x_cap, x_join);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+bad: ;
+%}.
+    "
+     either aGCId is invalid,
+     and/or lineWidth is not a smallInteger,
+     and/or lineStyle is none of #solid, #dashed, #doubleDashed
+     and/or capStyle is none of #notLast, #butt, #round, #projecting
+     and/or joinStyle is none of #miter, #bevel, #round
+    "
+    self primitiveFailedOrClosedConnection
+!
+
+setMaskOriginX:orgX y:orgY in:aGCid
+    "set the mask origin"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+        if (__bothSmallInteger(orgX, orgY) && __isExternalAddress(aGCid)) {
+            ENTER_XLIB();
+            XSetTSOrigin(myDpy, __GCVal(aGCid), __intVal(orgX), __intVal(orgY));
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setPixmapMask:aPixmapId in:aGCId
+    "set or clear the drawing mask - a pixmap mask providing full color"
+
+    <context: #return>
+%{
+
+    GC gc;
+    Pixmap pixmap;
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        if (__isExternalAddress(aGCId)) {
+            gc = __GCVal(aGCId);
+            if (__isExternalAddress(aPixmapId)) {
+                pixmap = __PixmapVal(aPixmapId);
+                ENTER_XLIB();
+                XSetTile(dpy, gc, pixmap);
+                XSetFillStyle(dpy, gc, FillTiled);
+                LEAVE_XLIB();
+                RETURN ( self );
+            }
+            if (aPixmapId == nil) {
+                ENTER_XLIB();
+                XSetFillStyle(dpy, gc, FillSolid);
+                LEAVE_XLIB();
+                RETURN ( self );
+            }
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+! !
+
+!XWorkstation methodsFor:'initialization & release'!
+
+closeConnection
+    "close down the connection to the X-server"
+
+    <context: #return>
+
+"/ 'closing' errorPrintCR.
+"/ thisContext fullPrintAll.
+
+%{ /* UNLIMITEDSTACK */   /* calls XSync()! */
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+
+        __INST(displayId) = nil;
+        ENTER_XLIB();
+        XCloseDisplay(dpy);
+        LEAVE_XLIB();
+    }
+%}
+!
+
+emergencyCloseConnection
+    "low level close of the displays connection (without sending any buffered
+     requests to the display). Only used in case of emergency (brokenConnection)"
+
+%{
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        __INST(displayId) = nil;
+        close(ConnectionNumber(dpy));
+    }
+%}
+!
+
+eventBufferSize
+%{
+    RETURN ( __MKSMALLINT(sizeof(XEvent) + 100) );
+%}
+!
+
+getWindowGroupWindow
+    "Creates a fake WindowGroup view. This window is used
+     in XWMHints & _NET_WM_LEADER properties to define
+     application window group"
+
+    windowGroupWindow isNil ifTrue:[
+        windowGroupWindow := WindowGroupWindow new create.
+    ].
+    ^ windowGroupWindow
+!
+
+initializeDefaultValues
+    activateOnClick := false.
+    maxOperationsUntilFlush := nil.
+
+    super initializeDefaultValues.
+
+    "JV@2012: On X11, mouse buttons are: left=1, middle=2, right=3
+    Even on 2-button mouse (button 2 is simply not reported).
+    Here the middle button is mapped to button #paste (which in EditTextView
+    pastes the PRIMARY selection). 128 is here to make clear that this
+    is somewhat special value.
+
+    This remapping kludge is here to have all the widget's code backward/windows
+    compatible while still having X11's middle button behavior.
+
+    Also note, that buttonTranslation is overwritten in display.rc,
+    the code is here just for a case display.rc is not read/available
+    and for documentation (symbol references does not search .rc files).
+    "
+
+    buttonTranslation := buttonTranslation copy.
+    buttonTranslation at: 2 put: #paste
+
+    "Modified (comment): / 17-04-2012 / 21:18:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+initializeDeviceSignals
+    super initializeDeviceSignals.
+
+    deviceIOTimeoutErrorSignal := deviceIOErrorSignal newSignal.
+    deviceIOTimeoutErrorSignal nameClass:self message:#deviceIOTimeoutErrorSignal.
+
+    ObjectMemory registerErrorInterruptHandler:self class forID:#DisplayError.
+    ObjectMemory registerErrorInterruptHandler:self class forID:#DisplayIOError.
+    ObjectMemory registerErrorInterruptHandler:self class forID:#DisplayIOTimeoutError.
+!
+
+initializeFor:aDisplayName
+    "initialize the receiver for a connection to an X-Server;
+     the argument, aDisplayName may be nil (for the default server from
+     DISPLAY-variable or command line argument) or the name of the server
+     as hostname:number"
+
+    displayId notNil ifTrue:[
+        "/ already connected - you bad guy try to trick me manually ?
+        ^ self
+    ].
+
+    displayId := self openConnectionTo:aDisplayName.
+    displayId isNil ifTrue:[
+        "/ could not connect.
+        DeviceOpenErrorSignal raiseWith:aDisplayName.
+        ^ nil
+    ].
+
+    xlibTimeout := xlibTimeout ? DefaultXLibTimeout.
+    xlibTimeoutForWindowCreation := xlibTimeoutForWindowCreation ? DefaultXLibTimeoutForWindowCreation.
+    hasConnectionBroken := false.
+
+    dispatching := false.
+    dispatchingExpose := false.
+    isSlow := false.
+    shiftDown := false.
+    ctrlDown := false.
+    metaDown := false.
+    altDown := false.
+    motionEventCompression := true.
+    buttonsPressed := 0.
+    displayName := aDisplayName.
+
+    listOfXFonts := nil.
+
+    atoms := nil.
+
+    "These values are initialized by primitive code in #createWindowFor:..."
+    protocolsAtom := nil.
+    deleteWindowAtom := nil.
+    saveYourselfAtom := nil.
+    quitAppAtom := nil.
+
+    self initializeDeviceResourceTables.
+    self initializeScreenProperties.
+
+    self initializeDefaultValues.
+    self initializeSpecialFlags.
+    self initializeKeyboardMap.
+    self initializeDeviceSignals.
+
+    self initializeViewStyle.
+!
+
+initializeModifierMappings
+    "initialize keyboard modifiers.
+     We assume that mod1 are the META modifiers and mod2 are the ALT modifiers,
+     but if any of them contains the Num_Lock key, it is disregarded."
+
+    |map|
+
+    super initializeModifierMappings.
+
+    rawKeySymTranslation := RawKeySymTranslation.
+
+    map := self modifierMapping.
+    map isNil ifTrue:[
+        "/
+        "/ mhmh - a crippled Xlib which does not provide modifier mappings
+        "/ setup some reasonable default. If that is not sufficient,
+        "/ you have to change things from your display.rc file.
+        "/
+        altModifierMask := self modifier1Mask.
+        metaModifierMask := self modifier2Mask.
+    ] ifFalse:[
+        | mod symbolFromKeyCode nonNilOnes |
+
+        altModifierMask := 0.
+        metaModifierMask := 0.
+
+        symbolFromKeyCode := [:key | self symbolFromKeycode:key].
+        nonNilOnes := [:str | str notNil].
+
+        mod := map at:1.
+        mod notNil ifTrue:[
+            shiftModifiers := mod collect:symbolFromKeyCode thenSelect:nonNilOnes.
+        ].
+        mod := map at:3.
+        mod notNil ifTrue:[
+            ctrlModifiers  := mod collect:symbolFromKeyCode thenSelect:nonNilOnes.
+        ].
+        mod := map at:4.
+        mod notNil ifTrue:[
+            mod := mod collect:symbolFromKeyCode thenSelect:nonNilOnes.
+            (mod includes:#'Num_Lock') ifFalse:[
+                metaModifiers := mod.
+                metaModifierMask := 1 bitShift:(4-1).
+            ].
+        ].
+        mod := map at:5.
+        mod notNil ifTrue:[
+            mod := mod collect:symbolFromKeyCode thenSelect:nonNilOnes.
+            (mod includes:#'Num_Lock') ifFalse:[
+                altModifiers   := mod.
+                altModifierMask := 1 bitShift:(5-1).
+            ].
+        ]
+    ].
+
+    "
+     Display initializeModifierMappings
+    "
+
+    "Modified: 1.12.1995 / 23:44:40 / stefan"
+!
+
+initializeScreenBounds
+    self isXineramaActive ifTrue:[
+        |rect|
+
+        self monitorBounds do:[:eachRect|
+            rect isNil ifTrue:[
+                rect := eachRect.
+            ] ifFalse:[
+                rect := rect merge:eachRect.
+            ]
+        ].
+        width := rect width.
+        height := rect height.
+
+        "propagate possible size changes to our rottView"
+        rootView notNil ifTrue:[
+            rootView initialize.
+        ].
+    ] ifFalse:[
+        width := self queryWidth.
+        height := self queryHeight.
+    ].
+    widthMM := self queryWidthMM.
+    heightMM := self queryHeightMM.
+
+    "
+      Display initializeScreenBounds
+    "
+!
+
+initializeScreenProperties
+    |masks|
+
+    super initializeScreenProperties.
+
+    hasShapeExtension := self queryShapeExtension.
+    hasShmExtension := self querySHMExtension.
+    hasDPSExtension := self queryDPSExtension.
+    hasXVideoExtension := self queryXVideoExtension.
+    hasMbufExtension := self queryMBUFExtension.
+    hasPEXExtension := self queryPEXExtension.
+    hasImageExtension := self queryXIEExtension.
+    hasInputExtension := self queryXIExtension.
+    hasXineramaExtension := self queryXineramaExtension.
+    hasRenderExtension := self queryRenderExtension.
+    hasXftLibrary := self queryXftLibrary.
+
+    primaryAtom := self atomIDOf:#PRIMARY.
+    stringAtom := self atomIDOf:#STRING.
+    clipboardAtom := self atomIDOf:#CLIPBOARD.
+
+    altModifierMask := self modifier2Mask.
+    metaModifierMask := self modifier1Mask.
+
+    screen := self queryDefaultScreen.
+
+    self initializeScreenBounds.
+
+    depth := self queryDepth.
+    ncells := self queryCells.
+    blackpixel := self queryBlackPixel.
+    whitepixel := self queryWhitePixel.
+
+    monitorType := #unknown.
+    visualType := self queryDefaultVisualType.
+
+    hasColors := hasGreyscales := true.
+    (visualType == #StaticGray
+     or:[ visualType == #GrayScale]) ifTrue:[
+        hasColors := false.
+        monitorType := #monochrome.
+    ].
+
+    ncells == 2 ifTrue:[
+        hasColors := hasGreyscales := false.
+    ].
+
+    masks := self queryRGBMasks.
+    redMask := masks at:1.
+    greenMask := masks at:2.
+    blueMask := masks at:3.
+    bitsPerRGB := masks at:4.
+
+    visualType == #TrueColor ifTrue:[
+        redShift := redMask lowBit - 1.
+        greenShift := greenMask lowBit - 1.
+        blueShift := blueMask lowBit - 1.
+
+        bitsRed := redMask highBit - redMask lowBit + 1.
+        bitsGreen := greenMask highBit - greenMask lowBit + 1.
+        bitsBlue := blueMask highBit - blueMask lowBit + 1.
+    ].
+
+%{
+
+    Display *dpy;
+    int scr;
+    Visual *visual;
+    XVisualInfo viproto;
+    XVisualInfo *vip;                   /* returned info */
+    int maxRGBDepth, maxRGBADepth;
+    int rgbRedMask, rgbGreenMask, rgbBlueMask;
+    int rgbaRedMask, rgbaGreenMask, rgbaBlueMask, rgbaAlphaMask;
+    int rgbVisualID, rgbaVisualID;
+    int nvi, i;
+    char *type, *nm;
+    int dummy;
+
+    if (ISCONNECTED) {
+        dpy = myDpy;
+
+        /*
+         * look for RGB visual with the highest depth
+         */
+        nvi = 0;
+        viproto.screen = scr;
+        vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi);
+        maxRGBDepth = maxRGBADepth = 0;
+        for (i = 0; i < nvi; i++) {
+            int thisDepth = vip[i].depth;
+
+            switch (vip[i].class) {
+                case TrueColor:
+                    if (thisDepth > maxRGBDepth) {
+                        if (thisDepth <= 24) {
+                            maxRGBDepth = thisDepth;
+                            rgbRedMask = vip[i].red_mask;
+                            rgbGreenMask = vip[i].green_mask;
+                            rgbBlueMask = vip[i].blue_mask;
+                            rgbVisualID = vip[i].visualid;
+                        } else {
+                            if (thisDepth > maxRGBADepth) {
+                                // printf("found rgba visual!\n");
+                                maxRGBADepth = thisDepth;
+                                rgbaRedMask = vip[i].red_mask;
+                                rgbaGreenMask = vip[i].green_mask;
+                                rgbaBlueMask = vip[i].blue_mask;
+                                rgbaVisualID = vip[i].visualid;
+                            }
+                        }
+                    }
+                    break;
+            }
+        }
+        if (vip) XFree ((char *) vip);
+
+        if (maxRGBDepth) {
+            __INST(rgbVisual) = __MKEXTERNALADDRESS(rgbVisualID); __STORESELF(rgbVisual);
+        }
+        if (maxRGBADepth) {
+            __INST(rgbaVisual) = __MKEXTERNALADDRESS(rgbaVisualID); __STORESELF(rgbaVisual);
+            if (!maxRGBDepth) {
+                __INST(rgbVisual) = __INST(rgbaVisual); __STORESELF(rgbVisual);
+            }
+        }
+    }
+%}.
+!
+
+initializeSpecialFlags
+    "perform additional special server implementation flags"
+
+    "/
+    "/ assume we have it ... (should check)
+    "/
+    hasSaveUnder := true.
+    ignoreBackingStore := false.
+
+    (self serverVendor = 'X11/NeWS') ifTrue:[
+        "/
+        "/ this is a kludge around a bug in the X11/NeWS server,
+        "/ which does not correctly handle saveUnder
+        "/
+        hasSaveUnder := false.
+    ].
+!
+
+initializeUniqueID
+    uniqueDeviceID isNil ifTrue:[
+        uniqueDeviceID := UUID genUUID.
+    ]
+!
+
+invalidateConnection
+    super invalidateConnection.
+
+    "the new display may support a different set of fonts"
+    self flushListOfAvailableFonts
+!
+
+openConnectionTo:dpyName
+    "open a connection to some display;
+     return the displayId if ok, nil of not ok"
+
+%{ /* STACK:100000 */    /* XOpenDisplay() calls gethostbyname() */
+    Display *dpy;
+    int i;
+    char *nm;
+
+    if (__isStringLike(dpyName))
+        nm = (char *) __stringVal(dpyName);
+    else {
+        nm = NULL;
+    }
+    dpy = XOpenDisplay(nm);
+
+    if (dpy) {
+        static int firstCall = 1;
+        OBJ dpyID;
+
+        dpyID = __MKEXTERNALADDRESS(dpy);
+
+        if (firstCall) {
+            firstCall = 0;
+            XSetErrorHandler(__XErrorHandler__);
+            XSetIOErrorHandler(__XIOErrorHandler__);
+        }
+        RETURN (dpyID);
+    }
+%}.
+    ^ nil
+!
+
+queryBlackPixel
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        int scr;
+
+        dpy = myDpy;
+        scr = DefaultScreen(dpy);
+        RETURN ( __MKSMALLINT(BlackPixel(dpy, scr)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryBlackPixel
+    "
+!
+
+queryCells
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        int scr;
+
+        dpy = myDpy;
+        scr = DefaultScreen(dpy);
+        RETURN ( __MKSMALLINT(DisplayCells(dpy, scr)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryCells
+    "
+!
+
+queryDPSExtension
+%{  /* NOCONTEXT */
+
+#ifdef DPS
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XQueryExtension(dpy, "DPSExtension", &dummy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryDPSExtension
+    "
+!
+
+queryDefaultScreen
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+
+        dpy = myDpy;
+        RETURN ( __MKSMALLINT(DefaultScreen(dpy)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryDefaultScreen
+    "
+!
+
+queryDefaultVisualType
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        Visual *visual;
+
+        dpy = myDpy;
+        visual = DefaultVisualOfScreen(DefaultScreenOfDisplay(dpy));
+        switch (visual->class) {
+            case StaticGray:
+                RETURN ( @symbol(StaticGray) );
+            case GrayScale:
+                RETURN ( @symbol(GrayScale) );
+            case StaticColor:
+                RETURN ( @symbol(StaticColor) );
+            case PseudoColor:
+                RETURN ( @symbol(PseudoColor) );
+            case TrueColor:
+                RETURN ( @symbol(TrueColor) );
+            case DirectColor:
+                RETURN ( @symbol(DirectColor) );
+        }
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryDefaultVisualType
+    "
+!
+
+queryDepth
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        int scr;
+
+        dpy = myDpy;
+        scr = DefaultScreen(dpy);
+        RETURN ( __MKSMALLINT(DisplayPlanes(dpy, scr)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryDepth
+    "
+!
+
+queryHeight
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        int scr;
+
+        dpy = myDpy;
+        scr = DefaultScreen(dpy);
+        RETURN ( __MKSMALLINT(DisplayHeight(dpy, scr)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryHeight
+    "
+!
+
+queryHeightMM
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        int scr;
+
+        dpy = myDpy;
+        scr = DefaultScreen(dpy);
+        RETURN ( __MKSMALLINT(DisplayHeightMM(dpy, scr)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryHeightMM
+    "
+!
+
+queryMBUFExtension
+%{  /* NOCONTEXT */
+
+#ifdef MBUF
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XQueryExtension(dpy, "Multi-Buffering", &dummy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryMBUFExtension
+    "
+!
+
+queryPEXExtension
+%{  /* NOCONTEXT */
+
+#ifdef PEX5
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XQueryExtension(dpy, PEX_NAME_STRING, &dummy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryPEXExtension
+    "
+!
+
+queryRGBMasks
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        Visual *visual;
+        OBJ redMask, greenMask, blueMask, bprgb;
+
+        dpy = myDpy;
+        visual = DefaultVisualOfScreen(DefaultScreenOfDisplay(dpy));
+        redMask   = __MKSMALLINT(visual->red_mask);
+        greenMask = __MKSMALLINT(visual->green_mask);
+        blueMask  = __MKSMALLINT(visual->blue_mask);
+        bprgb  = __MKSMALLINT(visual->bits_per_rgb);
+        RETURN ( __ARRAY_WITH4(redMask, greenMask, blueMask, bprgb) );
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryRGBMasks
+    "
+!
+
+queryRenderExtension
+%{  /* NOCONTEXT */
+
+#ifdef XRENDER
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XRenderQueryExtension (dpy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryRenderExtension
+    "
+!
+
+querySHMExtension
+%{  /* NOCONTEXT */
+
+#ifdef xxSHM
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XQueryExtension(dpy, "MIT_SHM", &dummy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display querySHMExtension
+    "
+!
+
+queryShapeExtension
+%{  /* NOCONTEXT */
+
+#ifdef SHAPE
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XShapeQueryExtension(dpy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryShapeExtension
+    "
+!
+
+queryWhitePixel
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        int scr;
+
+        dpy = myDpy;
+        scr = DefaultScreen(dpy);
+        RETURN ( __MKSMALLINT(WhitePixel(dpy, scr)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryWhitePixel
+    "
+!
+
+queryWidth
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        int scr;
+
+        dpy = myDpy;
+        scr = DefaultScreen(dpy);
+        RETURN ( __MKSMALLINT(DisplayWidth(dpy, scr)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryWidth
+    "
+!
+
+queryWidthMM
+%{  /* NOCONTEXT */
+
+    if (ISCONNECTED) {
+        Display *dpy;
+        int scr;
+
+        dpy = myDpy;
+        scr = DefaultScreen(dpy);
+        RETURN ( __MKSMALLINT(DisplayWidthMM(dpy, scr)));
+    }
+%}.
+    ^ nil
+
+    "
+     Display queryWidthMM
+    "
+!
+
+queryXIEExtension
+%{  /* NOCONTEXT */
+
+#ifdef XIE
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XQueryExtension(dpy, xieExtName, &dummy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryXIEExtension
+    "
+!
+
+queryXIExtension
+%{  /* NOCONTEXT */
+
+#ifdef XI
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XQueryExtension(dpy, "XInputExtension", &dummy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryXIExtension
+    "
+!
+
+queryXVideoExtension
+%{  /* NOCONTEXT */
+
+#ifdef XVIDEO
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XQueryExtension(dpy, "XVideo", &dummy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryXVideoExtension
+    "
+!
+
+queryXftLibrary
+%{
+#ifndef XFT
+    RETURN (false);
+#endif
+%}.
+    ^ self queryRenderExtension
+!
+
+queryXineramaExtension
+%{  /* NOCONTEXT */
+
+#ifdef XINERAMA
+    if (ISCONNECTED) {
+        Display *dpy;
+        int dummy;
+
+        dpy = myDpy;
+
+        if (XineramaQueryExtension (dpy, &dummy, &dummy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display queryXineramaExtension
+    "
+!
+
+reinitialize
+    preWaitAction notNil ifTrue:[
+        Processor removePreWaitAction:preWaitAction.
+        preWaitAction := nil.
+    ].
+    virtualRootId := rootId := nil.
+    selectionFetchers := nil.
+    dispatchingExpose := nil
+!
+
+releaseDeviceResources
+    preWaitAction notNil ifTrue:[
+        Processor removePreWaitAction:preWaitAction.
+        preWaitAction := nil.
+    ].
+    selectionFetchers := nil.
+    super releaseDeviceResources.
+! !
+
+!XWorkstation methodsFor:'keyboard mapping'!
+
+altModifierMask
+    "return the mask (in motionEvents) for the alt-key modifier.
+     Notice: ST/X may use the left ALT key as CMD/Meta key,
+     therefore return a variable here, which can be changed during startup."
+
+    ^ altModifierMask
+
+    "Created: 23.3.1996 / 12:43:22 / cg"
+    "Modified: 23.3.1996 / 12:44:56 / cg"
+!
+
+altModifierMask:aSmallInteger
+    "define which key takes the role of an alt-key.
+     By default, this is X's modifier1, which is the ALT key on
+     most keyboards. However, there may be exceptions to this,
+     and the setting can be changed with:
+        Display altModifierMask:(Display modifier2Mask)
+     Setting the mask to 0 disables the ALT key (in ST/X) altogether.
+    "
+
+    altModifierMask := aSmallInteger
+!
+
+ctrlModifierMask
+    "return the Xlib mask bit for the control modifier key"
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(ControlMask));
+%}
+!
+
+metaModifierMask
+    "return the mask (in motionEvents) for the meta-key modifier.
+     Notice: ST/X may use the left ALT key as CMD/Meta key,
+     therefore return a variable here, which can be changed during startup."
+
+    ^ metaModifierMask
+
+    "Created: 23.3.1996 / 12:43:39 / cg"
+    "Modified: 23.3.1996 / 12:45:09 / cg"
+!
+
+metaModifierMask:aSmallInteger
+    "define which key takes the role of a meta key.
+     By default, this is X's modifier2, which is the 2nd ALT key on
+     most keyboards (if present at all).
+     However, there may be exceptions to this, and the setting can
+     be changed with:
+        Display metaModifierMask:(Display modifier1Mask)
+     Setting the mask to 0 disables the META key (in ST/X) altogether.
+     As reported, some Xservers place the Meta-key onto NumLock,
+     and having NumLock enabled makes ST/X think, that meta is pressed
+     all the time. On those, you should disable the meta key by setting
+     the mask to 0.
+    "
+
+    metaModifierMask := aSmallInteger
+!
+
+modifier1Mask
+    "return the Xlib mask bit for the 1st modifier key.
+     See comment in altModifierMask: / metaModifierMask: for what
+     this could be used."
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(Mod1Mask));
+%}
+!
+
+modifier2Mask
+    "return the Xlib mask bit for the 2nd modifier key.
+     See comment in altModifierMask: / metaModifierMask: for what
+     this could be used."
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(Mod2Mask));
+%}
+!
+
+modifier3Mask
+    "return the Xlib mask bit for the 3rd modifier key.
+     See comment in altModifierMask: / metaModifierMask: for what
+     this could be used."
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(Mod3Mask));
+%}
+!
+
+modifier4Mask
+    "return the Xlib mask bit for the 4th modifier key.
+     See comment in altModifierMask: / metaModifierMask: for what
+     this could be used."
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(Mod4Mask));
+%}
+!
+
+modifier5Mask
+    "return the Xlib mask bit for the 5th modifier key.
+     See comment in altModifierMask: / metaModifierMask: for what
+     this could be used."
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(Mod5Mask));
+%}
+!
+
+modifierMapping
+    "Get the Modifier Mapping.
+     We return an array of arrays of keycodes"
+
+    |modifierKeyMap maxKeyPerMod ret nextKey|
+
+    modifierKeyMap := self rawModifierMapping.
+    modifierKeyMap isEmptyOrNil ifTrue:[^ nil].
+    maxKeyPerMod := modifierKeyMap size // 8.
+
+    ret := Array new:8.
+    nextKey := 1.
+    1 to:8 do:[ :i |
+        (modifierKeyMap at:nextKey) ~= 0 ifTrue:[
+            |mod|
+
+            mod := OrderedCollection new:maxKeyPerMod.
+            modifierKeyMap from:nextKey to:(nextKey+maxKeyPerMod-1) do:[ :key |
+                key ~= 0 ifTrue:[
+                    mod add:key
+                ].
+            ].
+            ret at:i put:mod asArray.
+        ].
+        nextKey := nextKey+maxKeyPerMod.
+    ].
+
+    ^ ret
+
+    "
+     Display modifierMapping
+    "
+
+    "
+     |mapping|
+
+     mapping := Display modifierMapping.
+     ^ mapping collect:[:eachRow |
+                             eachRow notNil ifTrue:[
+                                 eachRow collect:[ :key | Display stringFromKeycode:key ].
+                             ] ifFalse:[
+                                 nil
+                             ]
+                       ].
+    "
+!
+
+rawKeySymTranslation
+    "Get the raw keyboard mapping (maps some special X-keySyms to STX-internal names
+     and can also be used to untranslate a stupid x-mapping (as on hpux)."
+
+    ^ rawKeySymTranslation
+
+
+    "
+     Display rawKeySymTranslation
+    "
+!
+
+rawModifierMapping
+    "Get the raw Modifier Mapping."
+
+    |modifierKeyMap|
+
+%{
+    XModifierKeymap *modmap;
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        if ((modmap = XGetModifierMapping(dpy)) != 0) {
+           modifierKeyMap = __BYTEARRAY_UNINITIALIZED_NEW_INT(modmap->max_keypermod * 8);
+           if (modifierKeyMap != nil) {
+                memcpy((char *)__ByteArrayInstPtr(modifierKeyMap)->ba_element,
+                       (char *)modmap->modifiermap, modmap->max_keypermod * 8);
+           }
+           XFreeModifiermap(modmap);
+        }
+    }
+%}.
+    ^ modifierKeyMap
+
+    "
+        Display rawModifierMapping
+    "
+!
+
+shiftModifierMask
+    "return the Xlib mask bit for the shift modifier key"
+
+%{  /* NOCONTEXT */
+    RETURN (__MKSMALLINT(ShiftMask));
+%}
+!
+
+superModifierMask
+    "return the Xlib mask bit for the super modifier key"
+
+    ^ self modifier4Mask
+!
+
+symbolFromKeycode:code
+    "Get a KeySymbol (a smalltalk symbol) from the keycode."
+
+    |str|
+
+%{
+    KeySym keysym;
+    char *keystring;
+
+    if (ISCONNECTED && __isSmallInteger(code)) {
+        Display *dpy = myDpy;
+
+// Our Windows Xlib does not support Xkb as of 2013-01
+//        if ((keysym = XkbKeycodeToKeysym(dpy, __intVal(code), 0, 0)) != NoSymbol
+        if ((keysym = XKeycodeToKeysym(dpy, __intVal(code), 0)) != NoSymbol
+            && (keystring = XKeysymToString(keysym)) != 0)
+            str = __MKSYMBOL(keystring, 0);
+    }
+%}.
+    ^ str
+
+    "
+        Display symbolFromKeycode:50
+    "
+! !
+
+!XWorkstation methodsFor:'misc'!
+
+beep
+    "output an audible beep or bell"
+
+    UserPreferences current beepEnabled ifTrue:[
+        self beep:0 volume:50
+    ]
+
+    "Modified: / 3.12.1999 / 17:13:59 / ps"
+!
+
+beep:aSymbolOrInteger volume:volumeInPercent
+    "output an audible beep. aSymbolOrInteger determines the sound, but is ignored here
+     (kept for comaptibilty with WinWorkstation)."
+
+    <context: #return>
+%{
+    int volume;
+
+    if (__isSmallInteger(volumeInPercent)
+     && ISCONNECTED) {
+        /* stupid: X wants -100 .. 100 and calls this percent */
+        volume = __intVal(volumeInPercent) * 2 - 100;
+        if (volume < -100) volume = -100;
+        else if (volume > 100) volume = 100;
+
+        ENTER_XLIB();
+        XBell(myDpy, volume);
+        LEAVE_XLIB();
+    }
+%}
+!
+
+buffered
+    "buffer drawing - do not send it immediately to the display.
+     This is the default anyway.
+     See #unBuffered for additional info."
+
+    <context: #return>
+%{
+    if (ISCONNECTED) {
+        ENTER_XLIB();
+        XSynchronize(myDpy, 0);
+        LEAVE_XLIB();
+    }
+%}
+    "
+     Display buffered
+    "
+!
+
+flush
+    "send all buffered drawing to the display.
+     This may be required to make certain, that all previous operations
+     are really sent to the display before continuing. For example,
+     after a cursor-change with a followup long computation.
+     (otherwise, the cursor change request may still be in the output buffer)
+     See also #sync, which even waits until the request has been processed."
+
+    <context: #return>
+%{
+    if (ISCONNECTED) {
+        ENTER_XLIB();
+        XFlush(myDpy);
+        LEAVE_XLIB();
+    }
+%}.
+
+    operationsUntilFlush := maxOperationsUntilFlush.
+!
+
+flushDpsContext:aDPSContext
+    <context: #return>
+%{
+#ifdef DPS
+    if (ISCONNECTED
+        && __isExternalAddress(aDPSContext)) {
+        ENTER_XLIB();
+        DPSFlushContext(__DPSContextVal(aDPSContext));
+        LEAVE_XLIB();
+
+        RETURN ( self );
+    }
+#endif
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+flushIfAppropriate
+    "flush the device, if necessary"
+
+    operationsUntilFlush notNil ifTrue:[
+	operationsUntilFlush <= 0 ifTrue:[
+	    self flush.
+	    ^ true.
+	] ifFalse:[
+	    operationsUntilFlush := operationsUntilFlush - 1.
+	].
+    ].
+    ^ false.
+!
+
+primSync
+    "send all buffered drawing to the display AND wait until the display
+     has finished drawing it.
+     This is almost never needed, except if you are about to read previously
+     drawn pixels back from the display screen, or you want to wait for a beep
+     to be finished. See also #flush."
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+
+        ENTER_XLIB();
+        XSync(myDpy, 0);
+        LEAVE_XLIB();
+
+    }
+%}.
+    operationsUntilFlush := maxOperationsUntilFlush.
+!
+
+refreshKeyboardMapping:eB
+    <context: #return>
+%{
+    XMappingEvent *ev;
+
+    if (ISCONNECTED && __isByteArrayLike(eB)) {
+        ev = (XMappingEvent *)(__ByteArrayInstPtr(eB)->ba_element);
+        ENTER_XLIB();
+        XRefreshKeyboardMapping(ev);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+roundTripTime
+    "answer the round trip time in milliSeconds.
+     May be used to detect slow X11 connections"
+
+    self sync.
+    ^ Timestamp millisecondsToRun:[ self primSync ].
+
+    "
+     Screen current roundTripTime
+    "
+!
+
+setInputFocusTo:aWindowId
+    "set the focus to the view as defined by aWindowId.
+     When released, return the focus to the root window"
+
+"/    self setInputFocusTo:aWindowId revertTo:#parent
+    self setInputFocusTo:aWindowId revertTo:#root
+!
+
+setInputFocusTo:aWindowId revertTo:revertSymbol
+    "set the focus to the view as defined by aWindowId.
+     Passing nil set the focus to no window and lets the display discard all
+     input until a new focus is set.
+     RevertSymbol specifies what should happen if the view becomes invisible;
+     passing one of #parent, #root or nil specifies that the focus should be
+     given to the parent view, the root view or no view."
+
+    <context: #return>
+%{
+    int arg;
+    Window focusWindow;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aWindowId)) {
+            focusWindow = __WindowVal(aWindowId);
+        } else if (aWindowId == nil) {
+            focusWindow = None;
+        } else
+            goto err;
+        if (revertSymbol == @symbol(parent))
+            arg = RevertToParent;
+        else if (revertSymbol == @symbol(root))
+            arg = RevertToPointerRoot;
+        else
+            arg = RevertToNone;
+
+
+        ENTER_XLIB();
+        XSetInputFocus(myDpy, focusWindow, arg, CurrentTime);
+        LEAVE_XLIB();
+
+        RETURN ( self );
+    }
+err:;
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+sync
+    "send all buffered drawing to the display AND wait until the display
+     has finished drawing it.
+     This is almost never needed, except if you are about to read previously
+     drawn pixels back from the display screen, or you want to wait for a beep
+     to be finished. See also #flush."
+
+    self primSync.
+    self dispatchPendingEvents.
+!
+
+unBuffered
+    "make all drawing be sent immediately to the display.
+     This makes all graphics synchronous and turns off any buffering
+     (i.e. each individual draw-request is sent immediately without
+      packing multiple requests into a larger message buffer).
+     Be prepared, that this slows down graphics considerably.
+     However, it allows display errors to be handled immediately and
+     may be useful if you get Xdisplay errors and want to find the request
+     which was responsible for it. See also #buffered."
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+
+        ENTER_XLIB();
+        XSynchronize(myDpy, 1);
+        LEAVE_XLIB();
+
+    }
+%}
+    "
+     Display unBuffered
+    "
+! !
+
+!XWorkstation methodsFor:'pointer stuff'!
+
+anyButtonStateMask
+    "return an integer for masking out any button from a
+     buttonStates value."
+
+    "/ should use ``Display buttonXMotionMask bitOr:....''
+
+    ^ 256 + 512 + 1024
+
+    "Modified: 23.3.1996 / 12:41:33 / cg"
+    "Created: 23.3.1996 / 12:46:35 / cg"
+!
+
+buttonStates
+    "return an integer representing the state of the pointer buttons;
+     a one-bit in positions 0.. represent a pressed button.
+     See the button1Mask/button2Mask/button3Mask,
+     shiftMask/controlMask and modifierMask methods for the meaning of the bits."
+
+    <context: #return>
+%{
+    Window w;
+    int screen = __intVal(__INST(screen));
+    Window rootRet, childRet;
+    int rootX, rootY, winX, winY;
+    unsigned int mask;
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        w = RootWindow(dpy, screen);
+        if (w) {
+
+            ENTER_XLIB();
+            XQueryPointer(dpy, w, &rootRet, &childRet,
+                                 &rootX, &rootY,
+                                 &winX, &winY,
+                                 &mask);
+            LEAVE_XLIB();
+
+            RETURN (__MKSMALLINT(mask));
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ nil
+
+    "
+     Display buttonStates
+    "
+
+    "is the control-key pressed ?
+
+     Display buttonStates bitTest:(Display controlMask)
+    "
+
+    "is the alt/meta-key pressed ?
+
+     Display buttonStates bitTest:(Display altModifierMask)
+     Display buttonStates bitTest:(Display metaModifierMask)
+    "
+!
+
+leftButtonStateMask
+    "return an integer for masking out the left button from a
+     buttonStates value"
+
+    "/ should use ``Display button1MotionMask''
+
+    ^ 256
+
+    "Modified: 23.3.1996 / 12:41:33 / cg"
+!
+
+middleButtonStateMask
+    "return an integer for masking out the middle button from a
+     buttonStates value"
+
+    "/ should use ``Display button2MotionMask''
+
+    ^ 512
+
+    "Modified: 23.3.1996 / 12:41:43 / cg"
+!
+
+pointerPosition
+    "return the current pointer position in (virtual) root-window coordinates"
+
+    <context: #return>
+
+    |xpos ypos rootWindowId|
+
+    rootWindowId := self rootWindowId.
+
+%{
+    int screen = __intVal(__INST(screen));
+    Window rootRet, childRet;
+    int rootX, rootY, winX, winY;
+    unsigned int mask;
+
+    if (ISCONNECTED && rootWindowId != nil) {
+        Display *dpy = myDpy;
+        Window w = (Window)__externalAddressVal(rootWindowId);
+
+        ENTER_XLIB();
+        XQueryPointer(dpy, w, &rootRet, &childRet,
+                              &rootX, &rootY,
+                              &winX, &winY,
+                              &mask);
+        LEAVE_XLIB();
+        xpos = __MKSMALLINT(rootX);
+        ypos = __MKSMALLINT(rootY);
+
+    }
+%}.
+    xpos isNil ifTrue:[
+        self primitiveFailedOrClosedConnection.
+        ^ nil
+    ].
+    ^ xpos @ ypos
+!
+
+rightButtonStateMask
+    "return an integer for masking out the right button from a
+     buttonStates value"
+
+    "/ should use ``Display button3MotionMask''
+
+    ^ 1024
+
+    "Modified: 23.3.1996 / 12:41:52 / cg"
+!
+
+rootPositionOfLastEvent
+    "return the position in root-window coordinates
+     of the last button, key or pointer event"
+
+    ^ eventRootX @ eventRootY
+!
+
+setPointerPosition:newPosition in:aWindowId
+    "change the pointer position to a new position relative to the
+     given windows origin (which may be the rootWindow).
+     Be careful with this - its usually not very ergonomically
+     to change the mousePointer position.
+     This interface is provided for special applications (presentation
+     playback) and should not be used in normal applications."
+
+    <context: #return>
+
+    |xpos ypos|
+
+    xpos := newPosition x.
+    ypos := newPosition y.
+
+%{
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __bothSmallInteger(xpos, ypos)) {
+        Display *dpy = myDpy;
+        Window w = __WindowVal(aWindowId);
+
+        ENTER_XLIB();
+        XWarpPointer(dpy,
+                     None,  /* src window */
+                     w,  /* dst window */
+                     0,  /* src_x */
+                     0,  /* src_y */
+                     0,  /* src_w */
+                     0,  /* src_h */
+                     __intVal(xpos),  /* dst_x */
+                     __intVal(ypos)   /* dst_y */
+                    );
+        LEAVE_XLIB();
+    }
+%}.
+    ^ self
+
+    "
+     Display setPointerPosition:1000@1000
+    "
+! !
+
+!XWorkstation methodsFor:'private'!
+
+addSelectionHandler:someone
+    "register someone to be notified when the selection changes"
+
+    selectionHandlers isNil ifTrue:[
+        selectionHandlers := IdentitySet new.
+    ].
+    selectionHandlers add:someone
+!
+
+findSelectionFetcher:aDrawableId
+    "find the SelectionFetcher that receives selection events for aDrawableId.
+     Answer nil, if there is none"
+
+    selectionFetchers isNil ifTrue:[
+        ^ nil.
+    ].
+
+    ^ selectionFetchers at:aDrawableId ifAbsent:[].
+!
+
+registerSelectionFetcher:aSelectionFetcher
+    "register a SelectionFetcher that receives selection events for aDrawableId"
+
+    selectionFetchers isNil ifTrue:[
+        selectionFetchers := Dictionary new.
+    ].
+
+    selectionFetchers at:aSelectionFetcher drawableID put:aSelectionFetcher.
+!
+
+removeSelectionHandler:someone
+    "no longer tell someone about selection changes"
+
+    selectionHandlers notNil ifTrue:[
+        selectionHandlers remove:someone ifAbsent:nil.
+        selectionHandlers := selectionHandlers asNilIfEmpty
+    ].
+!
+
+unregisterSelectionFetcher:aSelectionFetcher
+    "unregister a SelectionFetcher that received selection events for aDrawableId"
+
+    selectionFetchers removeKey:aSelectionFetcher drawableID.
+! !
+
+!XWorkstation methodsFor:'properties'!
+
+deleteProperty:propertyID for:aWindowID
+    "delete a property in the XServer"
+
+    <context: #return>
+
+%{
+    if (ISCONNECTED && __isAtomID(propertyID)) {
+        Display *dpy = myDpy;
+        Atom prop;
+        Window window;
+
+        prop = __AtomVal(propertyID);
+
+        if (__isExternalAddress(aWindowID)) {
+            window = __WindowVal(aWindowID);
+        } else if (aWindowID == nil) {
+            window = DefaultRootWindow(dpy);
+        } else if (__isInteger(aWindowID)) {
+            window = (Window)__unsignedLongIntVal(aWindowID);
+        } else {
+            goto fail;
+        }
+
+        ENTER_XLIB();
+        XDeleteProperty(dpy, window, prop);
+        LEAVE_XLIB();
+        RETURN(true);
+    }
+fail:;
+%}.
+    self primitiveFailedOrClosedConnection.
+!
+
+getProperty:propertySymbolOrAtomID from:aWindowOrWindowIDOrNil delete:doDelete
+    "get a property as an association propertyType->propertyValue"
+
+    <context: #return>
+
+    |val typeID propertyID windowID|
+
+    propertySymbolOrAtomID isString ifTrue:[
+        propertyID := self atomIDOf:propertySymbolOrAtomID create:false.
+        propertyID isNil ifTrue:[^ nil].
+    ] ifFalse:[
+        propertyID := propertySymbolOrAtomID.
+    ].
+    aWindowOrWindowIDOrNil isView ifTrue:[
+        windowID := aWindowOrWindowIDOrNil id.
+    ] ifFalse:[
+        windowID := aWindowOrWindowIDOrNil.
+    ].
+
+%{
+    Window window;
+    Atom property;
+    char *cp, *cp2;
+    Atom actual_type;
+    int actual_format;
+    unsigned long nitems, bytes_after, nread;
+    unsigned char *data;
+    int ok = 1;
+#   define PROP_SIZE    2048
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        if (__isAtomID(propertyID)) {
+            property = __AtomVal(propertyID);
+
+            if (__isExternalAddress(windowID)) {
+                window = __WindowVal(windowID);
+            } else if (windowID == nil) {
+                window = DefaultRootWindow(dpy);
+            } else
+                goto fail;
+
+            nread = 0;
+            cp = 0;
+#ifdef PROPERTY_DEBUG
+            console_fprintf(stderr, "getProperty %x\n", property);
+#endif
+
+            do {
+                int retVal;
+
+                ENTER_XLIB();
+                retVal = XGetWindowProperty(dpy, window, property, nread/4, PROP_SIZE,
+                                            doDelete == true,
+                                            AnyPropertyType, &actual_type, &actual_format,
+                                            &nitems, &bytes_after, (unsigned char **)&data);
+                LEAVE_XLIB();
+                if (retVal != Success) {
+#ifdef PROPERTY_DEBUG
+                    console_fprintf(stderr, "- no success\n");
+#endif
+                    ok = 0;
+                    break;
+                }
+#ifdef PROPERTY_DEBUG
+                console_fprintf(stderr, "- type:%x\n", actual_type);
+#endif
+                nitems *= (actual_format / 8);
+                typeID = __MKATOMOBJ(actual_type);
+                if (! cp) {
+                    cp = cp2 = (char *)malloc(nitems+bytes_after);
+                } else {
+                    cp2 = cp + nread;
+                }
+                if (! cp) {
+                    XFree(data);
+                    goto fail;
+                }
+
+                nread += nitems;
+                bcopy(data, cp2, nitems);
+                XFree(data);
+#ifdef PROPERTY_DEBUG
+                console_fprintf(stderr, "- <nitems:%d bytes_after:%d>\n", nitems, bytes_after);
+#endif
+            } while (bytes_after > 0);
+
+            if (ok) {
+                switch (actual_format) {
+                case 32:
+                    val = __stArrayFromCUIntArray((unsigned int*)cp, nread/4);
+                    break;
+                case 16:
+                    val = __stArrayFromCUShortArray((unsigned short*)cp, nread/2);
+                    break;
+                case 8:
+                default:
+                    if (actual_type == XA_STRING) {
+                        val = __MKSTRING_L(cp, nread);
+                    } else {
+                        val = __MKBYTEARRAY(cp, nread);
+                    }
+                    break;
+                }
+            }
+            if (cp)
+                free(cp);
+        }
+    }
+fail: ;
+%}.
+    (typeID isNil or:[typeID == 0]) ifTrue:[
+        "typeID == 0 (None): The property does not exist in the specified window"
+        ^ nil
+    ].
+    ^ typeID->val
+
+    "
+     Display
+        getProperty:#'_NET_WM_ICON_GEOMETRY'
+        from:nil
+        delete:false
+    "
+!
+
+propertiesOf:aWindowOrWindowIDOrNil
+    "return a collection of all properties' atomIDs of a window.
+     Returns the rootWindows props for a nil window argument."
+
+    <context: #return>
+
+    |windowID atoms|
+
+    aWindowOrWindowIDOrNil isView ifTrue:[
+        windowID := aWindowOrWindowIDOrNil id.
+    ] ifFalse:[
+        windowID := aWindowOrWindowIDOrNil.
+    ].
+
+%{
+    Window window;
+    Atom *atomListPtr;
+    int i;
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+        int numProps = 0;
+
+        if (__isExternalAddress(windowID)) {
+            window = __WindowVal(windowID);
+        } else if (windowID == nil) {
+            window = DefaultRootWindow(dpy);
+        } else if (__isInteger(windowID)) {
+            window = (Window)__unsignedLongIntVal(windowID);
+        } else {
+            goto fail;
+        }
+
+        ENTER_XLIB();
+        atomListPtr = XListProperties(dpy, window, &numProps);
+        LEAVE_XLIB();
+
+        if (atomListPtr == NULL) {
+            RETURN (nil);
+        }
+
+        atoms = __ARRAY_NEW_INT(numProps);
+
+        if (atoms == nil) {
+            goto fail;
+        }
+
+        for (i=0; i<numProps; i++) {
+            OBJ atm;
+
+            atm = __MKATOMOBJ(atomListPtr[i]);
+            __ArrayInstPtr(atoms)->a_element[i] = atm; __STORE(atoms, atm);
+        }
+        XFree(atomListPtr);
+        RETURN (atoms);
+    }
+fail: ;
+%}.
+    ^ self primitiveFailed
+
+    "
+     Display propertiesOf:nil
+     Display propertiesOf:Transcript view id
+    "
+    "
+     (Display propertiesOf:nil) do:[:atm |
+        |v prop|
+
+        Transcript show:((Display atomName:atm) printStringLeftPaddedTo:5).
+        Transcript show:': '.
+        prop := Display getProperty:atm from:nil delete:false.
+        Transcript showCR:prop value.
+     ]
+    "
+!
+
+setIcon:anIcon for:aWindowID
+    |iconAtom typeAtom buffer iWidth iHeight|
+
+    iconAtom := self atomIDOf:#'_NET_WM_ICON' create:false.
+    iconAtom isNil ifTrue:[
+        "/Hmm, no such property, not running under EWMH compliant WM?
+        ^ self
+    ].
+    typeAtom := self atomIDOf:#'CARDINAL' create:false.
+    typeAtom isNil ifTrue:[
+        "/Hmm, no such property, not running under EWMH compliant WM?
+        ^ self
+    ].
+    iWidth  := anIcon width.
+    iHeight := anIcon height.
+    buffer := IntegerArray new:(iWidth*iHeight+2).
+    buffer at:1 put:iWidth.
+    buffer at:2 put:iHeight.
+
+    self setProperty:iconAtom type:typeAtom value:buffer for:aWindowID
+
+    "
+        Display setIcon:0 for:0
+    "
+!
+
+setProperty:propertyID type:typeID value:anObject for:aWindowID
+    "set a property in the XServer"
+
+    <context: #return>
+
+    |retval|
+
+    retval := false.
+
+%{  /* UNLIMITEDSTACK */
+    if (ISCONNECTED && __isAtomID(propertyID) && __isAtomID(typeID)) {
+        Display *dpy = myDpy;
+        Atom prop, type;
+        Window window;
+
+        prop = __AtomVal(propertyID);
+        type = __AtomVal(typeID);
+
+        if (__isExternalAddress(aWindowID)) {
+            window = __WindowVal(aWindowID);
+        } else if (aWindowID == nil) {
+            window = DefaultRootWindow(dpy);
+        } else if (__isInteger(aWindowID)) {
+            window = (Window)__unsignedLongIntVal(aWindowID);
+        } else {
+            RETURN(false);
+        }
+
+        retval = true;
+
+        ENTER_XLIB();
+        if (__isInteger(anObject)) {
+            unsigned INT value = __longIntVal(anObject);
+            XChangeProperty(dpy, window, prop, type, 32,
+                            PropModeReplace,
+                            (unsigned char *)&value, 1);
+        } else if (__isByteArrayLike(anObject)) {
+            XChangeProperty(dpy, window, prop, type, 8,
+                            PropModeReplace,
+                            __byteArrayVal(anObject),
+                            __byteArraySize(anObject));
+        } else if (__isWords(anObject)) {
+            /* wordArray-like (16bit-string) object */
+            XChangeProperty(dpy, window, prop, type, 16,
+                            PropModeReplace,
+                            __stringVal(anObject),
+                            __wordArraySize(anObject));
+        } else if (__isIntegerArray(anObject)) {
+            /* array of atoms */
+            XChangeProperty(dpy, window, prop, type, 32,
+                            PropModeReplace,
+                            (char *)__integerArrayVal(anObject),
+                            __integerArraySize(anObject));
+        } else if (__isStringLike(anObject)) {
+            XChangeProperty(dpy, window, prop, type, 8,
+                            PropModeReplace,
+                            __stringVal(anObject),
+                            __stringSize(anObject));
+        } else {
+            retval = false;
+        }
+        LEAVE_XLIB();
+
+        DPRINTF(("changeProp win=%"_lx_" prop=%"_lx_" type=%"_lx_"\n", (INT)window, (INT)prop, (INT)type));
+    }
+%}.
+    ^ retval
+! !
+
+!XWorkstation methodsFor:'queries'!
+
+defaultExtentForTopViews
+    "redefined, to define the default extent for the default monitor"
+    |extent|
+
+    "the standard monitor is the first entry in monitorBounds"
+    extent := self monitorBounds first extent.
+
+    self isPDA ifTrue:[
+        ^ extent - (16 @ 20)
+    ].
+    ^ extent * 2 // 3
+!
+
+isOpen
+    "answer true, if device can be used"
+
+    ^ displayId notNil and:[hasConnectionBroken not].
+!
+
+isXineramaActive
+%{  /* NOCONTEXT */
+
+#ifdef XINERAMA
+    if (ISCONNECTED) {
+        Display *dpy;
+        dpy = myDpy;
+
+        if (XineramaIsActive(dpy)) {
+            RETURN ( true );
+        }
+    }
+#endif
+%}.
+    ^ false
+
+    "
+     Display isXineramaActive
+    "
+!
+
+supportedClipboards
+    "answer a collection of symbols with the supported clipboards.
+     X11 additionaly supports a buffer containing the currently selected text
+     (in xterm) - the PRIMARY selection"
+
+    ^ #(clipboard selection)
+!
+
+supportsUTF8WindowLabels
+    "answer true, if window labels are to be utf-8 encoded"
+
+    ^ false
+!
+
+supportsVariableHeightFonts
+    "are fonts with variable height supported?"
+
+    ^ false
+! !
+
+!XWorkstation methodsFor:'resources'!
+
+atomIDOf:aStringOrSymbol
+    "return an X11 atoms ID.
+     This is highly X specific and only for local use (with selections).
+     The default is to create the atom, if it does not exist, in order to
+     speed up future lookups"
+
+    ^ self atomIDOf:aStringOrSymbol create:true
+
+    "
+     Display atomIDOf:#'FACE_NAME'
+     Display atomIDOf:#'FULL_NAME'
+     Display atomIDOf:#DndProtocol
+     Display atomIDOf:#DndSelection
+    "
+
+    "Modified: 4.4.1997 / 13:38:48 / cg"
+!
+
+atomIDOf:aStringOrSymbol create:create
+    "return an Atoms ID given its name.
+     If it already exists, return its ID.
+     If not and the create argument is true, it is created.
+     Otherwise, nil is returned.
+     This is highly X specific and only for local use (with selections)."
+
+    |atomSymbol atom|
+
+    atomSymbol := aStringOrSymbol asSymbol.
+    (atoms notNil and:[(atom := atoms at:atomSymbol ifAbsent:nil) notNil]) ifTrue:[
+        ^ atom.
+    ].
+
+    atom := self primAtomIDOf:atomSymbol create:create.
+    atom notNil ifTrue:[
+        atoms isNil ifTrue:[
+            atoms := IdentityDictionary new.
+        ].
+        atoms at:atomSymbol put:atom.
+    ].
+
+    ^ atom
+
+    "
+     Display atomIDOf:#'VT_SELECTION' create:false
+     Display atomIDOf:#CLIPBOARD create:false
+     Display atomIDOf:'STRING' create:false
+     Display atomIDOf:'PRIMARY' create:false
+     Display atomIDOf:'blabla' create:false
+    "
+!
+
+atomName:anAtomID
+    "given an AtomID, return its name.
+     This is highly X specific and only for local use (with selections)."
+
+    <context: #return>
+
+%{
+    OBJ str;
+    char *name;
+
+    if (ISCONNECTED && __isAtomID(anAtomID)) {
+        ENTER_XLIB();
+        name = XGetAtomName(myDpy, __AtomVal(anAtomID));
+        LEAVE_XLIB();
+        if (name == 0) {
+            RETURN (nil);
+        }
+        str = __MKSTRING(name);
+        XFree(name);
+        RETURN ( str );
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ nil
+
+    "
+     Display atomName:1    'PRIMARY'
+     Display atomName:130  '_DEC_DEVICE_FONTNAMES'
+     Display atomName:132  'FONTNAME_REGISTRY'
+     Display atomName:135 'FOUNDRY'
+     Display atomName:150  'CHARSET_REGISTRY'
+     Display atomName:151  'ISO8859'
+     Display atomName:152 'CHARSET_ENCODING'
+     Display atomName:154
+    "
+!
+
+getResource:name class:cls
+    "access the displays resource database for a default value
+     of name in a resource class.
+     This is highly X specific and  currently not used.
+
+     Notice:
+        we do not plan to use X's resources for ST/X's defaults,
+        styles or resources. This would make porting of applications
+        to different platforms much more difficult (Windows has no resource
+        database). If you stay within ST/X's resource files, these can be
+        easily transported to other platforms.
+
+     This method is provided for special applications which want to access
+     existing X resources and are not planned to be ever ported to other
+     platforms."
+
+%{
+    char *rslt;
+
+    if (ISCONNECTED
+     && __isStringLike(name)
+     && __isStringLike(cls)) {
+
+        rslt = XGetDefault(myDpy, (char *) __stringVal(cls),
+                                  (char *) __stringVal(name));
+
+        RETURN (rslt ? __MKSTRING(rslt) : nil );
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ nil.
+
+    "if your ~/.Xdefaults contains an entry such as:
+        OpenWindows.Beep:       notices
+     the following returns 'notices'.
+
+         Display getResource:'Beep' class:'OpenWindows'
+
+     if your ~/.Xdefaults contains an entry such as:
+        *.beNiceToColormap:       false
+     the following return 'false'.
+
+         Display getResource:'beNiceToColormap' class:'any'
+         Display getResource:'beNiceToColormap' class:''
+    "
+!
+
+primAtomIDOf:aStringOrSymbol create:create
+    "return an Atoms ID; if create is true, create it if not already present.
+     This is highly X specific and only for local use (with selections)."
+
+    <context: #return>
+
+%{
+    Atom prop;
+
+    if (ISCONNECTED
+     && __isStringLike(aStringOrSymbol)) {
+
+        ENTER_XLIB();
+        prop = XInternAtom(myDpy, __stringVal(aStringOrSymbol),
+                                  (create == true) ? False : True);
+        LEAVE_XLIB();
+        if (prop == None) {
+            RETURN (nil);
+        }
+        RETURN ( __MKATOMOBJ(prop) );
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ nil
+
+    "
+     Display primAtomIDOf:'VT_SELECTION' create:false
+     Display primAtomIDOf:'CUT_BUFFER0' create:false
+     Display primAtomIDOf:'STRING' create:false
+     Display primAtomIDOf:'PRIMARY' create:false
+    "
+! !
+
+!XWorkstation methodsFor:'retrieving pixels'!
+
+getBitsFromId:aDrawableId x:srcx y:srcy width:w height:h into:imageBits
+    "get bits from a drawable into the imageBits. The storage for the bits
+     must be big enough for the data to fit. If ok, returns an array with some
+     info and the bits in imageBits. The info contains the depth, bitOrder and
+     number of bytes per scanline. The number of bytes per scanline is not known
+     in advance, since the X-server is free to return whatever it thinks is a good padding."
+
+    |rawInfo info|
+
+    ((w <= 0) or:[h <= 0]) ifTrue:[
+        self primitiveFailed.
+        ^ nil
+    ].
+
+    rawInfo := Array new:8.
+                  "1 -> bit order"
+                  "2 -> depth"
+                  "3 -> bytes_per_line"
+                  "4 -> byte_order"
+                  "5 -> format"
+                  "6 -> bitmap_unit"
+                  "7 -> bitmap_pad"
+                  "8 -> bits_per_pixel"
+
+    "/ had to extract the getPixel call into a separate method, to specify
+    "/ unlimitedStack (some implementations use alloca and require huge amounts
+    "/ of temporary stack space
+
+    (self primGetBitsFrom:aDrawableId x:srcx y:srcy width:w height:h into:imageBits infoInto:rawInfo) ifTrue:[
+        info := IdentityDictionary new.
+        info at:#bitOrder put:(rawInfo at:1).
+        info at:#depth put:(rawInfo at:2).
+        info at:#bytesPerLine put:(rawInfo at:3).
+        info at:#byteOrder put:(rawInfo at:4).
+        info at:#format put:(rawInfo at:5).
+        info at:#bitmapUnit put:(rawInfo at:6).
+        info at:#bitmapPad put:(rawInfo at:7).
+        info at:#bitsPerPixel put:(rawInfo at:8).
+        ^ info
+    ].
+    "
+     some error occured - either args are not smallintegers, imageBits is not a ByteArray
+     or is too small to hold the bits
+    "
+    self primitiveFailedOrClosedConnection.
+    ^ nil
+!
+
+getPixelX:x y:y from:aDrawableId with:dummyGCId
+    "return the pixel value at x/y; coordinates start at 0/0 for the upper left.
+     Nil is returned for invalid coordinates or if any other problem arises."
+
+    <context: #return>
+
+%{  /* UNLIMITEDSTACK */
+
+    Window win;
+    XImage *img;
+    int ret;
+    int xpos, ypos;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aDrawableId) && __bothSmallInteger(x, y)) {
+        win = __WindowVal(aDrawableId);
+        xpos = __intVal(x);
+        ypos = __intVal(y);
+        if ((xpos < 0) || (ypos < 0)) {
+            RETURN ( __MKSMALLINT(0) );
+        }
+        ENTER_XLIB();
+        img = XGetImage(myDpy, win, xpos, ypos, 1, 1, (unsigned)~0, ZPixmap);
+        LEAVE_XLIB();
+        if (img != 0) {
+            ret = XGetPixel(img, 0, 0);
+            XDestroyImage(img);
+            RETURN (  __MKSMALLINT(ret) );
+        }
+    }
+%}.
+    ^ nil
+!
+
+primGetBitsFrom:aDrawableId x:srcx y:srcy width:w height:h into:imageBits infoInto:info
+    "since XGetImage may allocate huge amount of stack space
+     (some implementations use alloca), this must run with unlimited stack."
+
+    <context: #return>
+
+%{  /* UNLIMITEDSTACK */
+
+    Window win;
+    XImage *image = (XImage *)0;
+    int pad, bytes_per_line, numBytes;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aDrawableId)
+     && __bothSmallInteger(srcx, srcy)
+     && __bothSmallInteger(w, h)
+     && __isArray(info)
+     && __isByteArray(imageBits)) {
+        Display *dpy = myDpy;
+
+        win = __WindowVal(aDrawableId);
+        ENTER_XLIB();
+        image = XGetImage(dpy, win, __intVal(srcx), __intVal(srcy),
+                                    __intVal(w), __intVal(h),
+                                    (unsigned)AllPlanes, ZPixmap);
+        LEAVE_XLIB();
+
+        if (! image) {
+            RETURN ( false );
+        }
+
+        pad = image->bitmap_pad;
+#ifdef SUPERDEBUG
+        console_printf("pad:%d depth:%d\n", image->bitmap_pad, image->depth);
+#endif
+        switch (image->depth) {
+            case 1:
+            case 2:
+            case 4:
+            case 8:
+            case 16:
+            case 24:
+            case 32:
+                numBytes = image->bytes_per_line * image->height;
+                break;
+
+            default:
+                /* unsupported depth ? */
+                console_fprintf(stderr, "possibly unsupported depth:%d in primGetBits\n", image->depth);
+                numBytes = image->bytes_per_line * image->height;
+                break;
+        }
+
+#ifdef SUPERDEBUG
+        console_printf("bytes need:%d bytes given:%d\n", numBytes, __byteArraySize(imageBits));
+#endif
+
+        if (numBytes > __byteArraySize(imageBits)) {
+            /* imageBits too small */
+            console_fprintf(stderr, "Workstation [warning]: byteArray too small in primGetBits\n");
+            console_fprintf(stderr, "  bytes need:%d given:%d\n", numBytes, (int)__byteArraySize(imageBits));
+            console_fprintf(stderr, "  pad:%d depth:%d imgBytesPerLine:%d\n",
+                                image->bitmap_pad, image->depth, image->bytes_per_line);
+            goto fail;
+        }
+        if (image->bitmap_bit_order == MSBFirst)
+            __ArrayInstPtr(info)->a_element[0] = @symbol(msbFirst);
+        else
+            __ArrayInstPtr(info)->a_element[0] = @symbol(lsbFirst);
+        __ArrayInstPtr(info)->a_element[1] = __MKSMALLINT(image->depth);
+        __ArrayInstPtr(info)->a_element[2] = __MKSMALLINT(image->bytes_per_line);
+        if (image->byte_order == MSBFirst)
+            __ArrayInstPtr(info)->a_element[3] = @symbol(msbFirst);
+        else
+            __ArrayInstPtr(info)->a_element[3] = @symbol(lsbFirst);
+        if (image->format == XYBitmap)
+            __ArrayInstPtr(info)->a_element[4] = @symbol(XYBitmap);
+        else if (image->format == XYPixmap)
+            __ArrayInstPtr(info)->a_element[4] = @symbol(XYPixmap);
+        else if (image->format == ZPixmap)
+            __ArrayInstPtr(info)->a_element[4] = @symbol(ZPixmap);
+
+        __ArrayInstPtr(info)->a_element[5] = __MKSMALLINT(image->bitmap_unit);
+        __ArrayInstPtr(info)->a_element[6] = __MKSMALLINT(image->bitmap_pad);
+        __ArrayInstPtr(info)->a_element[7] = __MKSMALLINT(image->bits_per_pixel);
+        bcopy(image->data, __ByteArrayInstPtr(imageBits)->ba_element, numBytes);
+        XDestroyImage(image);
+        RETURN ( true );
+    }
+fail:
+    if (image) {
+        XDestroyImage(image);
+    }
+%}.
+    ^ false
+! !
+
+!XWorkstation methodsFor:'selection fetching'!
+
+getClipboardObjectFor:drawableId
+    "get the object selection.
+     Returns nil, if no selection is available.
+
+     Smalltalk puts ST_OBJECT only into the CLIPBOARD"
+
+    |selectionOwnerWindowId selection|
+
+    selectionOwnerWindowId := self getSelectionOwnerOf:clipboardAtom.
+    selectionOwnerWindowId isNil ifTrue:[
+        "no selection. There is the possibilty that one of our (modal)
+         views has been closed. Get the selection from the copyBuffer"
+        ^ copyBuffer.
+    ].
+    selectionOwnerWindowId = selectionOwner ifTrue:[
+        "I still hold the selection, so return my locally buffered data"
+        ^ copyBuffer
+    ].
+
+    drawableId notNil ifTrue:[
+        "sorry, cannot fetch a selection, if there is no drawableId.
+         Should I borrow a drawableId from another window?"
+
+        selection := SelectionFetcher
+            requestSelection:clipboardAtom
+            type:(self atomIDOf:#'ST_OBJECT')
+            onDevice:self for:drawableId.
+
+        "/ should not happen
+false ifTrue:[
+        "/ cg: disabled the code below: I don't want any string here (when asking for an object)
+        selection isEmptyOrNil ifTrue:[
+            selection := SelectionFetcher
+                requestSelection:clipboardAtom
+                type:(self atomIDOf:#'UTF8_STRING')
+                onDevice:self for:drawableId.
+
+            selection isNil ifTrue:[
+                selection := SelectionFetcher
+                    requestSelection:clipboardAtom
+                    type:(self atomIDOf:#STRING)
+                    onDevice:self for:drawableId.
+            ].
+        ].
+].
+    ].
+    selection isEmptyOrNil ifTrue:[ ^ copyBuffer ].
+
+    ^ selection.
+
+    "
+       Display getClipboardObjectFor:Transcript id
+    "
+!
+
+getClipboardText:selectionBufferSymbol for:drawableId
+    "get the text selection.
+     Returns nil, if no selection is available"
+
+    |selectionId selectionOwnerWindowId selection|
+
+    selectionBufferSymbol == #selection ifTrue:[
+        selectionId := primaryAtom.
+    ] ifFalse:[
+        selectionId := clipboardAtom.
+    ].
+
+    selectionOwnerWindowId := self getSelectionOwnerOf:selectionId.
+    selectionOwnerWindowId isNil ifTrue:[
+        "no selection. There is the possibilty that one of our (modal)
+         views has been closed. Get the selection from the copyBuffer"
+        ^ self copyBufferAsString.
+    ].
+
+    selectionOwnerWindowId = selectionOwner ifTrue:[
+        "I still hold the selection, so return my locally buffered data"
+        "JV@2012-04-02: Added support for PRIMARY/SELECTION buffers."
+        ^ selectionId == primaryAtom ifTrue:[
+            self primaryBufferAsString
+        ] ifFalse:[
+            self copyBufferAsString.
+        ]
+    ].
+
+    drawableId notNil ifTrue:[
+        "sorry, cannot fetch a selection, if there is no drawableId.
+         Should I borrow a drawableId from another window?"
+
+        selection := SelectionFetcher
+            requestSelection:selectionId
+            type:(self atomIDOf:#'UTF8_STRING')
+            onDevice:self for:drawableId.
+
+        selection isNil ifTrue:[
+            selection := SelectionFetcher
+                requestSelection:selectionId
+                type:(self atomIDOf:#STRING)
+                onDevice:self for:drawableId.
+        ].
+    ].
+
+    ^ selection
+
+     "
+       Display getTextSelection:#clipboard for:Transcript id
+       Display getTextSelection:#selection for:Transcript id
+     "
+
+    "Modified: / 02-04-2012 / 10:34:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!XWorkstation methodsFor:'selection sending'!
+
+selectionBuffer:bufferGetSelector as:aTargetAtomID
+    "convert the current selection to the format defined by aTargetAtom.
+     Answer an association with the type of converted selection (an atomID)
+     and the converted selection"
+
+    |buffer bufferAsString|
+
+    buffer := self perform:bufferGetSelector.
+
+    (aTargetAtomID == (self atomIDOf:#'ST_OBJECT')) ifTrue:[
+        "/ 'st-object' printCR.
+        "send the selection in binaryStore format"
+        "require libboss to be loaded"
+        (Smalltalk isClassLibraryLoaded:'libstx_libboss') ifFalse:[
+            'XWorkstation: cannot use binary store for copy buffer (libboss missing)' errorPrintCR.
+            ^ nil -> nil.
+        ].
+
+        [
+            ^ aTargetAtomID -> (buffer binaryStoreBytes).
+        ] on:Error do:[:ex|
+            'XWorkstation: error on binary store of copy buffer: ' infoPrint.
+            ex description infoPrintCR.
+            ^ nil -> nil.
+        ].
+    ].
+
+    bufferAsString := self class bufferAsString:buffer.
+
+    (aTargetAtomID == (self atomIDOf:#STRING)
+     or:[aTargetAtomID == (self atomIDOf:#'text/plain')]
+    ) ifTrue:[
+        "/ 'string' printCR.
+        "the other view wants the selection as string"
+        ^ aTargetAtomID -> (bufferAsString asSingleByteStringReplaceInvalidWith:$#).
+    ].
+
+    (aTargetAtomID == (self atomIDOf:#UTF8_STRING)
+     or:[aTargetAtomID == (self atomIDOf:#'text/plain;codeset=utf-8')]
+    ) ifTrue:[
+        "/ 'utf string' printCR.
+        "the other view wants the selection as utf8 string"
+        ^ aTargetAtomID -> (bufferAsString utf8Encoded).
+    ].
+
+    aTargetAtomID == (self atomIDOf:#LENGTH) ifTrue:[
+        "the other one wants to know the size of our selection.
+         LENGTH is deprecated, since we do not know how the selection is
+         going to be converted. The client must not rely on the length returned"
+
+        ^ (self atomIDOf:#INTEGER) -> (bufferAsString size).
+    ].
+
+    "we do not support the requestet target type"
+    ^ nil -> nil.
+
+    "Modified: / 23-08-2006 / 15:56:08 / cg"
+!
+
+setClipboardObject:anObject owner:aWindowId
+    "set the object selection, and make aWindowId be the owner.
+     This can be used by other Smalltalk(X) applications only.
+     We set only the CLIPBOARD selection"
+
+    clipboardSelectionTime := lastEventTime.
+    self setSelectionOwner:aWindowId of:clipboardAtom time:clipboardSelectionTime
+!
+
+setClipboardText:aString owner:aWindowId
+    "set the text selection, and make aWindowId be the owner.
+     This can be used by any other X application.
+
+     We set both the PRIMARY and CLIPBOARD, so that you can paste
+     into xterm."
+
+    clipboardSelectionTime := primarySelectionTime := lastEventTime.
+
+    self setSelectionOwner:aWindowId of:clipboardAtom time:clipboardSelectionTime.
+    self setSelectionOwner:aWindowId of:primaryAtom time:primarySelectionTime.
+
+    "Modified: / 17.6.1998 / 19:48:54 / cg"
+!
+
+setPrimaryText:aString owner:aWindowId
+    "set the PRIMARY selection, and make aWindowId be the owner.
+     This can be used by any other X application when middle-click
+     pasting. X Window specific."
+
+    primarySelectionTime := lastEventTime.
+
+    self setSelectionOwner:aWindowId of:primaryAtom time:primarySelectionTime.
+
+    "Created: / 27-03-2012 / 14:16:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+supportedTargetAtoms
+    "answer an integer array containing the list of supported targets
+     i.e. supported clipboard formats"
+
+    "Note: some sender code assumes that ST_OBJECT is first"
+    ^ #(ST_OBJECT STRING UTF8_STRING TIMESTAMP TARGETS LENGTH
+      #'text/plain' #'text/plain;codeset=utf-8'
+    ) collect:[:eachTargetSymbol|
+            self atomIDOf:eachTargetSymbol
+        ] as:IntegerArray.
+! !
+
+!XWorkstation methodsFor:'selections-basic'!
+
+getSelectionOwnerOf:selectionAtomSymbolOrID
+    "get the owner of a selection, aDrawableID.
+     Answer nil, if there is no owner"
+
+    <context:#return>
+
+    |selectionAtomID|
+
+    selectionAtomSymbolOrID isString ifTrue:[
+        selectionAtomID := self atomIDOf:selectionAtomSymbolOrID create:false.
+    ] ifFalse:[
+        selectionAtomID := selectionAtomSymbolOrID.
+    ].
+
+%{
+    Window window;
+
+    if (__isAtomID(selectionAtomID) && ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        ENTER_XLIB();
+        window = XGetSelectionOwner(dpy, __AtomVal(selectionAtomID));
+        LEAVE_XLIB();
+        RETURN ((window == None) ? nil : __MKEXTERNALADDRESS(window));
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ nil
+!
+
+requestSelection:selectionID type:typeID for:aWindowId intoProperty:propertyID
+    "ask the server to send us the selection - the view with id aWindowID
+     will later receive a SelectionNotify event for it (once the Xserver replies
+     with the selections value)."
+
+    <context:#return>
+
+    |anIntegerTimestamp|
+
+    anIntegerTimestamp := lastEventTime.
+
+%{
+
+    if (ISCONNECTED
+     && __isAtomID(typeID)
+     && __isAtomID(propertyID)
+     && __isAtomID(selectionID)) {
+        Display *dpy = myDpy;
+        Window w;
+        Time time;
+
+        if (__isExternalAddress(aWindowId)) {
+            w = __WindowVal(aWindowId);
+        } else if (aWindowId == nil) {
+            w = (Window)0;
+        } else
+            goto err;
+
+        if (anIntegerTimestamp == nil) {
+            /*
+             * the ICCCM convention says: you should set the time to the time when
+             * the selection was requested and not to CurrentTime
+             */
+            time = CurrentTime;
+        } else if (__isInteger(anIntegerTimestamp)) {
+            time = __unsignedLongIntVal(anIntegerTimestamp);
+        } else
+            goto err;
+
+        ENTER_XLIB();
+        XConvertSelection(dpy, __AtomVal(selectionID), __AtomVal(typeID),
+                               __AtomVal(propertyID), w, time);
+        LEAVE_XLIB();
+
+        RETURN (true);
+err:;
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false
+
+    "
+     Display
+        requestSelection:(Display atomIDOf:'PRIMARY')
+        property:(Display atomIDOf:'VT_SELECTION')
+        type:(Display atomIDOf:'STRING')
+        for:Transcript id
+    "
+    "
+     Display
+        requestSelection:(Display atomIDOf:'PRIMARY')
+        property:(Display atomIDOf:'VT_SELECTION')
+        type:(Display atomIDOf:'C_STRING')
+        for:Transcript id
+    "
+!
+
+sendNotifySelection:selectionID property:propertyID target:targetID time:aTime to:requestorID
+    "send a selectionNotify back from a SelectionRequest.
+     PropertyID should be the same as requested  or nil, if the selection
+     could not be converted.
+     TargetId should be the same as requested.
+     Time should be the time when the selection has been acquired"
+
+    <context: #return>
+%{
+    if (ISCONNECTED
+        && (__isAtomID(propertyID) || propertyID == nil)
+        && __isAtomID(targetID) && __isAtomID(selectionID)) {
+        Display *dpy = myDpy;
+        XEvent ev;
+        Window requestor;
+        Status result;
+
+        if (__isExternalAddress(requestorID)) {
+            requestor = __WindowVal(requestorID);
+        } else if (__isSmallInteger(requestorID)) {
+            requestor = (Window)__smallIntegerVal(requestorID);
+        } else if (requestorID == nil) {
+            requestor = DefaultRootWindow(dpy);
+        } else {
+            requestor = (Window)__unsignedLongIntVal(requestorID);
+        }
+
+        ev.xselection.type = SelectionNotify;
+        ev.xselection.display = dpy;
+        ev.xselection.selection = __AtomVal(selectionID);
+        ev.xselection.target = __AtomVal(targetID);
+        ev.xselection.requestor = requestor;
+
+        if (__isExternalAddress(aTime)) {
+            ev.xselection.time = (INT)(__externalAddressVal(aTime));
+        } else if (__isSmallInteger(aTime)) {
+            ev.xselection.time = __smallIntegerVal(aTime);
+        } else if (aTime == nil) {
+            ev.xselection.time = CurrentTime;
+        } else {
+            ev.xselection.time = (INT)__unsignedLongIntVal(aTime);
+        }
+#if 0
+        console_printf("ev.xselection.selection: %x\n", ev.xselection.selection);
+        console_printf("ev.xselection.target: %x\n", ev.xselection.target);
+        console_printf("ev.xselection.requestor: %x\n", ev.xselection.requestor);
+        console_printf("ev.xselection.time: %x\n", ev.xselection.time);
+        console_printf("requestor: %x\n", requestor);
+#endif
+
+        /* send nil property if selection cannot be converted */
+        if (propertyID == nil)
+            ev.xselection.property = None;
+        else
+            ev.xselection.property = __AtomVal(propertyID);
+
+
+        DPRINTF(("sending SelectionNotify sel=%"_lx_" prop=%"_lx_" target=%"_lx_" requestor=%"_lx_" to %"_lx_"\n",
+                (INT)ev.xselection.selection,
+                (INT)ev.xselection.property,
+                (INT)ev.xselection.target,
+                (INT)ev.xselection.requestor,
+                (INT)requestor));
+
+        ENTER_XLIB();
+        result = XSendEvent(dpy, requestor, False, 0 , &ev);
+        LEAVE_XLIB();
+
+        if ((result == BadValue) || (result == BadWindow)) {
+            DPRINTF(("bad status\n"));
+            RETURN (false);
+        }
+        ENTER_XLIB();
+        XFlush(dpy);
+        LEAVE_XLIB();
+        RETURN (true)
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false
+
+    "Modified: / 17.6.1998 / 20:23:20 / cg"
+!
+
+setSelectionOwner:aWindowId of:selectionAtomSymbolOrID time:anIntegerTimestamp
+    "set the owner of a selection; return false if failed"
+
+    <context: #return>
+
+    |selectionAtomID|
+
+    "store the current owner of the selection.
+     If we still own the selection on paste,
+     we can avoid the X11 overhead"
+
+    selectionOwner := aWindowId.
+
+    selectionAtomSymbolOrID isString ifTrue:[
+        selectionAtomID := self atomIDOf:selectionAtomSymbolOrID create:false.
+    ] ifFalse:[
+        selectionAtomID := selectionAtomSymbolOrID.
+    ].
+
+%{
+    Window win;
+
+    if (__isExternalAddress(aWindowId)
+     && __isAtomID(selectionAtomID)
+     && ISCONNECTED) {
+        Display *dpy = myDpy;
+        Time time;
+
+        win = __WindowVal(aWindowId);
+
+        if (anIntegerTimestamp == nil) {
+            /*
+             * the ICCCM convention says: you should set the time to the time when
+             * the selection was acquired and not to CurrentTime
+             */
+            time = CurrentTime;
+        } else if (__isInteger(anIntegerTimestamp)) {
+            time = __unsignedLongIntVal(anIntegerTimestamp);
+        } else
+            goto err;
+
+        DPRINTF(("setOwner prop=%"_lx_" win=%"_lx_"\n", (INT)__AtomVal(selectionAtomID), (INT)win));
+        ENTER_XLIB();
+        XSetSelectionOwner(dpy, __AtomVal(selectionAtomID), win, time);
+        RETURN (self);
+        LEAVE_XLIB();
+    }
+err:;
+%}.
+    self primitiveFailedOrClosedConnection.
+! !
+
+!XWorkstation methodsFor:'window queries'!
+
+allChildIdsOf:aWindowId
+    "return all children-ids of the given window.
+     Allows for all windows to be enumerated, if we start at the root."
+
+    |childIDs allChildIDs|
+
+    allChildIDs := OrderedCollection new.
+    childIDs := self childIdsOf:aWindowId.
+    childIDs notNil ifTrue:[
+        allChildIDs addAll:childIDs.
+        childIDs do:[:eachChildId |
+            allChildIDs addAll:(self allChildIdsOf:eachChildId).
+        ].
+    ].
+    ^ allChildIDs
+
+    "
+     Display allChildIdsOf:(Display rootWindowId)
+    "
+
+    "
+     |deviceIDAtom uuidAtom|
+
+     deviceIDAtom := (Display atomIDOf:#'STX_DEVICE_ID').
+     uuidAtom     := (Display atomIDOf:#'UUID').
+     (Display allChildIdsOf:(Display rootWindowId))
+        select:[:id |
+            |uuid|
+
+            Display
+                getProperty:deviceIDAtom
+                from:id
+                delete:false
+                into:[:type :value |
+                    type == uuidAtom ifTrue:[
+                        uuid := UUID fromBytes:value.
+                    ].
+                ].
+            uuid notNil.
+        ]
+    "
+!
+
+childIdsOf:aWindowId
+    "return all children-ids of the given window. Allows for all windows to be
+     enumerated, if we start at the root."
+
+    |childIdArray|
+%{
+    OBJ id;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        Display *dpy = myDpy;
+        Window win = __WindowVal(aWindowId);
+        Window rootReturn, parentReturn;
+        Window* children = (Window *)0;
+        unsigned int numChildren;
+        int i;
+        int rslt;
+
+        ENTER_XLIB();
+        rslt = XQueryTree(dpy, win,
+                       &rootReturn, &parentReturn,
+                       &children, &numChildren);
+        LEAVE_XLIB();
+        if (rslt) {
+            childIdArray = __ARRAY_NEW_INT(numChildren);
+            if (childIdArray != nil) {
+                for (i=0; i < numChildren; i++) {
+                    if (children[i]) {
+                        OBJ childId;
+
+                        childId = __MKEXTERNALADDRESS(children[i]);
+                        __ArrayInstPtr(childIdArray)->a_element[i] = childId;
+                        __STORE(childIdArray, childId);
+                    }
+                }
+                if (children) XFree(children);
+            }
+            RETURN (childIdArray);
+        }
+    }
+%}.
+    ^ nil.
+
+    "
+      Display childIdsOf:(Display rootWindowId)
+    "
+!
+
+realRootWindowId
+    "return the id of the real root window.
+     This may not be the window you see as background,
+     since some window managers install a virtual root window on top
+     of it. Except for very special cases, use #rootWindowId, which takes
+     care of any virtual root."
+
+%{
+    int screen = __intVal(__INST(screen));
+    Window root;
+    OBJ id;
+
+    if (__INST(rootId) != nil) {
+        RETURN (__INST(rootId));
+    }
+
+    if (ISCONNECTED) {
+        root = RootWindow(myDpy, screen);
+        if (! root) {
+            id = nil;
+        } else {
+            id = __MKEXTERNALADDRESS(root); __INST(rootId) = id; __STORE(self, id);
+        }
+        RETURN (id);
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ nil
+
+    "
+      Display rootWindowId
+      Display realRootWindowId
+    "
+!
+
+rootWindowId
+    "return the id of the root window.
+     This is the window you see as background,
+     however, it may or may not be the real physical root window,
+     since some window managers install a virtual root window on top
+     of the real one. If this is the case, that views id is returned here."
+
+%{
+    int screen = __intVal(__INST(screen));
+    Window rootWin, vRootWin = 0;
+    OBJ id;
+
+    if (__INST(virtualRootId) != nil) {
+        RETURN (__INST(virtualRootId));
+    }
+
+    if (ISCONNECTED) {
+        Display *dpy = myDpy;
+
+        rootWin = RootWindow(dpy, screen);
+#ifndef IRIS
+
+        /*
+         * on IRIS, this creates a badwindow error - why ?
+         * children contains a funny window (000034)
+         */
+
+        /*
+         * care for virtual root windows (tvtwm & friends)
+         */
+        {
+            Atom vRootAtom, kwinAtom;
+            int i;
+            Window rootReturn, parentReturn;
+            Window* children = (Window *)0;
+            unsigned int numChildren;
+            int ignoreVRoot = 0;
+
+            /*
+             * Take care of KDE 2.1.
+             * they define _SWM_ROOT but this is not the parent of
+             * the application windows.
+             * Instead it is used for background painting
+             */
+
+            kwinAtom = XInternAtom(dpy, "KWIN_RUNNING", True);
+            if (kwinAtom != None) {
+                Atom actual_type;
+                int actual_format;
+                unsigned long nitems, bytesafter;
+                unsigned char *retVal = 0;
+
+                ignoreVRoot = XGetWindowProperty(dpy, rootWin, kwinAtom,
+                                       0L, 1L, False, kwinAtom,
+                                       &actual_type, &actual_format,
+                                       &nitems, &bytesafter, &retVal) == Success
+                              && actual_type != 0;
+                if (retVal)
+                    XFree(retVal);
+            }
+
+            if (!ignoreVRoot) {
+                vRootAtom = XInternAtom(dpy, "__SWM_VROOT", True);
+                if (vRootAtom != None) {
+                    if (XQueryTree(dpy, rootWin,
+                                       &rootReturn, &parentReturn,
+                                       &children, &numChildren)) {
+                        for (i=0; i < numChildren; i++) {
+                            Atom actual_type;
+                            int actual_format;
+                            unsigned long nitems, bytesafter;
+                            Window* newRoot = (Window*) 0;
+
+                            if (children[i]) {
+                                if (XGetWindowProperty(dpy, children[i], vRootAtom,
+                                                       0L, 1L, False, XA_WINDOW,
+                                                       &actual_type, &actual_format,
+                                                       &nitems, &bytesafter,
+                                                       (unsigned char**) &newRoot
+                                                      ) == Success && newRoot) {
+                                    vRootWin = *newRoot;
+                                    XFree(newRoot); /* XXX */
+                                    break;
+                                }
+                            }
+                        }
+                        if (children) XFree(children);
+                    }
+                }
+             }
+        }
+#endif
+    }
+
+    if (! vRootWin) {
+        vRootWin = rootWin;
+        if (! vRootWin) {
+            RETURN ( nil );
+        }
+    }
+    id = __MKEXTERNALADDRESS(rootWin); __INST(rootId) = id; __STORE(self, id);
+    id = __MKEXTERNALADDRESS(vRootWin); __INST(virtualRootId) = id; __STORE(self, id);
+    RETURN ( id );
+%}
+
+    "
+      Display rootWindowId
+    "
+! !
+
+!XWorkstation methodsFor:'window stuff'!
+
+clearRectangleX:x y:y width:width height:height in:aWindowId
+    "clear a rectangular area to viewbackground"
+
+    <context: #return>
+%{
+
+    int w, h;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aWindowId)
+         && __bothSmallInteger(x, y)
+         && __bothSmallInteger(width, height)) {
+            w = __intVal(width);
+            h = __intVal(height);
+            /*
+             * need this check here: some servers simply dump core with bad args
+             */
+            if ((w >= 0) && (h >= 0)) {
+                ENTER_XLIB();
+                XClearArea(myDpy, __WindowVal(aWindowId), __intVal(x), __intVal(y), w, h, 0);
+                LEAVE_XLIB();
+            }
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+!
+
+clearWindow:aWindowId
+    "clear a window to viewbackground"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aWindowId)) {
+            ENTER_XLIB();
+            XClearWindow(myDpy, __WindowVal(aWindowId));
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+configureWindow:aWindowId sibling:siblingId stackMode:modeSymbol
+    "configure stacking operation of aWindowId w.r.t siblingId"
+
+    <context: #return>
+%{
+
+    XWindowChanges chg;
+    int mask = CWSibling | CWStackMode;
+
+    if (ISCONNECTED) {
+        if (__isExternalAddress(aWindowId)
+         && __isExternalAddress(siblingId)) {
+            if (modeSymbol == @symbol(above)) {
+                chg.stack_mode = Above;
+            } else if (modeSymbol == @symbol(below)) {
+                chg.stack_mode = Below;
+            } else if (modeSymbol == @symbol(topIf)) {
+                chg.stack_mode = TopIf;
+            } else if (modeSymbol == @symbol(bottomIf)) {
+                chg.stack_mode = BottomIf;
+            } else if (modeSymbol == @symbol(opposite)) {
+                chg.stack_mode = Opposite;
+            } else {
+                mask = CWSibling;
+            }
+
+            chg.sibling = __WindowVal(siblingId);
+            ENTER_XLIB();
+            XConfigureWindow(myDpy, __WindowVal(aWindowId),
+                                    mask, &chg);
+            LEAVE_XLIB();
+            RETURN ( self );
+        }
+    }
+bad: ;
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+getGeometryOf:aWindowId
+    "get a windows geometry.
+     NOTICE: X-WindowManagers usually do wrap client topViews into their own
+     decoration views (top label, resize boundaries etc.).
+     Thus, the numbers returned here for topViews are the physical (real) dimensions
+     relative to such a wrapper.
+     In contrast, the values found in the views instance variables are virtual dimensions
+     (i.e. ST/X makes this decoration view transparent to the program."
+
+    <context: #return>
+
+    |x y width height depth borderWidth info|
+
+%{
+    int x_ret, y_ret;
+    unsigned int width_ret, height_ret,
+                 border_width_ret, depth_ret;
+    Window root_ret;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        ENTER_XLIB();
+        XGetGeometry(myDpy, __WindowVal(aWindowId),
+                     &root_ret,
+                     &x_ret, &y_ret,
+                     &width_ret, &height_ret, &border_width_ret,
+                     &depth_ret);
+        LEAVE_XLIB();
+
+        x = __MKSMALLINT(x_ret);
+        y = __MKSMALLINT(y_ret);
+        width = __MKSMALLINT(width_ret);
+        height = __MKSMALLINT(height_ret);
+        depth = __MKSMALLINT(depth_ret);
+        borderWidth = __MKSMALLINT(border_width_ret);
+    }
+%}.
+    borderWidth isNil ifTrue:[
+        self primitiveFailedOrClosedConnection.
+        ^ nil
+    ].
+    info := Dictionary new.
+    info at:#origin put:(x @ y).
+    info at:#extent put:(width @ height).
+    info at:#depth  put:depth.
+    info at:#borderWidth put:borderWidth.
+    ^ info
+
+    "
+     Transcript topView device
+        getGeometryOf:(Transcript id)
+    "
+    "
+     Transcript topView device
+        getGeometryOf:(Transcript topView id)
+    "
+    "
+     Display
+        getGeometryOf:(Display viewIdFromUser)
+    "
+    "
+     |d|
+
+     d := Transcript topView device.
+     d getGeometryOf:(d parentWindowIdOf:Transcript topView id)
+    "
+!
+
+isValidWindowId:aWindowId
+    "return true, if the given window ID is (still) valid.
+     Especially useful, if the passed windowID is
+     an alien (external) windows id."
+
+    |ret|
+
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        char *name = NULL;
+        Status ok;
+        Window root, parent, *children = NULL;
+        unsigned int nChildren;
+
+/*        ENTER_XLIB(); */
+        ok = XQueryTree(myDpy, __WindowVal(aWindowId),
+                        &root, &parent, &children, &nChildren);
+        if (children) {
+            XFree(children);
+        }
+/*        LEAVE_XLIB();   */
+        if (ok) {
+            RETURN (true);
+        }
+        RETURN (false);
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false
+
+    "
+     |v aWindowId ok|
+
+     v := StandardSystemView new.
+     v label:'hello'.
+     v openAndWait.
+     aWindowId := v id.
+     ok := Display isValidWindowId:aWindowId.
+     Transcript showCR:'ok is: ' , ok printString.
+     Delay waitForSeconds:1.
+     v destroy.
+     ok := Display isValidWindowId:aWindowId.
+     Transcript showCR:'ok is: ' , ok printString.
+    "
+!
+
+lowerWindow:aWindowId
+    "bring a window to back"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        ENTER_XLIB();
+        XLowerWindow(myDpy, __WindowVal(aWindowId));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+mapView:aView id:aWindowId iconified:aBoolean atX:xPos y:yPos
+              width:w height:h minExtent:minExt maxExtent:maxExt
+
+    <context: #return>
+
+    "make a window visible - either as icon or as a real view
+     in addition, allow change of extend, position, minExtend and maxExtent.
+     Needed for restart, to allow recreating a view as iconified,
+     and to collaps/expand windows."
+
+    |wicon wiconId iconMaskId wiconView wiconViewId wlabel minW minH maxW maxH|
+
+    aBoolean ifTrue:[
+        wicon := aView icon.
+        wicon notNil ifTrue:[
+            wiconId := wicon id.
+            wicon mask notNil ifTrue:[
+                iconMaskId := wicon mask id.
+            ].
+        ].
+        wiconView := aView iconView.
+        wiconView notNil ifTrue:[
+            wiconViewId := wiconView id
+        ].
+        wlabel := aView label.
+    ].
+    minExt notNil ifTrue:[
+        minW := minExt x.
+        minH := minExt y.
+    ].
+    maxExt notNil ifTrue:[
+        maxW := maxExt x.
+        maxH := maxExt y.
+    ].
+%{
+
+    XWMHints wmhints;
+    XSizeHints szhints;
+    Window win;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        Display *dpy = myDpy;
+
+        win = __WindowVal(aWindowId);
+
+        szhints.flags = 0;
+        if (__bothSmallInteger(xPos, yPos)) {
+            szhints.x = __intVal(xPos);
+            szhints.y = __intVal(yPos);
+            szhints.flags |= USPosition;
+        }
+        if (__bothSmallInteger(w, h)) {
+            szhints.width = __intVal(w);
+            szhints.height = __intVal(h);
+            szhints.flags |= USSize;
+        }
+        if (__bothSmallInteger(minW, minH)) {
+            szhints.flags |= PMinSize;
+            szhints.min_width = __intVal(minW);
+            szhints.min_height = __intVal(minH);
+        }
+        if (__bothSmallInteger(maxW, maxH)) {
+            szhints.flags |= PMaxSize;
+            szhints.max_width = __intVal(maxW);
+            szhints.max_height = __intVal(maxH);
+        }
+
+        if (aBoolean == true) {
+            char *windowName = "";
+            Pixmap iconBitmap = (Pixmap)0;
+            Pixmap iconMask = (Pixmap)0;
+            Window iconWindow = (Window)0;
+
+            if (__isExternalAddress(wiconId))
+                iconBitmap = __PixmapVal(wiconId);
+
+            if (__isExternalAddress(iconMaskId)) {
+                iconMask = __PixmapVal(iconMaskId);
+            }
+
+            if (__isExternalAddress(wiconViewId))
+                iconWindow = __WindowVal(wiconViewId);
+
+            if (__isStringLike(wlabel))
+                windowName = (char *) __stringVal(wlabel);
+
+            if (iconBitmap || windowName) {
+                ENTER_XLIB();
+                XSetStandardProperties(dpy, win,
+                                        windowName, windowName,
+                                        iconBitmap,
+                                        0, 0, &szhints);
+                LEAVE_XLIB();
+            }
+
+            wmhints.flags = 0;
+            if (iconBitmap) {
+                wmhints.flags |= IconPixmapHint;
+                wmhints.icon_pixmap = iconBitmap;
+            }
+            if (iconMask) {
+                wmhints.flags |= IconMaskHint;
+                wmhints.icon_mask = iconMask;
+            }
+            if (iconWindow) {
+                wmhints.flags |= IconWindowHint;
+                wmhints.icon_window = iconWindow;
+            }
+
+            wmhints.initial_state = IconicState;
+            wmhints.flags |= StateHint;
+            ENTER_XLIB();
+            XSetWMHints(dpy, win, &wmhints);
+            LEAVE_XLIB();
+        }
+
+        if (szhints.flags) {
+            ENTER_XLIB();
+            XSetNormalHints(dpy, win, &szhints);
+            LEAVE_XLIB();
+        }
+
+        ENTER_XLIB();
+        XMapWindow(dpy, win);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+mapWindow:aWindowId
+    "make a window visible"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        ENTER_XLIB();
+        XMapWindow(myDpy, __WindowVal(aWindowId));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+moveResizeWindow:aWindowId x:x y:y width:w height:h
+    "move and resize a window"
+
+    <context: #return>
+%{
+
+    int newWidth, newHeight;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __bothSmallInteger(w, h)
+     && __bothSmallInteger(x, y)) {
+        newWidth = __intVal(w);
+        newHeight = __intVal(h);
+        if (newWidth < 1) newWidth = 1;
+        if (newHeight < 1) newHeight = 1;
+        ENTER_XLIB();
+        XMoveResizeWindow(myDpy, __WindowVal(aWindowId),
+                              __intVal(x), __intVal(y),
+                              newWidth, newHeight);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+moveWindow:aWindowId x:x y:y
+    "move a window"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId) && __bothSmallInteger(x, y)) {
+        ENTER_XLIB();
+        XMoveWindow(myDpy, __WindowVal(aWindowId), __intVal(x), __intVal(y));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+newGraphicsContextFor:aGraphicsMedium
+    "create a new graphics context.
+     The defaults is to use the inherited graphics context.
+     Subclasses may redefine this to use their own graphics context"
+
+"/    ^ aGraphicsMedium.
+    |gc|
+
+    gc := X11GraphicsContext onDevice:self.
+    gc font:aGraphicsMedium class defaultFont.
+    ^ gc.
+!
+
+parentWindowIdOf:aWindowId
+    "return a windows parent-window id.
+     Useful with getGeometryOf:, to compute information about the decoration."
+
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        Status ok;
+        Window root, parent, *children = NULL;
+        unsigned int nChildren;
+
+/*        ENTER_XLIB(); */
+        ok = XQueryTree(myDpy, __WindowVal(aWindowId),
+                        &root, &parent, &children, &nChildren);
+        if (children) {
+            XFree(children);
+        }
+/*        LEAVE_XLIB();   */
+        if (! ok) {
+            RETURN ( nil );
+        }
+        RETURN ( __MKEXTERNALADDRESS(parent) );
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false
+
+    "
+     |id|
+
+     id := Transcript device parentWindowIdOf:(Transcript id).
+     self assert: ( Transcript container id = id ).
+    "
+!
+
+raiseWindow:aWindowId
+    "bring a window to front"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        ENTER_XLIB();
+        XRaiseWindow(myDpy, __WindowVal(aWindowId));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+reparentWindow:windowId to:newParentWindowId
+    "change a windows parent (an optional interface)"
+
+    <context: #return>
+%{
+    if (ISCONNECTED
+     && __isExternalAddress(windowId)
+     && __isExternalAddress(newParentWindowId)) {
+        Display *dpy = myDpy;
+        Window _child, _newParent;
+        int i;
+
+        _child = __WindowVal(windowId);
+        _newParent = __WindowVal(newParentWindowId);
+        ENTER_XLIB();
+
+#if 0
+        XWithdrawWindow (dpy, _child, DefaultScreen(dpy));
+        XSync (dpy, 0);
+#endif
+        /*
+         * Code 'stolen' from xswallow source ...
+         * ... mhmh - what is this loop for ?
+         */
+        for (i=0; i<5; i++) {
+            XReparentWindow (dpy, _child, _newParent, 0, 0);
+            XSync (dpy, 0);
+        }
+#if 0
+        XMapWindow (dpy, _child);
+        XSync (dpy, 0);
+#endif
+        LEAVE_XLIB();
+        RETURN ( true );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+resizeWindow:aWindowId width:w height:h
+    "resize a window"
+
+    <context: #return>
+%{
+
+    int newWidth, newHeight;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId) && __bothSmallInteger(w, h)) {
+        newWidth = __intVal(w);
+        newHeight = __intVal(h);
+        if (newWidth < 1) newWidth = 1;
+        if (newHeight < 1) newHeight = 1;
+        ENTER_XLIB();
+        XResizeWindow(myDpy, __WindowVal(aWindowId), newWidth, newHeight);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setBackingStore:how in:aWindowId
+    "turn on/off backing-store for a window"
+
+    <context: #return>
+%{
+
+    XSetWindowAttributes wa;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        if (__INST(ignoreBackingStore) != true) {
+            if (how == @symbol(always)) wa.backing_store = Always;
+            else if (how == @symbol(whenMapped)) wa.backing_store = WhenMapped;
+            else if (how == true) wa.backing_store = Always;
+            else wa.backing_store = 0;
+
+            ENTER_XLIB();
+            XChangeWindowAttributes(myDpy, __WindowVal(aWindowId), CWBackingStore, &wa);
+            LEAVE_XLIB();
+
+        }
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setBitGravity:how in:aWindowId
+    "set bit gravity for a window"
+
+    <context: #return>
+%{
+
+    XSetWindowAttributes wa;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        if (how == @symbol(NorthWest)) {
+            wa.bit_gravity = NorthWestGravity;
+        } else if (how == @symbol(NorthEast)) {
+            wa.bit_gravity = NorthEastGravity;
+        } else if (how == @symbol(SouthWest)) {
+            wa.bit_gravity = SouthWestGravity;
+        } else if (how == @symbol(SouthEast)) {
+            wa.bit_gravity = SouthEastGravity;
+        } else if (how == @symbol(Center)) {
+            wa.bit_gravity = CenterGravity;
+        } else if (how == @symbol(North)) {
+            wa.bit_gravity = NorthGravity;
+        } else if (how == @symbol(South)) {
+            wa.bit_gravity = SouthGravity;
+        } else if (how == @symbol(West)) {
+            wa.bit_gravity = WestGravity;
+        } else if (how == @symbol(East)) {
+            wa.bit_gravity = EastGravity;
+        } else {
+            wa.bit_gravity = NorthWestGravity;
+        }
+
+
+        ENTER_XLIB();
+        XChangeWindowAttributes(myDpy, __WindowVal(aWindowId), CWBitGravity, &wa);
+        LEAVE_XLIB();
+
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setCursor:aCursorId in:aWindowId
+    "define a windows cursor"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __isExternalAddress(aCursorId)) {
+        Display *dpy = myDpy;
+        Window w = __WindowVal(aWindowId);
+        Cursor c = __CursorVal(aCursorId);
+
+        if (w && c) {
+            ENTER_XLIB();
+            XDefineCursor(dpy, w, c);
+            LEAVE_XLIB();
+        }
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setForegroundWindow:aWindowId
+    "bring a window to front.
+     Send a specific message to the WindowManager"
+
+    |activeWindowAtom|
+
+"/    self raiseWindow:aWindowId.
+
+    activeWindowAtom := self atomIDOf:#'_NET_ACTIVE_WINDOW' create:false.
+    activeWindowAtom notNil ifTrue:[
+        self
+            sendClientEvent:activeWindowAtom
+            format:32
+            to:(self rootWindowId)
+            propagate:false
+            eventMask:((self eventMaskFor:#substructureNotify) bitOr:(self eventMaskFor:#substructureRedirect))
+            window:aWindowId
+            data1:2                 "activate request from pager. This is a trick: kwm ignores requests from applications (1)"
+            data2:nil
+            data3:nil
+            data4:nil
+            data5:nil.
+    ].
+
+    "
+      Transcript topView setForegroundWindow
+    "
+!
+
+setIconName:aString in:aWindowId
+    "define a windows iconname"
+
+    <context: #return>
+
+    |utf8StringAtom utf8String simpleString|
+
+    utf8StringAtom := self atomIDOf:#UTF8_STRING create:true.
+
+    utf8String := aString utf8Encoded.
+    aString isWideString ifTrue:[
+        "/ X does not like 2-byte labels ...
+        simpleString := aString asSingleByteStringReplaceInvalidWith:$?
+    ] ifFalse:[
+        simpleString := aString.
+    ].
+
+%{
+    XTextProperty titleProperty;
+
+    if (ISCONNECTED
+     && __isStringLike(utf8String)
+     && __isStringLike(simpleString)
+     && __isExternalAddress(aWindowId)) {
+
+        titleProperty.value =  __stringVal(utf8String);
+        titleProperty.encoding = __smallIntegerVal(utf8StringAtom);
+        titleProperty.format = 8;
+        titleProperty.nitems = __stringSize(utf8String);
+
+        ENTER_XLIB();
+        XSetIconName(myDpy, __WindowVal(aWindowId), (char *) __stringVal(simpleString));
+        /* alternative settings for UTF8-Strings */
+        XSetWMIconName(myDpy, __WindowVal(aWindowId), &titleProperty);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setSaveUnder:yesOrNo in:aWindowId
+    "turn on/off save-under for a window"
+
+    <context: #return>
+%{
+
+    XSetWindowAttributes wa;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        if (__INST(hasSaveUnder) == true) {
+            wa.save_under = (yesOrNo == true) ? 1 : 0;
+            ENTER_XLIB();
+            XChangeWindowAttributes(myDpy, __WindowVal(aWindowId), CWSaveUnder, &wa);
+            LEAVE_XLIB();
+        }
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setTransient:aWindowId for:aMainWindowId
+    "set aWindowId to be a transient of aMainWindow"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        Window w;
+
+        if ((aMainWindowId == nil) || (aMainWindowId == __MKSMALLINT(0))) {
+            w = (Window) 0;
+        } else {
+            if (__isExternalAddress(aMainWindowId)) {
+                w = __WindowVal(aMainWindowId);
+            } else {
+                goto getOutOfHere;
+            }
+        }
+        ENTER_XLIB();
+        XSetTransientForHint(myDpy, __WindowVal(aWindowId), w);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+ getOutOfHere: ;
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowBackground:aColorIndex in:aWindowId
+    "set the windows background color. This is the color with which
+     the view is filled whenever exposed. Do not confuse this with
+     the background drawing color, which is used with opaque drawing."
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __isSmallInteger(aColorIndex)) {
+        ENTER_XLIB();
+        XSetWindowBackground(myDpy, __WindowVal(aWindowId), __intVal(aColorIndex));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowBackgroundPixmap:aPixmapId in:aWindowId
+    "set the windows background pattern to be a form.
+     This is the pattern with which the view is filled whenever exposed.
+     Do not confuse this with the background drawing color, which is used
+     with opaque drawing."
+
+    <context: #return>
+%{  /* STACK: 64000 */
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __isExternalAddress(aPixmapId)) {
+        ENTER_XLIB();
+        XSetWindowBackgroundPixmap(myDpy, __WindowVal(aWindowId), __PixmapVal(aPixmapId));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowBorderColor:aColorIndex in:aWindowId
+    "set the windows border color"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __isSmallInteger(aColorIndex)) {
+        ENTER_XLIB();
+        XSetWindowBorder(myDpy, __WindowVal(aWindowId), __intVal(aColorIndex));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowBorderPixmap:aPixmapId in:aWindowId
+    "set the windows border pattern"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __isExternalAddress(aPixmapId)) {
+        ENTER_XLIB();
+        XSetWindowBorderPixmap(myDpy, __WindowVal(aWindowId), __PixmapVal(aPixmapId));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowBorderShape:aPixmapId in:aWindowId
+    "set the windows border shape"
+
+    <context: #return>
+
+    hasShapeExtension ifFalse:[^ self].
+
+%{
+
+#ifdef SHAPE
+    Pixmap shapeBitmap;
+
+    if (__isExternalAddress(aPixmapId))
+        shapeBitmap = __PixmapVal(aPixmapId);
+    else
+        shapeBitmap = (Pixmap)0;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        ENTER_XLIB();
+        XShapeCombineMask(myDpy, __WindowVal(aWindowId), ShapeBounding,
+                          0, 0, shapeBitmap, ShapeSet);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+#endif
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowBorderWidth:aNumber in:aWindowId
+    "set the windows border width"
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)
+     && __isSmallInteger(aNumber)) {
+        ENTER_XLIB();
+        XSetWindowBorderWidth(myDpy, __WindowVal(aWindowId), __intVal(aNumber));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowClass:wClass name:wName in:aWindowId
+    "define class and name of a window.
+     This may be used by the window manager to
+     select client specific resources."
+
+    <context: #return>
+%{
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        XClassHint classhint;
+
+        classhint.res_class = classhint.res_name = 0;
+
+        if (__isStringLike(wClass)) {
+            classhint.res_class = (char *) __stringVal(wClass);
+        } else if (wClass != nil)
+            goto error;
+
+        if (__isStringLike(wName)) {
+            classhint.res_name = (char *) __stringVal(wName);
+        } else if (wName != nil)
+            goto error;
+
+        ENTER_XLIB();
+        XSetClassHint(myDpy, __WindowVal(aWindowId), &classhint);
+        LEAVE_XLIB();
+        RETURN ( self );
+error:;
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowGravity:how in:aWindowId
+    "set window gravity for a window"
+
+    <context: #return>
+%{
+
+    XSetWindowAttributes wa;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        if (how == @symbol(NorthWest)) {
+            wa.win_gravity = NorthWestGravity;
+        } else if (how == @symbol(NorthEast)) {
+            wa.win_gravity = NorthEastGravity;
+        } else if (how == @symbol(SouthWest)) {
+            wa.win_gravity = SouthWestGravity;
+        } else if (how == @symbol(SouthEast)) {
+            wa.win_gravity = SouthEastGravity;
+        } else if (how == @symbol(Center)) {
+            wa.win_gravity = CenterGravity;
+        } else if (how == @symbol(North)) {
+            wa.win_gravity = NorthGravity;
+        } else if (how == @symbol(South)) {
+            wa.win_gravity = SouthGravity;
+        } else if (how == @symbol(West)) {
+            wa.win_gravity = WestGravity;
+        } else if (how == @symbol(East)) {
+            wa.win_gravity = EastGravity;
+        } else {
+            wa.win_gravity = NorthWestGravity;
+        }
+
+
+        ENTER_XLIB();
+        XChangeWindowAttributes(myDpy, __WindowVal(aWindowId), CWWinGravity, &wa);
+        LEAVE_XLIB();
+
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowIcon:aForm in:aWindowId
+    "define a bitmap to be used as icon"
+
+    <context: #return>
+
+    |iconId|
+
+    aForm notNil ifTrue:[
+        iconId := aForm id
+    ].
+%{
+    if (ISCONNECTED
+     && __isExternalAddress(iconId)
+     && __isExternalAddress(aWindowId)) {
+        XWMHints hints;
+
+        hints.icon_pixmap = __PixmapVal(iconId);
+        hints.flags = IconPixmapHint;
+        ENTER_XLIB();
+        XSetWMHints(myDpy, __WindowVal(aWindowId), &hints);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowIcon:aForm mask:aMaskForm in:aWindowId
+    "define a windows icon and (optional) iconMask."
+
+    <context: #return>
+
+    |iconId maskId|
+
+    aForm notNil ifTrue:[
+        iconId := aForm id
+    ].
+    aMaskForm notNil ifTrue:[
+        maskId := aMaskForm id.
+    ].
+%{
+    if (ISCONNECTED
+     && __isExternalAddress(iconId)
+     && __isExternalAddress(aWindowId)) {
+        XWMHints hints;
+
+        hints.icon_pixmap = __PixmapVal(iconId);
+        hints.flags = IconPixmapHint;
+        if ((maskId != nil)
+         && __isExternalAddress(maskId)) {
+            hints.icon_mask = __PixmapVal(maskId);
+            hints.flags |= IconMaskHint;
+        }
+        ENTER_XLIB();
+        XSetWMHints(myDpy, __WindowVal(aWindowId), &hints);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+
+!
+
+setWindowIconWindow:aView in:aWindowId
+    "define a window to be used as icon"
+
+    <context: #return>
+
+    |iconWindowId|
+
+    aView notNil ifTrue:[
+        iconWindowId := aView id
+    ].
+%{
+    if (ISCONNECTED
+     && __isExternalAddress(iconWindowId)
+     && __isExternalAddress(aWindowId)) {
+        XWMHints wmhints;
+
+        wmhints.icon_window = __WindowVal(iconWindowId);
+        wmhints.flags = IconWindowHint;
+        ENTER_XLIB();
+        XSetWMHints(myDpy, __WindowVal(aWindowId), &wmhints);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowMinExtentX:minW y:minH maxExtentX:maxW y:maxH in:aWindowId
+    "set a windows minimum & max extents.
+     nil arguments are ignored."
+
+    <context: #return>
+%{
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        Display *dpy = myDpy;
+        XSizeHints szhints;
+        Window win;
+
+        win = __WindowVal(aWindowId);
+
+        szhints.flags = 0;
+        if (__bothSmallInteger(minW, minH)) {
+            szhints.flags |= PMinSize;
+            szhints.min_width = __intVal(minW);
+            szhints.min_height = __intVal(minH);
+        }
+        if (__bothSmallInteger(maxW, maxH)) {
+            szhints.flags |= PMaxSize;
+            szhints.max_width = __intVal(maxW);
+            szhints.max_height = __intVal(maxH);
+        }
+
+        if (szhints.flags) {
+            ENTER_XLIB();
+            XSetNormalHints(dpy, win, &szhints);
+            LEAVE_XLIB();
+        }
+    }
+%}.
+!
+
+setWindowName:aString in:aWindowId
+    "define a windows name"
+
+    <context: #return>
+
+    |utf8StringAtom utf8String simpleString|
+
+    utf8StringAtom := self atomIDOf:#UTF8_STRING create:true.
+
+    utf8String := aString utf8Encoded.
+    aString isWideString ifTrue:[
+        "/ X does not like 2-byte labels ...
+        simpleString := aString asSingleByteStringReplaceInvalidWith:$?
+    ] ifFalse:[
+        simpleString := aString.
+    ].
+
+%{
+
+    XTextProperty titleProperty;
+
+    if (ISCONNECTED
+     && __isStringLike(utf8String)
+     && __isStringLike(simpleString)
+     && __isExternalAddress(aWindowId)) {
+
+        titleProperty.value =  __stringVal(utf8String);
+        titleProperty.encoding = __smallIntegerVal(utf8StringAtom);
+        titleProperty.format = 8;
+        titleProperty.nitems = __stringSize(utf8String);
+
+        ENTER_XLIB();
+        XStoreName(myDpy, __WindowVal(aWindowId), (char *) __stringVal(simpleString));
+        /* alternative settings for UTF8-Strings */
+        XSetWMName(myDpy, __WindowVal(aWindowId), &titleProperty);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowPid:anIntegerOrNil in:aWindowId
+    "Sets the _NET_WM_PID property for the window.
+     This may be used by the window manager to group windows.
+     If anIntegerOrNil is nil, then PID of currently running
+     Smalltalk is used"
+
+    | propertyID typeId pid |
+
+    propertyID := self atomIDOf: '_NET_WM_PID' create: false.
+    propertyID isNil ifTrue:[ ^ self ].
+    pid := anIntegerOrNil isNil ifTrue:[OperatingSystem getProcessId] ifFalse:[anIntegerOrNil].
+    typeId := self atomIDOf:#'CARDINAL' create:false.
+
+    self setProperty:propertyID type:typeId value:pid for:aWindowId
+
+    "Created: / 04-01-2013 / 16:03:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setWindowShape:aPixmapId in:aWindowId
+    "set the windows shape.
+     Returns false, if the display does not support the
+     X shape extension."
+
+    <context: #return>
+
+    hasShapeExtension ifFalse:[^ self].
+
+%{
+
+#ifdef SHAPE
+    Pixmap shapeBitmap;
+
+    if (__isExternalAddress(aPixmapId))
+        shapeBitmap = __PixmapVal(aPixmapId);
+    else
+        shapeBitmap = (Pixmap)0;
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        ENTER_XLIB();
+        XShapeCombineMask(myDpy, __WindowVal(aWindowId), ShapeClip,
+                          0, 0,
+                          shapeBitmap, ShapeSet);
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+#endif
+%}.
+    self primitiveFailedOrClosedConnection
+!
+
+setWindowState:aSymbol in:aWindowId
+    "tell the window type to the window manager.
+     Send a specific message to the WindowManager"
+
+    |netWmWindowStateAtom stateAtom|
+
+    netWmWindowStateAtom := self atomIDOf:#'_NET_WM_WINDOW_STATE' create:false.
+    stateAtom := self atomIDOf:aSymbol create:false.
+
+    (netWmWindowStateAtom notNil and:[stateAtom notNil]) ifTrue:[
+        self
+            sendClientEvent:netWmWindowStateAtom
+            format:32
+            to:(self rootWindowId)
+            propagate:true
+            eventMask:((self eventMaskFor:#substructureNotify) bitOr:(self eventMaskFor:#substructureRedirect))
+            window:aWindowId
+            data1:(self atomIDOf:#'_NET_WM_STATE_ADD' create:false)
+            data2:stateAtom
+            data3:nil
+            data4:1
+            data5:nil.
+    ] ifFalse:[self halt.].
+
+    "
+      |v|
+
+      v := TopView new create.
+      Display setWindowState:#'_NET_WM_WINDOW_STATE_STICKY' in:v id.
+      v open.
+    "
+!
+
+setWindowType:aSymbol in:aWindowId
+    "Tell the window type to the window manager.
+     See Extended Window Manager Hints 1.3,
+     chapter 'Application Window Properties'
+     http://standards.freedesktop.org/wm-spec/1.3/
+
+    JV@2012-05-15: There was some code prior 2012-05-15,
+    but that code does not work anymore and I wonder if it
+    ever worked correctly. I changed it to be
+    EWMH compatible, as this improve UX on modern Linxu
+    machines.
+
+    It also helps to fix super-annoying problem with window autoraiser
+    on X11 in a proper way - window manager should manage top-level
+    window stacking, that's why it is called a 'window manager' :-)
+
+    "
+
+    | nameAtom typeAtom valueAtom |
+
+    self assert:(#(_NET_WM_WINDOW_TYPE_DESKTOP
+                  _NET_WM_WINDOW_TYPE_DOCK
+                  _NET_WM_WINDOW_TYPE_TOOLBAR
+                  _NET_WM_WINDOW_TYPE_MENU
+                  _NET_WM_WINDOW_TYPE_UTILITY
+                  _NET_WM_WINDOW_TYPE_SPLASH
+                  _NET_WM_WINDOW_TYPE_DIALOG
+                  _NET_WM_WINDOW_TYPE_NORMAL) includes: aSymbol).
+
+    nameAtom := self atomIDOf:#'_NET_WM_WINDOW_TYPE' create:false.
+    nameAtom isNil ifTrue:[
+        "/Hmm, no such property, not running under EWMH compliant WM?
+        self breakPoint: #jv.
+        ^self
+    ].
+    "/ Hmm, hmm, no access to XA_ATOM, XA_INTEGER and so on...
+    typeAtom := self atomIDOf:#'ATOM' create:false.
+    typeAtom isNil ifTrue:[
+        self error:'Oops, no ATOM atom'.
+    ].
+    valueAtom := self atomIDOf: aSymbol create:false.
+    valueAtom isNil ifTrue:[
+        "/Hmm, no such property, not running under EWMH compliant WM?
+        self breakPoint: #jv.
+        ^self
+    ].
+
+    self setProperty: nameAtom type: typeAtom value: valueAtom for: aWindowId.
+
+
+"/   Original code that does not work (if ever worked)
+"/
+"/    |netWmWindowTypeAtom typeAtom|
+"/
+"/    netWmWindowTypeAtom := self atomIDOf:#'_NET_WM_WINDOW_TYPE' create:false.
+"/    typeAtom := self atomIDOf:aSymbol create:false.
+"/
+"/    (netWmWindowTypeAtom notNil and:[typeAtom notNil]) ifTrue:[
+"/        self
+"/            sendClientEvent:netWmWindowTypeAtom
+"/            format:32
+"/            to:(self rootWindowId)
+"/            propagate:true
+"/            eventMask:((self eventMaskFor:#substructureNotify) bitOr:(self eventMaskFor:#substructureRedirect))
+"/            window:aWindowId
+"/            data1:typeAtom
+"/            data2:nil
+"/            data3:nil
+"/            data4:nil
+"/            data5:nil.
+"/    ].
+
+    "
+      |v|
+
+      v := TopView new create.
+      Display setWindowType:#'_NET_WM_WINDOW_TYPE_DOCK' in:v id.
+      v open.
+
+      |v|
+
+      v := TopView new create.
+      Display setWindowType:#'_NET_WM_WINDOW_TYPE_UTILITY' in:v id.
+      v open.
+    "
+
+    "Modified (comment): / 15-05-2012 / 10:49:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+unmapWindow:aWindowId
+    "make a window invisible"
+
+    <context: #return>
+%{
+    /*
+     * ignore closed connection
+     */
+    if (! ISCONNECTED) {
+        RETURN ( self );
+    }
+
+    if (__isExternalAddress(aWindowId)) {
+        ENTER_XLIB();
+        XUnmapWindow(myDpy, __WindowVal(aWindowId));
+        LEAVE_XLIB();
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailed
+!
+
+windowIsIconified:aWindowId
+    "return true, if some window is iconified.
+     The passed windowID may be an alien windows id."
+
+    <context: #return>
+%{
+
+    if (ISCONNECTED
+     && __isExternalAddress(aWindowId)) {
+        Atom JunkAtom;
+        int JunkInt;
+        unsigned long WinState,JunkLong;
+        unsigned char *Property;
+        Atom WM_STATE_Atom;
+
+        if (__INST(wmStateAtom) != nil) {
+            WM_STATE_Atom = __AtomVal(__INST(wmStateAtom));
+
+            ENTER_XLIB();
+            XGetWindowProperty(myDpy, __WindowVal(aWindowId),
+                               WM_STATE_Atom,
+                               0L, 2L, False, AnyPropertyType,
+                               &JunkAtom,&JunkInt,&WinState,&JunkLong,
+                               &Property);
+            LEAVE_XLIB();
+            WinState=(unsigned long)(*((long*)Property));
+            if (WinState==3) {
+                RETURN (true);
+            }
+        }
+        RETURN (false);
+    }
+%}.
+    self primitiveFailedOrClosedConnection.
+    ^ false "/ or true or what ?
+! !
+
+!XWorkstation::SelectionFetcher class methodsFor:'documentation'!
+
+documentation
+"
+    This class is responsible for fetching the clipboard.
+    The X11 clipboard is implemented via asynchonous messages.
+
+    For each fetch operation an instance of this class is created.
+    The asynchronous messages are queued and executed in the
+    process that requests the clipboard.
+
+    [author:]
+        Stefan Vogel (stefan@zwerg)
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+
+"
+! !
+
+!XWorkstation::SelectionFetcher class methodsFor:'selections'!
+
+requestSelection:selectionId type:aTargetId onDevice:aDisplay for:aDrawableId
+    ^ self new requestSelection:selectionId type:aTargetId onDevice:aDisplay for:aDrawableId
+! !
+
+!XWorkstation::SelectionFetcher methodsFor:'accessing'!
+
+drawableID
+    ^ drawableID
+!
+
+getSelection
+    "convert the data in buffer to a selection"
+
+    |selection|
+
+    buffer isNil ifTrue:[
+        ^ nil.
+    ].
+
+    targetID == (display atomIDOf:#STRING) ifTrue:[
+        display clipboardEncoding notNil ifTrue:[
+            selection := buffer decodeFrom:display clipboardEncoding
+        ].
+        selection := buffer.
+    ] ifFalse:[targetID == (display atomIDOf:#'UTF8_STRING') ifTrue:[
+"/ Transcript show:'UTF8: '; showCR:buffer storeString.
+        selection := CharacterArray fromUTF8Bytes:buffer
+    ] ifFalse:[targetID == (display atomIDOf:#TEXT) ifTrue:[
+"/ Transcript show:'TEXT: '; showCR:buffer storeString.
+        selection := buffer asString
+    ] ifFalse:[targetID == (display atomIDOf:#'COMPOUND_TEXT') ifTrue:[
+"/ Transcript show:'COMPOUND_TEXT: '; showCR:buffer storeString.
+        selection := buffer asString
+    ]]]].
+
+    selection notNil ifTrue:[
+        (selection endsWith:Character cr) ifTrue:[
+            selection := selection asStringCollection copyWith:''
+        ].
+        ^ selection.
+    ].
+
+    targetID == (display atomIDOf:#'TARGETS') ifTrue:[
+        ^ buffer
+    ].
+    targetID == (display atomIDOf:#'ST_OBJECT') ifTrue:[
+        "require libboss to be loaded"
+        (Smalltalk isClassLibraryLoaded:'libstx_libboss') ifFalse:[
+            'SelectionFetch: cannot decode object (libboss library missing)' errorPrintCR.
+            ^ nil
+        ].
+        ^ (Object
+            readBinaryFrom:(ReadStream on:buffer)
+            onError:[:ex |
+                ('SelectionFetch: error while decoding binary object: ',ex description) errorPrintCR.
+                nil
+            ])
+    ].
+
+    'XWorkstation: unimplemented property targetID: ' infoPrint. (display atomName:targetID) infoPrint.
+    ' buffer:' infoPrint. buffer infoPrintCR.
+    ^ nil
+
+    "Modified: / 23-08-2006 / 15:56:04 / cg"
+! !
+
+!XWorkstation::SelectionFetcher methodsFor:'event handling'!
+
+message:aMessage
+    "got an asynchronous event from the display.
+     Save and wake up waiters"
+
+    aMessage selector == #propertyChange:property:state:time: ifTrue:[
+        (aMessage arguments at:2) ~~ propertyID ifTrue:[
+            "I am only interested in changes of the property used to
+             store the selection"
+            ^ self.
+        ].
+        message notNil ifTrue:[
+            "this should not happen - bad selection holder?"
+            'XWorkstation(error): message overflow: ' errorPrint. display errorPrintCR.
+            ^ self.
+        ].
+    ].
+
+    "we get a propertyChange before the selectionNotify.
+     Since the propertyChange will be ignored anyway (because we are not in incremental mod,
+     a selectionNotify message may overwrite a propertyChange message"
+
+    message := aMessage.
+    sema signal.
+!
+
+propertyChange:aView property:aPropertyId state:stateSymbol time:time
+    "this is a forwarded propretyChange event from XWorkstation"
+
+    |property propertyValue|
+
+    incremental ifFalse:[
+        "ignore property changes until we are in incremental mode"
+        ^ self.
+    ].
+
+    property := display getProperty:propertyID from:drawableID delete:true.
+    propertyValue := property value.
+
+    propertyValue size == 0 ifTrue:[
+        "property with size 0 signals end of transfer"
+        done := true.
+    ] ifFalse:[
+        buffer isNil ifTrue:[
+            targetID := property key.
+            buffer := propertyValue.
+        ] ifFalse:[
+            targetID ~= property key ifTrue:[
+                'XWorkstation(warning): targetID change in incremental select: ' errorPrint. display errorPrintCR.
+            ].
+            buffer := buffer, propertyValue.
+        ].
+    ].
+!
+
+selectionClear:aView selection:selectionId time:time
+    "sent when another X-client has created a selection.
+     This is a very X-specific mechanism."
+!
+
+selectionNotify:aView selection:aSelectionID target:aTargetID property:aPropertyID requestor:requestorID time:time
+    "this is a forwarded selectionNotify event from XWorkstation"
+
+    |property propertyKey atomName|
+
+    aSelectionID ~~ selectionID ifTrue:[
+        "ignore notification that is not for our selection"
+        ^ self.
+    ].
+
+    aPropertyID == 0 ifTrue:[
+        "the selection owner could not convert the selection to our target type"
+        done := true.
+        ^ self.
+    ].
+
+    property := display getProperty:aPropertyID from:drawableID delete:true.
+    property isNil ifTrue:[
+        "the property does not exist in the specified window"
+        done := true.
+        ^ self
+    ].
+
+    propertyKey := property key.
+    propertyKey == aTargetID ifTrue:[
+        "good, the property is consistent with our request.
+         The whole selection is in the property"
+        buffer := property value.
+        done := true.
+    ] ifFalse:[propertyKey == (display atomIDOf:#INCR) ifTrue:[
+        "this is an incremental transfer. Wait for property change"
+        incremental := true.
+    ] ifFalse:[
+        atomName := (display atomName:propertyKey) ? propertyKey.
+        'XWorkstation(error): unexpected targetID (' errorPrint.
+        atomName errorPrint.
+        ') in selectionNotify: ' errorPrint.
+        display errorPrintCR.
+        done := true.
+    ]].
+! !
+
+!XWorkstation::SelectionFetcher methodsFor:'selection actions'!
+
+requestSelection:aSelectionId type:aTargetId onDevice:aDisplay for:aDrawableId
+    "request the selection of type targetId.
+     Wait for next asynchronous message and process it,
+     until done"
+
+    display := aDisplay.
+    drawableID := aDrawableId.
+    selectionID := aSelectionId.
+    propertyID := display atomIDOf:#'VT_SELECTION'.
+    targetID := aTargetId.
+    sema := Semaphore new name:'X11SelectionFetcher'.
+    done := false.
+    incremental := false.
+
+    [
+        |timeout|
+
+        display registerSelectionFetcher:self.
+
+        display
+            requestSelection:aSelectionId
+            type:aTargetId
+            for:drawableID
+            intoProperty:propertyID.
+
+        timeout := display xlibTimeout.
+        [
+            |currentMessage|
+
+            (sema waitWithTimeout:timeout) isNil ifTrue:[
+                "the selection owner didn't respond within reasonable time"
+                'XWorkstation(error): selection owner does not respond:' infoPrint. display infoPrintCR.
+                ^ nil.
+            ].
+            currentMessage := message.
+            message := nil.
+            currentMessage notNil ifTrue:[currentMessage sendTo:self].
+        ] doUntil:[done].
+    ] ensure:[
+        display unregisterSelectionFetcher:self.
+    ].
+
+    ^ self getSelection
+! !
+
+!XWorkstation::SelectionFetcher methodsFor:'testing'!
+
+matchesDrawableId:aDrawableId
+    "return true, if this SelectionFetcher fetches for aDrawableId"
+
+    ^ drawableID = aDrawableId
+! !
+
+!XWorkstation::WindowGroupWindow class methodsFor:'documentation'!
+
+documentation
+"
+    A special window to serve as window group id. This window
+    is newer mapped. This window is used
+    in XWMHints & _NET_WM_LEADER properties to define
+    application window group
+
+    [author:]
+        Jan Vrany <jan.vrany@fit.cvut.cz>
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+        Inter-Client Communication Conventions Manual [http://tronche.com/gui/x/icccm/]
+
+
+"
+! !
+
+!XWorkstation::WindowGroupWindow methodsFor:'testing'!
+
+isICCCWindowGroupWindow
+    ^ true
+! !
+
+!XWorkstation::X11GraphicsContext methodsFor:'displaying'!
+
+displayString:aString x:x y:y opaque:opaque
+    "draw a string - if opaque is false, draw foreground only; otherwise, draw both
+     foreground and background characters.
+     If the coordinates are not integers, an error is triggered."
+
+    <context: #return>
+
+    |displayId|
+
+    device flushIfAppropriate.
+    displayId := device displayIdOrErrorIfBroken.
+
+%{
+#if 0
+    GC gc;
+    Window win;
+    char *cp;
+    int n;
+    OBJ cls;
+#   define NLOCALBUFFER 200
+    XChar2b xlatebuffer[NLOCALBUFFER];
+    int nInstBytes;
+
+    if (displayId != nil
+     && __isExternalAddress(__INST(gcId))
+     && __isExternalAddress(__INST(drawableId))
+     && __isNonNilObject(aString)
+     && __bothSmallInteger(x, y)) {
+	int lMax = __intVal(@global(XWorkstation:MaxStringLength));
+	Display *dpy = __DisplayVal(displayId);
+	gc = __GCVal(__INST(gcId));
+	win = __WindowVal(__INST(drawableId));
 
 	cp = (char *) __stringVal(aString);
 
@@ -4212,8856 +13279,19 @@
 	}
     }
 #undef NLOCALBUFFER
-%}.
-    ^ super displayString:aString x:x y:y in:aDrawableId with:aGCId opaque:opaque
-!
-
-drawBits:givenBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:givenPadding
-	width:imageWidth height:imageHeight
-	x:srcx y:srcy
-	into:aDrawableId
-	x:dstx y:dsty
-	width:w height:h
-	with:aGCId
-
-    "draw a bitImage which has depth id, width iw and height ih into
-     the drawable. draw a region of w/h pixels from srcx/srcy to dstx/dsty.
-     Individual source pixels have bitsPerPixel bits, allowing to draw
-     depth and pixel-units to be different.
-     It has to be checked elsewhere, that the server can do it with the given
-     depth - otherwise, primitive failure will be signalled.
-     Also it is assumed, that the colormap is setup correctly and the
-     colors are allocated - otherwise the colors may be wrong."
-
-    |fmt padding bits wantedPadding|
-
-    padding := givenPadding.
-    bits := givenBits.
-
-    "/ the XF86_VGA16 server seems to report an error when we pass it an
-    "/ 8-bit padded image. (it wants it 32bit padded).
-    "/ as a workaround, repad it here (although, the server and/or Xlib should
-    "/ care for that.
-
-    ((imageDepth == 4) and:[depth == 4]) ifTrue:[
-	fmt := self supportedImageFormatForDepth:4.
-	fmt isNil ifTrue:[
-	    self primitiveFailed. "/ cannot represent this image
-	    ^ nil
-	].
-	wantedPadding := fmt at:#padding.
-	wantedPadding > givenPadding ifTrue:[
-	    bits := self
-			    repadBits:givenBits
-			    width:imageWidth
-			    height:imageHeight
-			    depth:imageDepth
-			    from:givenPadding
-			    to:wantedPadding.
-	    padding := wantedPadding.
-	]
-    ].
-
-
-    operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
-    ].
-    "
-     sorry; I had to separate it into 2 methods, since XPutImage needs
-     an unlimited stack, and thus cannot send primitiveFailed
-    "
-    (self
-	primDrawBits:bits
-	bitsPerPixel:bitsPerPixel
-	depth:imageDepth
-	msb:true
-	padding:padding
-	width:imageWidth height:imageHeight
-	x:srcx y:srcy
-	into:aDrawableId
-	x:dstx y:dsty
-	width:w height:h
-	with:aGCId)
-    ifFalse:[
-	"
-	 also happens, if a segmentation violation occurs in the
-	 XPutImage ...
-	"
-	self primitiveFailedOrClosedConnection
-    ].
-!
-
-fillArcX:x y:y width:width height:height from:startAngle angle:angle
-	       in:aDrawableId with:aGCId
-    "fill an arc. If any coordinate is not integer, an error is triggered.
-     The angles may be floats or integer - they are given in degrees."
-
-    <context: #return>
-
-    operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
-    ].
-%{
-
-    GC gc;
-    Window win;
-    int w, h, angle1, angle2;
-    double f;
-
-    if (__isSmallInteger(startAngle))
-	angle1 = __intVal(startAngle) * 64;
-    else if (__isFloat(startAngle)) {
-	f = __floatVal(startAngle);
-	angle1 = f * 64;
-    } else if (__isShortFloat(startAngle)) {
-	f = __shortFloatVal(startAngle);
-	angle1 = f * 64;
-    } else goto bad;
-
-    if (__isSmallInteger(angle))
-	angle2 = __intVal(angle) * 64;
-    else if (__isFloat(angle)) {
-	f = __floatVal(angle);
-	angle2 = f * 64;
-    } else if (__isShortFloat(angle)) {
-	f = __shortFloatVal(angle);
-	angle2 = f * 64;
-    } else goto bad;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aGCId)
-     && __isExternalAddress(aDrawableId)
-     && __bothSmallInteger(x, y)
-     && __bothSmallInteger(width, height)) {
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-	w = __intVal(width);
-	h = __intVal(height);
-	/*
-	 * need this check here: some servers simply dump core with bad args
-	 */
-	if ((w >= 0) && (h >= 0) && (angle1 >= 0) && (angle2 >= 0)) {
-	    ENTER_XLIB();
-	    XFillArc(myDpy, win, gc, __intVal(x), __intVal(y),
-				   w, h, angle1, angle2);
-	    LEAVE_XLIB();
-	}
-	RETURN ( self );
-    }
-    bad: ;
-%}.
-    "badGC, badDrawable or coordinates not integer
-     or non float angle(s)"
-
-    self primitiveFailedOrClosedConnection
-!
-
-fillPolygon:aPolygon in:aDrawableId with:aGCId
-    "fill a polygon given by its points.
-     If any coordinate is not integer, an error is triggered."
-
-    <context: #return>
-
-    |numberOfPoints|
-
-    operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
-    ].
-    numberOfPoints := aPolygon size.
-%{
-    GC gc;
-    Window win;
-    OBJ point, x, y;
-    int i, num;
-    XPoint *points;
-    XPoint qPoints[100];
-    int mustFree = 0;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aGCId)
-     && __isExternalAddress(aDrawableId)
-     && __isSmallInteger(numberOfPoints)) {
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-	num = __intVal(numberOfPoints);
-	if (num < 3) {
-	    RETURN ( self );
-	}
-	/*
-	 * avoid (slow) malloc, if not many points
-	 */
-	if (num > 100) {
-	    points = (XPoint *) malloc(sizeof(XPoint) * num);
-	    if (! points) goto fail;
-	    mustFree = 1;
-	} else
-	    points = qPoints;
-	for (i=0; i<num; i++) {
-	    point = __AT_(aPolygon, __MKSMALLINT(i+1));
-	    if (! __isPoint(point)) goto fail;
-	    x = _point_X(point);
-	    y = _point_Y(point);
-	    if (! __bothSmallInteger(x, y))
-		goto fail;
-	    points[i].x = __intVal(x);
-	    points[i].y = __intVal(y);
-	}
-	ENTER_XLIB();
-	XFillPolygon(myDpy, win, gc, points, num, Complex, CoordModeOrigin);
-	LEAVE_XLIB();
-	if (mustFree)
-	    free(points);
-	RETURN ( self );
-
-fail: ;
-	if (mustFree)
-	    free(points);
-    }
-%}.
-    "badGC, badDrawable or coordinates not integer"
-    self primitiveFailedOrClosedConnection
-!
-
-fillRectangleX:x y:y width:width height:height in:aDrawableId with:aGCId
-    "fill a rectangle. If any coordinate is not integer, an error is triggered."
-
-    <context: #return>
-
-    operationsUntilFlush notNil ifTrue:[
-	operationsUntilFlush <= 0 ifTrue:[
-	    self flush.
-	] ifFalse:[
-	    operationsUntilFlush := operationsUntilFlush - 1.
-	].
-    ].
-%{
-
-    int w, h;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aGCId)
-     && __isExternalAddress(aDrawableId)
-     && __bothSmallInteger(x, y)
-     && __bothSmallInteger(width, height)) {
-	w = __intVal(width);
-	h = __intVal(height);
-	/*
-	 * need this check here: some servers simply dump core with bad args
-	 */
-	if ((w >= 0) && (h >= 0)) {
-	    ENTER_XLIB();
-	    XFillRectangle(myDpy,
-			   __DrawableVal(aDrawableId), __GCVal(aGCId),
-			   __intVal(x), __intVal(y), w, h);
-	    LEAVE_XLIB();
-	}
-	RETURN ( self );
-    }
-%}.
-    "badGC, badDrawable or coordinates not integer"
-    self primitiveFailedOrClosedConnection
-!
-
-primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth msb:msb masks:maskArray padding:bitPadding
-			     extent:imageExtent sourceOrigin:srcOrg
-			       into:aDrawableId
-		  destinationOrigin:dstOrg extent:dstExtent
-			       with:aGCId
-
-    <context: #return>
-
-    |imageWidth imageHeight rm gm bm srcx srcy dstx dsty w h|
-
-    imageWidth := imageExtent x.
-    imageHeight := imageExtent y.
-    rm := maskArray at:1.
-    gm := maskArray at:2.
-    bm := maskArray at:3.
-    srcx := srcOrg x.
-    srcy := srcOrg y.
-    dstx := dstOrg x.
-    dsty := dstOrg y.
-    w := dstExtent x.
-    h := dstExtent y.
-
-    "since XPutImage may allocate huge amount of stack space
-     (some implementations use alloca), this must run with unlimited stack."
-
-%{  /* UNLIMITEDSTACK */
-
-    /*
-     * need unlimited stack, since some Xlibs do a huge alloca in
-     * XPutImage
-     */
-    GC gc;
-    Window win;
-    XImage image;
-    int imgWdth;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aGCId)
-     && __isExternalAddress(aDrawableId)
-     && __bothSmallInteger(srcx, srcy)
-     && __bothSmallInteger(dstx, dsty)
-     && __bothSmallInteger(w, h)
-     && __bothSmallInteger(imageWidth, imageHeight)
-     && __bothSmallInteger(imageDepth, bitsPerPixel)
-     && __isSmallInteger(bitPadding)
-     && __bothSmallInteger(rm, gm)
-     && __isSmallInteger(bm)
-     && __isByteArrayLike(imageBits)) {
-	Display *dpy = myDpy;
-	int pad = __intVal(bitPadding);
-
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-	if (! gc || !win)
-	    goto fail;
-#ifdef ARGDEBUG
-	console_printf("args ok\n");
-#endif
-	image.data = (char *)__ByteArrayInstPtr(imageBits)->ba_element;
-	image.width = imgWdth = __intVal(imageWidth);
-	image.height = __intVal(imageHeight);
-	image.xoffset = 0;
-	image.format = ZPixmap;
-	image.byte_order = (msb == true) ? MSBFirst : LSBFirst;
-	image.bitmap_unit = 8;
-	image.bitmap_bit_order = MSBFirst;
-	image.bitmap_pad = pad;
-	image.depth = __intVal(imageDepth);
-	image.bits_per_pixel = __intVal(bitsPerPixel);
-	image.red_mask = __intVal(rm);
-	image.green_mask = __intVal(gm);
-	image.blue_mask = __intVal(bm);
-
-	image.bytes_per_line = ((((imgWdth * image.bits_per_pixel) + (pad-1)) / pad) * pad) / 8;
-
-	switch (image.bits_per_pixel) {
-	    case 1:
-	    case 2:
-	    case 4:
-	    case 8:
-	    case 16:
-	    case 24:
-	    case 32:
-		break;
-
-	    default:
-#ifdef ARGDEBUG
-		console_printf("bits_per_pixel=%d\n",image.bits_per_pixel);
-#endif
-		goto fail;
-	}
-
-	/* ENTER_XLIB(); */
-	XPutImage(dpy, win, gc, &image, __intVal(srcx), __intVal(srcy),
-					__intVal(dstx), __intVal(dsty),
-					__intVal(w), __intVal(h));
-	/* LEAVE_XLIB(); */
-
-	RETURN ( true );
-    }
-#ifdef ARGDEBUG
-    if (!! __isExternalAddress(aGCId)) console_printf("GC\n");
-    if (!! __isExternalAddress(aDrawableId)) console_printf("aDrawableId\n");
-    if (!! __isSmallInteger(srcx)) console_printf("srcx\n");
-    if (!! __isSmallInteger(srcy)) console_printf("srcy\n");
-    if (!! __isSmallInteger(dstx)) console_printf("dstx\n");
-    if (!! __isSmallInteger(dsty)) console_printf("dsty\n");
-    if (!! __isSmallInteger(w)) console_printf("w\n");
-    if (!! __isSmallInteger(h)) console_printf("h\n");
-    if (!! __isSmallInteger(imageWidth)) console_printf("imageWidth\n");
-    if (!! __isSmallInteger(imageHeight)) console_printf("imageHeight\n");
-    if (!! __isSmallInteger(imageDepth)) console_printf("imageDepth\n");
-    if (!! __isSmallInteger(bitsPerPixel)) console_printf("bitsPerPixel\n");
-    if (!! __isByteArrayLike(imageBits)) console_printf("imageBits\n");
-#endif
-
-fail: ;
-%}
-.
-    ^ false
-!
-
-primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth msb:msb padding:bitPadding
-			      width:imageWidth height:imageHeight
-				  x:srcx y:srcy
-			       into:aDrawableId
-				  x:dstx y:dsty
-			      width:w height:h
-			       with:aGCId
-
-    <context: #return>
-
-    "since XPutImage may allocate huge amount of stack space
-     (some implementations use alloca), this must run with unlimited stack."
-
-%{  /* UNLIMITEDSTACK */
-
-    /*
-     * need unlimited stack, since some Xlibs do a huge alloca in
-     * XPutImage
-     */
-    GC gc;
-    Window win;
-    XImage image;
-    int imgWdth;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aGCId)
-     && __isExternalAddress(aDrawableId)
-     && __bothSmallInteger(srcx, srcy)
-     && __bothSmallInteger(dstx, dsty)
-     && __bothSmallInteger(w, h)
-     && __bothSmallInteger(imageWidth, imageHeight)
-     && __bothSmallInteger(imageDepth, bitsPerPixel)
-     && __isSmallInteger(bitPadding)
-     && __isByteArrayLike(imageBits)) {
-	Display *dpy = myDpy;
-	int pad = __intVal(bitPadding);
-
-	gc = __GCVal(aGCId);
-	win = __WindowVal(aDrawableId);
-	if (! gc || !win)
-	    goto fail;
-#ifdef ARGDEBUG
-	console_printf("args ok\n");
-#endif
-	image.data = (char *)__ByteArrayInstPtr(imageBits)->ba_element;
-	image.width = imgWdth = __intVal(imageWidth);
-	image.height = __intVal(imageHeight);
-	image.xoffset = 0;
-	image.format = ZPixmap;
-	image.byte_order = (msb == true) ? MSBFirst : LSBFirst;
-	image.bitmap_unit = 8;
-	image.bitmap_bit_order = MSBFirst;
-	image.bitmap_pad = pad;
-	image.depth = __intVal(imageDepth);
-	image.bits_per_pixel = __intVal(bitsPerPixel);
-
-	/*
-	image.bytes_per_line = ((((imgWdth * image.depth) + (pad-1)) / pad) * pad) / 8;
-	*/
-	image.bytes_per_line = ((((imgWdth * image.bits_per_pixel) + (pad-1)) / pad) * pad) / 8;
-
-	switch (image.bits_per_pixel) {
-	    case 1:
-	    case 2:
-	    case 4:
-	    case 8:
-	    case 16:
-	    case 24:
-	    case 32:
-		break;
-
-	    default:
-#ifdef ARGDEBUG
-		console_printf("bits_per_pixel=%d\n",image.bits_per_pixel);
-#endif
-		goto fail;
-	}
-
-	image.red_mask = 0xFFFF;
-	image.green_mask = 0xFFFF;
-	image.blue_mask = 0xFFFF;
-
-	/* ENTER_XLIB(); */
-	XPutImage(dpy, win, gc, &image, __intVal(srcx), __intVal(srcy),
-					__intVal(dstx), __intVal(dsty),
-					__intVal(w), __intVal(h));
-	/* LEAVE_XLIB(); */
-
-	RETURN ( true );
-    }
-#ifdef ARGDEBUG
-    if (!! __isExternalAddress(aGCId)) console_printf("GC\n");
-    if (!! __isExternalAddress(aDrawableId)) console_printf("aDrawableId\n");
-    if (!! __isSmallInteger(srcx)) console_printf("srcx\n");
-    if (!! __isSmallInteger(srcy)) console_printf("srcy\n");
-    if (!! __isSmallInteger(dstx)) console_printf("dstx\n");
-    if (!! __isSmallInteger(dsty)) console_printf("dsty\n");
-    if (!! __isSmallInteger(w)) console_printf("w\n");
-    if (!! __isSmallInteger(h)) console_printf("h\n");
-    if (!! __isSmallInteger(imageWidth)) console_printf("imageWidth\n");
-    if (!! __isSmallInteger(imageHeight)) console_printf("imageHeight\n");
-    if (!! __isSmallInteger(imageDepth)) console_printf("imageDepth\n");
-    if (!! __isSmallInteger(bitsPerPixel)) console_printf("bitsPerPixel\n");
-    if (!! __isByteArrayLike(imageBits)) console_printf("imageBits\n");
-#endif
-
-fail: ;
-%}
-.
-    ^ false
-! !
-
-!XWorkstation methodsFor:'event forwarding'!
-
-buttonMotion:view state:state x:x y:y rootX:rX rootY:rY time:time
-    "forward a buttonMotion event for some view"
-
-    lastEventTime := time.
-    self buttonMotion:state x:x y:y view:view
-!
-
-buttonPress:view button:button state:state x:x y:y rootX:rX rootY:rY time:time
-    "forward a buttonPress event for some view"
-
-    |logicalButton|
-
-    lastEventTime := time.
-    altDown := state bitTest:altModifierMask.
-    metaDown := state bitTest:metaModifierMask.
-    shiftDown := state bitTest:(self shiftModifierMask).
-    ctrlDown := state bitTest:(self ctrlModifierMask).
-
-    eventRootX := rX.
-    eventRootY := rY.
-
-    "/ physical to logical button translation
-    logicalButton := buttonTranslation at:button ifAbsent:button.
-
-    "/ special for mouse-wheel implementation
-    (logicalButton == #wheelFwd or:[logicalButton == #wheelBwd]) ifTrue:[
-      self mouseWheelMotion:state x:x y:y amount:(logicalButton == #wheelFwd ifTrue:[10] ifFalse:[-10]) deltaTime:10 view:view.
-      ^ self.
-    ].
-
-    logicalButton isInteger ifTrue:[
-	buttonsPressed := buttonsPressed bitOr:(1 bitShift:logicalButton-1).
-    ].
-
-    (multiClickTimeDelta notNil and:[lastButtonPressTime notNil]) ifTrue:[
-	time < (lastButtonPressTime + multiClickTimeDelta) ifTrue:[
-	    lastButtonPressTime := time.
-	    self buttonMultiPress:logicalButton x:x y:y view:view.
-	    ^ self.
-	].
-    ].
-    lastButtonPressTime := time.
-
-    view isNil ifTrue:[
-	"/ event arrived, after I destroyed it myself
-	^ self
-    ].
-    logicalButton == 1 ifTrue:[
-	activateOnClick == true ifTrue:[
-	    "/ dont raise above an active popup view.
-	    (activeKeyboardGrab isNil and:[activePointerGrab isNil]) ifTrue:[
-		view topView raise.
-	    ]
-	].
-    ].
-    super buttonPress:logicalButton x:x y:y view:view
-!
-
-buttonRelease:view button:button state:state x:x y:y rootX:rX rootY:rY time:time
-    "forward a buttonPress event for some view"
-
-    |logicalButton|
-
-    lastEventTime := time.
-    altDown := state bitTest:altModifierMask.
-    metaDown := state bitTest:metaModifierMask.
-    shiftDown := state bitTest:(self shiftModifierMask).
-    ctrlDown := state bitTest:(self ctrlModifierMask).
-
-    eventRootX := rX.
-    eventRootY := rY.
-
-    "/ physical to logical button translation
-    logicalButton := buttonTranslation at:button ifAbsent:button.
-
-    "/ special for HPs mouse-wheel implementation
-    (logicalButton == #wheelFwd or:[logicalButton == #wheelBwd]) ifTrue:[
-      ^ self
-    ].
-
-    logicalButton isInteger ifTrue:[
-	buttonsPressed := buttonsPressed bitClear:(1 bitShift:logicalButton-1).
-    ].
-    self buttonRelease:logicalButton x:x y:y view:view
-!
-
-clientMessage:targetView type:typeAtom format:format data:data
-    |sensor|
-
-    targetView isNil ifTrue:[
-	"targetView is gone? Anyway, cannot do anything with this event..."
-	^ self.
-    ].
-
-    "DND drag&drop protocol"
-    (format == 32 and:[typeAtom == (self atomIDOf:#DndProtocol)]) ifTrue:[
-	self dndMessage:nil data:data view:targetView.
-	^ self.
-    ].
-
-    sensor := targetView sensor.
-    "not posted, if there is no sensor ..."
-    sensor notNil ifTrue:[
-	sensor clientMessage:typeAtom format:format eventData:data view:targetView
-    ].
-
-    "Created: 4.4.1997 / 17:49:26 / cg"
-!
-
-configure:view x:x y:y width:w height:h above:above
-    "forward a size-change event for some view"
-
-    self configureX:x y:y width:w height:h view:view.
-    above notNil ifTrue:[
-	|aboveView|
-	aboveView := self viewFromId:above.
-	aboveView notNil ifTrue:[
-	    "view is now on the top of the window stack"
-	    self coveredBy:view view:aboveView.
-	].
-     ].
-!
-
-createWindow:view x:x y:y width:w height:h
-
-    view isNil ifTrue:[
-	"/ event arrived, after I destroyed it myself
-	^ self
-    ].
-    view sensor createWindow:view x:x y:y width:w height:h
-
-    "Created: / 30-05-2011 / 16:05:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 30-05-2011 / 19:00:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-dndMessage:event data:data view:targetView
-    "handle a drag&drop protocol message"
-
-    |sensor property dropType dropValue names i1 i2 propertyType|
-
-    dropType := data doubleWordAt:1.
-
-    "/ see def's in DragAndDropTypes.h
-    dropType := (self dndDropTypes) at:dropType+1 ifAbsent:#DndNotDnd.
-
-    property := self
-	getProperty:(self atomIDOf:#DndSelection)
-	from:rootId
-	delete:false.
-
-    propertyType := property key.
-    dropValue := property value.
-
-    "/ preconvert into a collection
-    "/ of fileNames, string or byteArray
-    "/ Notice: we do not yet convert into dropObjects
-    "/ here, to allow arbitrary data to be handled by
-    "/ redefined dropMessage methods in applications.
-    "/ Conversion is done for some well known types
-    "/ in the default dropMessage handling of SimpleView.
-
-    dropType == #DndFiles ifTrue:[
-	"/ actually, a list of fileNames
-	propertyType ~~ stringAtom ifTrue:[
-	    'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
-	    ^ self
-	].
-
-	names := OrderedCollection new.
-	i1 := 1.
-	[i1 ~~ 0] whileTrue:[
-	    i2 := dropValue indexOf:(Character value:0) startingAt:i1.
-	    i2 ~~ 0 ifTrue:[
-		names add:(dropValue copyFrom:i1 to:(i2-1)).
-		i1 := i2 + 1.
-	    ] ifFalse:[
-		i1 := i2
-	    ].
-	].
-	dropValue := names.
-	dropValue := dropValue collect:[:nm | nm asFilename].
-	dropType := #files.
-    ] ifFalse:[ (dropType == #DndFile) ifTrue:[
-	propertyType ~~ stringAtom ifTrue:[
-	    'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
-	    ^ self
-	].
-	dropValue := dropValue asFilename.
-	dropType := #file.
-    ] ifFalse:[ (dropType == #DndDir) ifTrue:[
-	propertyType ~~ stringAtom ifTrue:[
-	    'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
-	    ^ self
-	].
-	dropValue := dropValue asFilename.
-	dropType := #directory.
-    ] ifFalse:[ (dropType == #DndText) ifTrue:[
-	propertyType ~~ stringAtom ifTrue:[
-	    'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
-	    ^ self
-	].
-	dropType := #text.
-    ] ifFalse:[ (dropType == #DndExe) ifTrue:[
-	propertyType ~~ stringAtom ifTrue:[
-	    'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
-	    ^ self
-	].
-	dropType := #executable.
-    ] ifFalse:[ (dropType == #DndLink) ifTrue:[
-	propertyType ~~ stringAtom ifTrue:[
-	    'XWorkstation [info]: expected a string propertyValue in drop' infoPrintCR.
-	    ^ self
-	].
-	dropType := #link.
-    ] ifFalse:[ (dropType == #DndRawData) ifTrue:[
-	dropType := #rawData.
-    ] ifFalse:[
-	'XWorkstation [info]: unsupported dropType: ' infoPrint. dropType infoPrintCR.
-	'XWorkstation [info]: data: ' infoPrint. dropValue infoPrintCR.
-	dropType := #unknown.
-    ]]]]]]].
-
-    sensor := targetView sensor.
-    "not posted, if there is no sensor ..."
-    sensor notNil ifTrue:[
-	sensor dropMessage:dropType data:dropValue view:targetView position:nil handle:nil
-    ].
-
-    "Created: 4.4.1997 / 17:59:37 / cg"
-!
-
-expose:view x:x y:y width:w height:h count:count
-    "forward an expose event for some view"
-
-    self exposeX:x y:y width:w height:h view:view.
-
-
-
-
-!
-
-focusIn:view mode:mode detail:detail
-    "a view got the keyboard focus"
-
-    mode ~~ 1 "NotifyGrab" ifTrue:[
-	"mode NotifyGrab is set for pseudo-focus-changes, when a view grabs the keyboard"
-	self focusInView:view
-    ].
-!
-
-focusOut:view mode:mode detail:detail
-    "a view lost the keyboard focus"
-
-    mode ~~ 1 "NotifyGrab" ifTrue:[
-	"mode NotifyGrab is set for pseudo-focus-changes, when a view grabs the keyboard"
-	self focusOutView:view
-    ].
-!
-
-graphicsExpose:view x:x y:y width:w height:h count:count
-    "forward a graphics-expose event for some view"
-
-    self graphicsExposeX:x y:y width:w height:h final:(count==0) view:view
-
-
-
-
-!
-
-keyPress:view key:key code:keyCode state:state x:x y:y rootX:rX rootY:rY time:time
-    "forward a key-press event for some view"
-
-    |commonKey|
-
-    lastEventTime := time.
-    altDown := state bitTest:altModifierMask.
-    metaDown := state bitTest:metaModifierMask.
-    shiftDown := state bitTest:(self shiftModifierMask).
-    ctrlDown := state bitTest:(self ctrlModifierMask).
-    key isNil ifTrue:[
-	"/ happens sometimes on some systems
-	"/ (alt-graph on sun has no keysym)
-	^ self
-    ].
-    eventRootX := rX.
-    eventRootY := rY.
-
-    "very low-level mapping of X11 event symbols to common ST/X event symbols"
-    commonKey := rawKeySymTranslation at:key ifAbsent:key.
-
-    self keyPress:commonKey x:x y:y view:view.
-!
-
-keyRelease:view key:key code:keyCode state:state x:x y:y rootX:rX rootY:rY time:time
-    "forward a key-release event for some view"
-
-    |commonKey|
-
-    lastEventTime := time.
-    altDown := state bitTest:altModifierMask.
-    metaDown := state bitTest:metaModifierMask.
-    shiftDown := state bitTest:(self shiftModifierMask).
-    ctrlDown := state bitTest:(self ctrlModifierMask).
-
-    key isNil ifTrue:[
-	"/ happens sometimes on some systems
-	"/ (alt-graph on sun has no keysym)
-	^ self
-    ].
-    eventRootX := rX.
-    eventRootY := rY.
-
-    "very low-level mapping of X11 event symbols to common ST/X event symbols"
-    commonKey := rawKeySymTranslation at:key ifAbsent:key.
-
-    self keyRelease:commonKey x:x y:y view:view.
-!
-
-mappingNotify:view request:what event:eB
-    "One of Keyboard-, Modifier- or PointerMap has changed, probably by xmodmap.
-     Tell xlib about the fact."
-
-    (what == #mappingKeyboard or:[what == #mappingModifier]) ifTrue:[
-	self refreshKeyboardMapping:eB.
-	"Maybe some of our modifiers have been changed"
-	self initializeModifierMappings.
-    ].
-
-!
-
-pointerEnter:view x:x y:y rootX:rX rootY:rY state:state mode:mode detail:detail time:time
-    "forward a pointer enter event for some view"
-
-    lastEventTime := time.
-    altDown := state bitTest:altModifierMask.
-    metaDown := state bitTest:metaModifierMask.
-    shiftDown := state bitTest:(self shiftModifierMask).
-    ctrlDown := state bitTest:(self ctrlModifierMask).
-
-    eventRootX := rX.
-    eventRootY := rY.
-    self pointerEnter:state x:x y:y view:view
-!
-
-pointerLeave:view x:x y:y rootX:rX rootY:rY state:state mode:mode detail:detail time:time
-    "forward a pointer leave event for some view"
-
-    lastEventTime := time.
-    altDown := state bitTest:altModifierMask.
-    metaDown := state bitTest:metaModifierMask.
-    shiftDown := state bitTest:(self shiftModifierMask).
-    ctrlDown := state bitTest:(self ctrlModifierMask).
-
-    eventRootX := rX.
-    eventRootY := rY.
-    self pointerLeave:state view:view
-!
-
-propertyChange:aView property:propertyId state:aSymbol time:time
-    "sent when an X property changes.
-     This is a very X-specific mechanism."
-
-    |selectionFetcher|
-
-    lastEventTime := time.
-    aView isNil ifTrue:[
-	"event arrived, after aView has been destroyed"
-	^ self
-    ].
-
-"/    'propertyChange ' infoPrint. (self atomName:propertyId) print. ': ' print. aSymbol printCR.
-"/    aView propertyChange:atom state:aSymbol.
-
-    "JV@2011-01-06: Forward this event to views, they may
-     be interested (for now, only XEmbedSiteView is)"
-
-    aView sensor propertyChange:aView property:propertyId state:aSymbol time:time.
-
-    aSymbol ~~ #newValue ifTrue:[
-	"I am not interested in delete notifications"
-	^ self.
-    ].
-    selectionFetcher := self findSelectionFetcher:aView id.
-    selectionFetcher notNil ifTrue:[
-	selectionFetcher message:thisContext message.
-    ].
-
-    "Modified: / 01-06-2011 / 13:40:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-selectionClear:aView selection:selectionID time:time
-    "sent when another X-client has created a selection.
-     This is a very X-specific mechanism."
-
-    |selectionFetcher|
-
-    lastEventTime := time.
-
-    selectionHandlers notNil ifTrue:[
-	selectionHandlers do:[:eachHandler |
-	    eachHandler selectionClear:selectionID
-	]
-    ].
-
-    aView isNil ifTrue:[
-	"event arrived, after aView has been destroyed"
-	^ self
-    ].
-    selectionFetcher := self findSelectionFetcher:aView id.
-    selectionFetcher notNil ifTrue:[
-	selectionFetcher message:thisContext message.
-    ].
-!
-
-selectionNotify:aView selection:selectionID target:targetID property:propertyID requestor:requestorID time:time
-    "This event is sent by the selection owner as a response to our request for a selection.
-     This is a very X-specific mechanism."
-
-    |selectionFetcher|
-
-"/    Transcript show:'seletionNotify selID:'.
-"/    Transcript show:selectionID; show:' ('; show:(self atomName:selectionID); show:') '.
-"/    Transcript show:' targetID:'.
-"/    Transcript show:targetID; show:' ('; show:(self atomName:targetID); show:') '.
-"/    Transcript show:' propertyID:'.
-"/    Transcript show:propertyID; show:' ('; show:(self atomName:propertyID); show:') '.
-"/    Transcript showCR:''.
-"/    Transcript endEntry.
-
-    lastEventTime := time.
-
-    aView isNil ifTrue:[
-	"event arrived, after aView has been destroyed"
-	^ self
-    ].
-    selectionFetcher := self findSelectionFetcher:aView id.
-    selectionFetcher notNil ifTrue:[
-	selectionFetcher message:thisContext message.
-    ].
-!
-
-selectionRequest:aView requestor:requestorID selection:selectionID target:targetID property:propertyID time:time
-    "sent by some other X-client to ask for the selection.
-     This is a very X-specific mechanism."
-
-    |selection property bufferGetSelector responseTargetID selectionTime|
-
-"/'Selection: ' print. (self atomName:selectionID) printCR. ' TargetId: ' print. (self atomName:targetID) printCR.
-"/' Property: ' print. (self atomName:propertyID) printCR. ' Requestor: ' print. requestorID printCR.
-
-    lastEventTime := time.
-
-    "JV@2012-03-27: Support both PRIMARY and CLIPBOARD selections"
-    selectionID == primaryAtom ifTrue:[
-	bufferGetSelector := #getPrimaryBuffer.
-	selectionTime := primarySelectionTime.
-    ] ifFalse:[
-	bufferGetSelector := #getCopyBuffer.
-	selectionTime := clipboardSelectionTime.
-    ].
-
-    (targetID == (self atomIDOf:#TIMESTAMP)) ifTrue:[
-	"the other view wants to know when we acquired ownership of the selection"
-	responseTargetID := self atomIDOf:#INTEGER.
-	selection := selectionTime.
-    ] ifFalse:[(targetID == (self atomIDOf:#TARGETS)) ifTrue:[
-	"the other view wants to know which targets we support"
-	responseTargetID := self atomIDOf:#ATOM.
-	selection := self supportedTargetAtoms.
-    ] ifFalse:[
-	selection := self selectionBuffer:bufferGetSelector as:targetID.
-	responseTargetID := selection key.
-	selection := selection value.
-    ]].
-
-"/'Send selection: ' print. selection printCR.
-
-    property := propertyID.
-
-    selection isNil ifTrue:[
-	"sending property None tells the client,
-	 that I could not convert"
-"/        ('XWorkstation: unsupported selection target ', (self atomName:targetID)) errorPrintCR.
-	property := nil.
-	responseTargetID := targetID.
-    ] ifFalse:[
-	property == 0 ifTrue:[
-	    "Support old (obsolete) clients requesting a None property.
-	     Set the propertyID to the targetID"
-	    property := responseTargetID.
-	].
-	self setProperty:property
-	     type:responseTargetID
-	     value:selection
-	     for:requestorID.
-    ].
-
-    self sendNotifySelection:selectionID
-	 property:property
-	 target:responseTargetID
-	 time:time
-	 to:requestorID.
-
-    "Modified: / 27-03-2012 / 15:22:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-visibilityNotify:aView state:how
-
-    aView notNil ifTrue:[
-	aView visibilityChange:how
-    ]
-! !
-
-!XWorkstation methodsFor:'event forwarding-ignored events'!
-
-circulateNotify:aView place:aSymbol
-    "sent, when the stacking order changes.
-     ignored for now."
-
-!
-
-circulateRequest:aView place:aSymbol
-    "sent, when the stacking order is about to change.
-     ignored for now."
-!
-
-colorMapNotify:aView state:aBoolean
-    "sent, when another colormap is installed.
-     This is a very X-specific mechanism."
-
-    aView isNil ifTrue:[
-	"/ event arrived, after I destroyed it myself
-	^ self
-    ].
-    "/ not yet implemented
-    "/ aView colorMapChange
-!
-
-configureRequest:view x:x y:y width:w height:h above:above detail:detail
-    "ignored for now"
-
-    "/ view configureRequest
-!
-
-gravityNotify:aView x:x y:y
-    "ignored for now"
-
-    "/ aView gravityNotify
-!
-
-keymapNotify:aView
-    "ignore for now"
-
-!
-
-mapRequest:aView
-    "ignored for now"
-
-    "/ aView mapRequest
-!
-
-reparentedView:aView parentId:parentId x:x y:y
-    "ignored for now"
-
-    "/ aView reparented
-!
-
-resizeRequest:aView width:width height:height
-    "ignored for now"
-
-    "/ aView resizeRequest
-! !
-
-!XWorkstation methodsFor:'event handling'!
-
-defaultEventMask
-    "return a mask to enable some events by default."
-
-%{  /* NOCONTEXT */
-    RETURN (__MKSMALLINT( ExposureMask | StructureNotifyMask |
-			 KeyPressMask | KeyReleaseMask |
-			 PointerMotionMask |
-			 EnterWindowMask | LeaveWindowMask |
-			 ButtonPressMask | ButtonMotionMask | ButtonReleaseMask |
-			 PropertyChangeMask ));
-%}
-!
-
-dispatchEvent:evArray
-    |viewId view evType arguments|
-
-    viewId := evArray at:1.
-    viewId notNil ifTrue:[
-	viewId = lastId ifTrue:[
-	    view := lastView
-	] ifFalse:[
-	    view := self viewFromId:viewId
-	].
-    ].
-
-    evType := evArray at:3.
-
-    (self respondsTo:evType) ifTrue:[
-	arguments := evArray copyFrom:3 to:(3 + evType numArgs - 1).
-	arguments at:1 put:view.
-
-	self perform:evType withArguments:arguments.
-	^ true.
-    ].
-'********** unhandled event:' errorPrintCR.
-evType errorPrintCR. (evArray at:2) errorPrintCR.
-'********** see dispatchEvent' errorPrintCR.
-    ^ false
-!
-
-dispatchEventFor:aViewIdOrNil withMask:eventMask
-    "central event handling method:
-     get next event and send appropriate message to the sensor or view.
-     If the argument aViewIdOrNil is nil, events for any view are processed,
-     otherwise only events for the view with given id are processed.
-     If the argument aMask is nonNil, only events for this eventMask are
-     handled.
-     WARNING: this may block to wait for an event - you better check for a
-	      pending event before calling this."
-
-    |eventArray|
-
-    eventArray := Array new:13.
-
-    (self getEventFor:aViewIdOrNil withMask:eventMask into:eventArray) ifTrue:[
-	AbortOperationRequest handle:[:ex |
-	    ex return
-	] do:[
-	    self dispatchEvent:eventArray.
-	]
-    ].
-
-    "Modified: 19.8.1997 / 17:10:42 / cg"
-!
-
-dispatchExposeEventFor:aViewIdOrNil
-    "get next expose event and send appropriate message to the sensor or view.
-     If the argument aViewIdOrNil is nil, events for any view are processed,
-     otherwise only events for the view with given id are processed.
-     WARNING: this may block to wait for an event - you better check for a
-	      pending event before calling this."
-
-    self dispatchEventFor:aViewIdOrNil withMask:(self eventMaskFor:#expose)
-
-    "Modified: 19.8.1997 / 17:10:26 / cg"
-!
-
-dispatchLoop
-    preWaitAction := [self flush].
-    Processor addPreWaitAction:preWaitAction.
-    [
-	super dispatchLoop
-    ] ensure:[
-	Processor removePreWaitAction:preWaitAction.
-	preWaitAction := nil.
-    ].
-!
-
-dispatchPendingEvents
-    "central event handling method for modal operation.
-     (i.e. this is now only used in the modal debugger)
-     Dispatch any pending events; return when no more are pending.
-     This code is somewhat special, since X has a concept of graphic
-     expose events (which are sent after a bitblt). After such a bitblt,
-     we only handle exposes until the graphicsExpose arrives.
-     Other systems may not need such a kludge"
-
-    "interested in exposes only ?"
-
-    |eventArray|
-
-    dispatchingExpose notNil ifTrue:[
-	[self exposeEventPendingFor:dispatchingExpose withSync:false] whileTrue:[
-	    self dispatchExposeEventFor:dispatchingExpose
-	].
-	^ self
-    ].
-
-    [self eventPendingWithSync:false] whileTrue:[
-	eventArray isNil ifTrue:[
-	    eventArray := Array new:13.
-	].
-	(self getEventFor:nil withMask:nil into:eventArray) ifTrue:[
-	    AbortOperationRequest handle:[:ex |
-		ex return
-	    ] do:[
-		self dispatchEvent:eventArray.
-		"/ multi-screen config: give others a chance
-		"/ (needed because we run at high (non-timesliced) prio)
-		Processor yield.
-	    ]
-	].
-    ]
-
-    "Modified: 19.8.1997 / 17:11:18 / cg"
-!
-
-disposeEventsWithMask:aMask for:aWindowIdOrNil
-    "dispose (throw away) specific events. If aWindowId is nil,
-     events matching the mask are thrown away regardless of which
-     view they are for. Otherwise, only matching events for that
-     view are flushed."
-
-    <context: #return>
-%{ /* UNLIMITEDSTACK */
-
-    XEvent ev;
-    Window win;
-
-    if (ISCONNECTED
-     && __isSmallInteger(aMask)) {
-	Display *dpy = myDpy;
-
-	ENTER_XLIB();
-	if (__isExternalAddress(aWindowIdOrNil)) {
-	    win = __WindowVal(aWindowIdOrNil);
-	    while (XCheckWindowEvent(dpy, win, __intVal(aMask), &ev)) ;;
-	} else {
-	    while (XCheckMaskEvent(dpy, __intVal(aMask), &ev)) ;;
-	}
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-eventMaskFor:anEventSymbol
-    "return the eventMask bit-constant corresponding to an event symbol"
-
-%{  /* NOCONTEXT */
-
-    int m = 0;
-
-    if (anEventSymbol == @symbol(keyPress)) m = KeyPressMask;
-    else if (anEventSymbol == @symbol(keyRelease)) m = KeyReleaseMask;
-    else if (anEventSymbol == @symbol(buttonPress)) m = ButtonPressMask;
-    else if (anEventSymbol == @symbol(buttonRelease)) m = ButtonReleaseMask;
-    else if (anEventSymbol == @symbol(buttonMotion)) m = ButtonMotionMask;
-    else if (anEventSymbol == @symbol(pointerMotion)) m = PointerMotionMask;
-    else if (anEventSymbol == @symbol(expose)) m = ExposureMask;
-    else if (anEventSymbol == @symbol(focusChange)) m = FocusChangeMask;
-    else if (anEventSymbol == @symbol(enter)) m = EnterWindowMask;
-    else if (anEventSymbol == @symbol(leave)) m = LeaveWindowMask;
-    else if (anEventSymbol == @symbol(keymapState)) m = KeymapStateMask;
-    else if (anEventSymbol == @symbol(visibilityChange)) m = VisibilityChangeMask;
-    else if (anEventSymbol == @symbol(structureNotify)) m = StructureNotifyMask;
-    else if (anEventSymbol == @symbol(resizeRedirect)) m = ResizeRedirectMask;
-    else if (anEventSymbol == @symbol(propertyChange)) m = PropertyChangeMask;
-    else if (anEventSymbol == @symbol(colormapChange)) m = ColormapChangeMask;
-    else if (anEventSymbol == @symbol(substructureNotify)) m = SubstructureNotifyMask;
-    else if (anEventSymbol == @symbol(substructureRedirect)) m = SubstructureRedirectMask;
-    RETURN (__MKSMALLINT(m));
-%}
-!
-
-eventPending
-    "return true, if any event is pending.
-     This looks for both the internal queue and the display connection."
-
-    "/ ConservativeSync is required for some Xlib implementation,
-    "/ where eventPending returns wrong if we do not flush the buffer.
-    "/ (especially Win32 & Xlib)
-
-    ConservativeSync == true ifTrue:[self sync].
-
-    dispatchingExpose notNil ifTrue:[
-	^ self exposeEventPendingFor:dispatchingExpose withSync:false
-    ].
-    ^ self eventPendingWithSync:false
-
-    "Modified: / 28.4.1999 / 11:08:12 / cg"
-!
-
-eventPending:anEventSymbol for:aWindowIdOrNil
-    "return true, if a specific event is pending"
-
-    ^ self eventsPending:(self eventMaskFor:anEventSymbol) for:aWindowIdOrNil withSync:false
-!
-
-eventPending:anEventMask for:aWindowIdOrNil withSync:doSync
-    "return true, if any of the masked events is pending"
-
-    <context: #return>
-%{  /* UNLIMITEDSTACK */
-
-    XEvent ev;
-    Window win;
-    int thereIsOne;
-    OBJ rslt = false;
-
-    if (ISCONNECTED && __isSmallInteger(anEventMask)) {
-	Display *dpy = myDpy;
-
-	ENTER_XLIB();
-	if (doSync == true) {
-	    XSync(dpy, 0);      /* make certain everything is flushed */
-	}
-	if (__isExternalAddress(aWindowIdOrNil)) {
-	    win = __WindowVal(aWindowIdOrNil);
-	    thereIsOne = XCheckWindowEvent(dpy, win, __intVal(anEventMask), &ev);
-	} else {
-	    thereIsOne = XCheckMaskEvent(dpy, __intVal(anEventMask), &ev);
-	}
-	if (thereIsOne) {
-	    XPutBackEvent(dpy, &ev);
-	    rslt = true;
-	}
-	LEAVE_XLIB();
-    }
-    RETURN ( rslt );
-%}
-!
-
-eventPendingWithSync:doSync
-    "return true, if any event is pending.
-     If doSync is true, do a sync output buffer (i.e. send all to the display and wait until its processed)
-     before checking."
-
-    <context: #return>
-%{  /* UNLIMITEDSTACK */
-    OBJ rslt = false;
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	if (XEventsQueued(dpy, QueuedAlready)) {
-	    RETURN (true);
-	}
-
-	ENTER_XLIB();
-	if (doSync == true) {
-	    XSync(dpy, 0);      /* make certain everything is flushed */
-	}
-	if (XPending(dpy)) {
-	    rslt = true;
-	}
-	LEAVE_XLIB();
-    }
-    RETURN ( rslt );
-%}
-!
-
-eventQueued
-    "return true, if any event is queued"
-
-    dispatchingExpose notNil ifTrue:[
-	^ self exposeEventPendingFor:dispatchingExpose withSync:false
-    ].
-    ^ self eventQueuedAlready
-
-    "Created: 12.12.1995 / 21:43:00 / stefan"
-!
-
-eventQueuedAlready
-    "return true, if any event is queued internally.
-     (i.e. in X's internal event queue, which is both filled by explicit
-      nextEvent calls AND whenever drawing is done and events are pending on
-      the display connection)."
-
-%{  /* UNLIMITEDSTACK */
-    OBJ rslt = false;
-
-    if (ISCONNECTED) {
-	/* ENTER ... LEAVE not needed; XEventsQueued will not block */
-	/* ENTER_XLIB(); */
-	if (XEventsQueued(myDpy, QueuedAlready)) {
-	    rslt = true;
-	}
-	/* LEAVE_XLIB(); */
-    }
-    RETURN ( rslt );
-%}
-!
-
-exposeEventPendingFor:aWindowIdOrNil withSync:doSync
-    "return true, if any expose event is pending for a specific view,
-     or any view (if the arg is nil).
-     This is an X specific, only required after a scroll operation."
-
-    <context: #return>
-
-%{  /* UNLIMITEDSTACK */
-
-    XEvent ev;
-    Window win;
-    int thereIsOne;
-    OBJ rslt = false;
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	ENTER_XLIB();
-	if (doSync == true) {
-	    XSync(dpy, 0);      /* make certain everything is flushed */
-	}
-	if (__isExternalAddress(aWindowIdOrNil)) {
-	    win = __WindowVal(aWindowIdOrNil);
-	    thereIsOne = XCheckWindowEvent(dpy, win, ExposureMask, &ev);
-	} else {
-	    thereIsOne = XCheckMaskEvent(dpy, ExposureMask, &ev);
-	}
-	if (thereIsOne) {
-	    XPutBackEvent(dpy, &ev);
-	    rslt = true;
-	}
-	LEAVE_XLIB();
-    }
-    RETURN ( rslt );
-%}
-!
-
-getEventFor:aViewIdOrNil withMask:eventMask into:anEventArray
-    "read next event if there is one and put events data into anEventArray.
-     If aViewIdOrNil is nil, events for any view are fetched;
-     otherwise only events for that specific view will be fetched.
-     Returns true, if there was an event, false otherwise.
-     This method may block - so you better check for pending events
-     before calling for it.
-
-     The event fields are placed them into anEventArray (must be at least size 13):
-     the fields are:
-	1:      windowID
-	2:      eventType-ID
-	3:      eventTypeSymbol
-
-	4..     args
-
-     Sorry I had to split dispatch into this fetch method and a separate
-     handler method to allow UNLIMITEDSTACK here.
-     (some Xlibs do a big alloca there which cannot be done in
-      #dispatchEvent:, since it dispatches out into ST-methods).
-    "
-
-%{  /* UNLIMITEDSTACK */
-
-    Display *dpy;
-    Window win, wWanted;
-    int evMask, returnValue;
-    XEvent ev;
-    OBJ eB;
-    KeySym keySym;
-    unsigned char buffer[64];
-    int i, nchars;
-    char *keySymString;
-    OBJ arg, sym, t, windowID;
-
-    if (! ISCONNECTED) {
-	RETURN (false);
-    }
-
-    dpy = myDpy;
-
-    ev.type = 0;
-
-    if (__isSmallInteger(eventMask)) {
-	evMask = __intVal(eventMask);
-    } else {
-	evMask = ~0;
-    }
-
-    if (__isExternalAddress(aViewIdOrNil)) {
-	wWanted = __WindowVal(aViewIdOrNil);
-	returnValue = XCheckWindowEvent(dpy, wWanted, evMask, &ev);
-    } else {
-	if (evMask == ~0) {
-	    XNextEvent(dpy, &ev);
-	    returnValue = 1;
-	} else {
-	    returnValue = XCheckMaskEvent(dpy, evMask, &ev);
-	}
-    }
-    if (!returnValue) {
-	/* there is no event */
-	RETURN (false);
-    }
-
-    if (anEventArray == nil) {
-	/* sender is not interested in the event */
-	RETURN(true);
-    }
-
-    if (!__isArray(anEventArray)) {
-	console_fprintf(stderr, "XWorkstation: bad argument [%d]\n", __LINE__);
-	RETURN (false);
-    }
-    if (__arraySize(anEventArray) < 11) {
-	console_fprintf(stderr, "XWorkstation: bad argument [%d]\n", __LINE__);
-	RETURN (false);
-    }
-
-#   define ANYBUTTON   (Button1MotionMask | Button2MotionMask | Button3MotionMask)
-
-#   define ae ((XAnyEvent *)&ev)
-#   define ee ((XExposeEvent *)&ev)
-#   define ke ((XKeyPressedEvent *)&ev)
-#   define be ((XButtonPressedEvent *)&ev)
-#   define ce ((XConfigureEvent *)&ev)
-#   define cr ((XConfigureRequestEvent *)&ev)
-#   define me ((XMotionEvent *)&ev)
-#   define ele ((XCrossingEvent *)&ev)
-#   define de ((XDestroyWindowEvent *)&ev)
-#   define ve ((XVisibilityEvent *)&ev)
-#   define fe ((XFocusChangeEvent *)&ev)
-#   define cre ((XCreateWindowEvent *)&ev)
-#   define mape ((XMappingEvent *)&ev)
-#   define gre ((XGravityEvent *)&ev)
-#   define rr ((XResizeRequestEvent *)&ev)
-#   define rpe ((XReparentEvent *)&ev)
-#   define cie ((XCirculateEvent *)&ev)
-#   define pe ((XPropertyEvent *)&ev)
-#   define sce ((XSelectionClearEvent *)&ev)
-#   define cme ((XColormapEvent *)&ev)
-
-    if (((t = __INST(lastId)) != nil)
-	 && __isExternalAddress(t)
-	 && (__WindowVal(t) == ae->window)) {
-	windowID = t;
-    } else {
-	windowID = __MKEXTERNALADDRESS(ae->window);
-    }
-
-    __ArrayInstPtr(anEventArray)->a_element[0] = windowID; __STORE(anEventArray, windowID);
-    __ArrayInstPtr(anEventArray)->a_element[1] = __MKSMALLINT(ev.type);
-
-    switch (ev.type) {
-	case KeyRelease:
-	    sym = @symbol(keyRelease:key:code:state:x:y:rootX:rootY:time:);
-	    goto keyPressAndRelease;
-
-	case KeyPress:
-	    sym = @symbol(keyPress:key:code:state:x:y:rootX:rootY:time:);
-	    /* FALL INTO */
-
-	keyPressAndRelease:
-	    arg = nil;
-	    nchars = XLookupString(ke, (char *)buffer, sizeof(buffer), &keySym, NULL);
-	    if (nchars == 1 && (((buffer[0] >= ' ') && (buffer[0] <= '~'))
-		|| (buffer[0] >= 0x80))) {
-		arg = __MKCHARACTER(buffer[0]);
-//            } else if (nchars > 2) {
-//                arg = __MKSTRING_L(buffer, nchars);
-	    } else {
-		keySymString = XKeysymToString(keySym);
-		if (keySymString) {
-		    arg = __MKSYMBOL(keySymString, 0);
-		}
-	    }
-
-#ifdef IGNORE_UNKNOWN_KEYCODES
-	    if (arg == nil) {
-		/* happens sometimes (alt-graph on sun has no keysym) */
-		RETURN (false);
-	    }
-#endif
-	    __ArrayInstPtr(anEventArray)->a_element[2] = sym;
-
-	    __ArrayInstPtr(anEventArray)->a_element[3] = arg; __STORE(anEventArray, arg);
-	    t = __MKUINT(ke->keycode); __ArrayInstPtr(anEventArray)->a_element[4] = t; __STORE(anEventArray, t);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(ke->state);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(ke->x);
-	    __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(ke->y);
-	    __ArrayInstPtr(anEventArray)->a_element[8] = __mkSmallInteger(ke->x_root);
-	    __ArrayInstPtr(anEventArray)->a_element[9] = __mkSmallInteger(ke->y_root);
-	    t = __MKUINT(ke->time); __ArrayInstPtr(anEventArray)->a_element[10] = t; __STORE(anEventArray, t);
-	    break;
-
-	case ButtonPress:
-	    sym = @symbol(buttonPress:button:state:x:y:rootX:rootY:time:);
-	    goto buttonPressAndRelease;
-
-	case ButtonRelease:
-	    sym = @symbol(buttonRelease:button:state:x:y:rootX:rootY:time:);
-	    /* fall into */
-
-	buttonPressAndRelease:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = sym;
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(be->button);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(ke->state);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(be->x);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(be->y);
-	    __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(be->x_root);
-	    __ArrayInstPtr(anEventArray)->a_element[8] = __mkSmallInteger(be->y_root);
-	    t = __MKUINT(be->time); __ArrayInstPtr(anEventArray)->a_element[9] = t; __STORE(anEventArray, t);
-	    break;
-
-	case MotionNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(buttonMotion:state:x:y:rootX:rootY:time:);
-
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(me->state);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(me->x);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(me->y);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(me->x_root);
-	    __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(me->y_root);
-	    t = __MKUINT(me->time); __ArrayInstPtr(anEventArray)->a_element[8] = t; __STORE(anEventArray, t);
-	    break;
-
-	case FocusIn:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(focusIn:mode:detail:);
-	    goto focusInOut;
-
-	case FocusOut:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(focusOut:mode:detail:);
-	    /* fall into */
-
-	focusInOut:
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(fe->mode);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(fe->detail);
-	    break;
-
-	case EnterNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(pointerEnter:x:y:rootX:rootY:state:mode:detail:time:);
-	    goto enterLeave;
-
-	case LeaveNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(pointerLeave:x:y:rootX:rootY:state:mode:detail:time:);
-	    /* fall into */
-
-	enterLeave:
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(ele->x);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(ele->y);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(ele->x_root);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(ele->y_root);
-	    __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(ele->state);
-	    __ArrayInstPtr(anEventArray)->a_element[8] = __mkSmallInteger(ele->mode);
-	    __ArrayInstPtr(anEventArray)->a_element[9] = __mkSmallInteger(ele->detail);
-	    t = __MKUINT(ele->time); __ArrayInstPtr(anEventArray)->a_element[10] = t; __STORE(anEventArray, t);
-	    break;
-
-	case Expose:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(expose:x:y:width:height:count:);
-	    goto expose;
-
-	case GraphicsExpose:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(graphicsExpose:x:y:width:height:count:);
-	    /* fall into */
-
-	expose:
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(ee->x);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(ee->y);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(ee->width);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(ee->height);
-	    __ArrayInstPtr(anEventArray)->a_element[7] = __mkSmallInteger(ee->count);
-	    break;
-
-	case NoExpose:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(noExposeView:);
-	    break;
-
-	case VisibilityNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(visibilityNotify:state:);
-	    switch (ve->state) {
-		case VisibilityUnobscured:
-		    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(unobscured);
-		    break;
-		case VisibilityPartiallyObscured:
-		    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(partiallyObscured);
-		    break;
-		case VisibilityFullyObscured:
-		    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(fullyObscured);
-		    break;
-		default:
-		    __ArrayInstPtr(anEventArray)->a_element[3] = __MKSMALLINT(ve->state);
-		    break;
-	    }
-	    break;
-
-	case CreateNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(createWindow:x:y:width:height:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(cre->x);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(cre->y);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(cre->width);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(cre->height);
-	    break;
-
-	case DestroyNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(destroyedView:);
-	    break;
-
-	case UnmapNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(unmappedView:);
-	    break;
-
-	case MapNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(mappedView:);
-	    break;
-
-	case ConfigureNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(configure:x:y:width:height:above:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(ce->x);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(ce->y);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(ce->width);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(ce->height);
-	    __ArrayInstPtr(anEventArray)->a_element[7] = nil;
-	    if (ce->above != None) {
-		t = __MKEXTERNALADDRESS(ce->above); __ArrayInstPtr(anEventArray)->a_element[7] = t; __STORE(anEventArray, t);
-	    }
-	    break;
-
-	case GravityNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(gravityNotify:x:y:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(gre->x);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(gre->y);
-	    break;
-
-	case ResizeRequest:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(resizeRequest:width:height:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(rr->width);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(rr->height);
-	    break;
-
-	case ConfigureRequest:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(configureRequest:x:y:width:height:above:detail:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __mkSmallInteger(cr->x);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(cr->y);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(cr->width);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __mkSmallInteger(cr->height);
-	    __ArrayInstPtr(anEventArray)->a_element[7] = nil;
-	    if (cr->above != None) {
-		t = __MKEXTERNALADDRESS(cr->above); __ArrayInstPtr(anEventArray)->a_element[7] = t; __STORE(anEventArray, t);
-	    }
-	    switch (cr->detail) {
-		case Above:
-		    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(above);
-		    break;
-		case Below:
-		    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(below);
-		    break;
-		case TopIf:
-		    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(topIf);
-		    break;
-		case BottomIf:
-		    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(bottomIf);
-		    break;
-		case Opposite:
-		    __ArrayInstPtr(anEventArray)->a_element[8] = @symbol(opposite);
-		    break;
-		default:
-		    __ArrayInstPtr(anEventArray)->a_element[8] = __MKSMALLINT(cr->detail);
-		    break;
-	    }
-	    break;
-
-	case CirculateNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(circulateNotify:place:);
-	    goto circulate;
-
-	case CirculateRequest:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(circulateRequest:place:);
-	    /* fall into */
-	circulate:
-	    switch (cie->place) {
-		case PlaceOnTop:
-		    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(placeOnTop);
-		    break;
-		case PlaceOnBottom:
-		    __ArrayInstPtr(anEventArray)->a_element[3] = @symbol(placeOnBottom);
-		    break;
-		default:
-		    __ArrayInstPtr(anEventArray)->a_element[3] = __MKSMALLINT(cie->place);
-		    break;
-	    }
-	    break;
-
-	case PropertyNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(propertyChange:property:state:time:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __MKATOMOBJ(pe->atom);
-	    switch (pe->state) {
-		case PropertyNewValue:
-		    __ArrayInstPtr(anEventArray)->a_element[4] = @symbol(newValue);
-		    break;
-		case PropertyDelete:
-		    __ArrayInstPtr(anEventArray)->a_element[4] = @symbol(deleted);
-		    break;
-		default:
-		    __ArrayInstPtr(anEventArray)->a_element[4] = __MKSMALLINT(pe->state);
-		    break;
-	    }
-	    t = __MKUINT(pe->time); __ArrayInstPtr(anEventArray)->a_element[5] = t; __STORE(anEventArray, t);
-	    break;
-
-	case SelectionClear:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(selectionClear:selection:time:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __MKATOMOBJ(sce->selection);
-	    t = __MKUINT(sce->time); __ArrayInstPtr(anEventArray)->a_element[4] = t; __STORE(anEventArray, t);
-	    break;
-
-	case SelectionRequest:
-	    /*
-	     * someone wants the selection
-	     */
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(selectionRequest:requestor:selection:target:property:time:);
-	    t = __MKEXTERNALADDRESS(ev.xselectionrequest.requestor); __ArrayInstPtr(anEventArray)->a_element[3] = t; __STORE(anEventArray, t);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __MKATOMOBJ(ev.xselectionrequest.selection);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __MKATOMOBJ(ev.xselectionrequest.target);
-	    __ArrayInstPtr(anEventArray)->a_element[6] = __MKATOMOBJ(ev.xselectionrequest.property);
-	    t = __MKUINT(ev.xselectionrequest.time); __ArrayInstPtr(anEventArray)->a_element[7] = t; __STORE(anEventArray, t);
-	    break;
-
-	case SelectionNotify:
-	    /*
-	     * returned selection value (answer from SelectionRequest)
-	     */
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(selectionNotify:selection:target:property:requestor:time:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __MKATOMOBJ(ev.xselection.selection);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __MKATOMOBJ(ev.xselection.target);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __MKATOMOBJ(ev.xselection.property);
-	    t = __MKEXTERNALADDRESS(ev.xselection.requestor); __ArrayInstPtr(anEventArray)->a_element[6] = t; __STORE(anEventArray, t);
-	    t = __MKUINT(ev.xselection.time); __ArrayInstPtr(anEventArray)->a_element[7] = t; __STORE(anEventArray, t);
-	    break;
-
-	case ColormapNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(colormapNotify:state:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = cme->state == ColormapInstalled ? true : false;
-	    break;
-
-	case ClientMessage:
-	    if (ev.xclient.message_type == (int) __AtomVal(__INST(protocolsAtom))) {
-		if ((ev.xclient.data.l[0] == (int) __AtomVal(__INST(quitAppAtom)))
-		 || (ev.xclient.data.l[0] == (int) __AtomVal(__INST(deleteWindowAtom)))) {
-		    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(terminateView:);
-		    break;
-		}
-		if (ev.xclient.data.l[0] == (int) __AtomVal(__INST(saveYourselfAtom))) {
-		    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(saveAndTerminateView:);
-		    break;
-		}
-	    }
-	    /*
-	     * any other client message
-	     */
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(clientMessage:type:format:data:);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = __MKATOMOBJ(ev.xclient.message_type);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __MKSMALLINT(ev.xclient.format);
-	    t = __MKBYTEARRAY(&ev.xclient.data, sizeof(ev.xclient.data)); __ArrayInstPtr(anEventArray)->a_element[5] = t; __STORE(anEventArray, t);
-	    break;
-
-	case MappingNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(mappingNotify:request:event:);
-	    switch(mape->request) {
-		case MappingModifier:
-		    arg = @symbol(mappingModifier);
-		    break;
-		case MappingKeyboard:
-		    arg = @symbol(mappingKeyboard);
-		    break;
-		case MappingPointer:
-		    arg = @symbol(mappingPointer);
-		    break;
-		default:
-		    arg = __MKSMALLINT(mape->request);
-		    break;
-	    }
-	    __ArrayInstPtr(anEventArray)->a_element[3] = arg;
-	    t = __MKBYTEARRAY(&ev, sizeof(*mape)); __ArrayInstPtr(anEventArray)->a_element[4] = t;
-	    __STORE(anEventArray, t);
-	    break;
-
-	case KeymapNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(keymapNotify:);
-	    break;
-
-	case MapRequest:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(mapRequest:);
-	    break;
-
-	case ReparentNotify:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(reparentedView:parentId:x:y:);
-	    t = __MKEXTERNALADDRESS(rpe->parent);
-	    __ArrayInstPtr(anEventArray)->a_element[3] = t; __STORE(anEventArray, t);
-	    __ArrayInstPtr(anEventArray)->a_element[4] = __mkSmallInteger(rpe->x);
-	    __ArrayInstPtr(anEventArray)->a_element[5] = __mkSmallInteger(rpe->y);
-	    break;
-
-	default:
-	    __ArrayInstPtr(anEventArray)->a_element[2] = @symbol(unknownX11Event);
-	    break;
-    }
-#undef ae
-#undef ee
-#undef ke
-#undef be
-#undef ce
-#undef cr
-#undef cre
-#undef cle
-#undef gre
-#undef me
-#undef ewe
-#undef ele
-#undef lwe
-#undef de
-#undef mape
-#undef ve
-#undef fe
-#undef rr
-#undef rpe
-#undef pe
-#undef cie
-#undef sce
-#undef cme
-
-%}.
-
-    ^ true
-!
-
-handleAllEvents
-    "from now on, handle any kind of event"
-
-    dispatchingExpose := nil
-!
-
-handleExposeOnlyFor:aView
-    "from now on, handle expose events only"
-
-    dispatchingExpose := aView id
-!
-
-registerHotKeyForWindow:aDrawableId withId:anId modifiers:aModifier virtualKeyCode:aVirtualKeyCode
-    "Defines a system-wide hot key."
-    <resource: #todo>
-
-    "no-op until implemented"
-
-    ^ false.
-!
-
-setEventMask:aMask in:aWindowId
-    "tell X that we are only interested in events from aMask, which
-     is the bitwise or of the eventMask bits (see 'eventMaskFor:')"
-
-    <context: #return>
-%{
-
-    int mask;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __isSmallInteger(aMask)) {
-	mask = __intVal(aMask);
-
-#ifdef OLD
-	/* these may not be disabled */
-	mask |= ExposureMask | StructureNotifyMask |
-		KeyPressMask | KeyReleaseMask |
-		EnterWindowMask | LeaveWindowMask |
-		ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
-#endif
-
-	ENTER_XLIB();
-	XSelectInput(myDpy, __WindowVal(aWindowId), mask);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-startDispatch
-    "redefined to clear dispatchingExpose, which is a special X feature"
-
-    dispatching ifTrue:[^ self].
-    dispatchingExpose := nil.
-    super startDispatch.
-!
-
-unregisterHotKeyForWindow:aDrawableId withId:anId
-    "Release a system-wide hot key."
-    <resource: #todo>
-
-    "no-op until implemented. Since we never registered anything, the unregister succeeds"
-
-    ^ true.
-! !
-
-!XWorkstation methodsFor:'event handling-old dispatch'!
-
-buttonPress:button x:x y:y view:aView
-    "forward a button-press event for some view"
-
-    aView isNil ifTrue:[
-	"/ event arrived, after I destroyed it myself
-	^ self
-    ].
-    button == 1 ifTrue:[
-	activateOnClick == true ifTrue:[
-	    "/ dont raise above an active popup view.
-	    (activeKeyboardGrab isNil and:[activePointerGrab isNil]) ifTrue:[
-		aView topView raise.
-"/            ] ifFalse:[
-"/                activeKeyboardGrab printCR.
-"/                activePointerGrab printCR.
-	    ]
-	].
-    ].
-    super buttonPress:button x:x y:y view:aView
-
-
-
-! !
-
-!XWorkstation methodsFor:'event sending'!
-
-sendClientEvent:msgType format:msgFormat to:targetWindowID propagate:propagate eventMask:eventMask window:windowID data1:d1 data2:d2 data3:d3 data4:d4 data5:d5
-    "send a ClientMessage to some other (possibly: non-ST/X) view.
-     The client message gets message_type and msgFormat as specified by
-     the arguments. The additional data arguments specify up to
-     5 longWords of user data; each may be an integer or nil.
-     It is passed transparently in the events data field.
-     See XProtocol specification for more details."
-
-    "/ Event.xclient.type              = ClientMessage;
-    "/ Event.xclient.display           = dpy;
-    "/ Event.xclient.message_type      = msgType;
-    "/ Event.xclient.format            = msgFormat;
-    "/ Event.xclient.window            = windowID;
-    "/ Event.xclient.data.l[0]         = d1
-    "/ Event.xclient.data.l[1]         = d2
-    "/ Event.xclient.data.l[2]         = d3
-    "/ Event.xclient.data.l[3]         = d4
-    "/ Event.xclient.data.l[4]         = d5
-    "/
-    "/ XSendEvent(dpy, targetWindowID, propagate, eventMask, &Event);
-
-    <context: #return>
-%{
-    int type;
-    int state;
-    int __eventMask;
-
-    if (ISCONNECTED
-     && __isInteger(msgType)
-     && __isInteger(msgFormat)
-     && (eventMask == nil || __isInteger(eventMask))
-     && (__isExternalAddress(windowID) || __isInteger(windowID))
-     && (__isExternalAddress(targetWindowID) || __isInteger(targetWindowID))) {
-	Display *dpy = myDpy;
-	XEvent ev;
-	Status result;
-	Window targetWindow;
-
-	if (__isInteger(d1)) {
-	    ev.xclient.data.l[0] = __longIntVal(d1);
-	} else {
-	    if (__isExternalAddress(d1)) {
-		ev.xclient.data.l[0] = (INT)__externalAddressVal(d1);
-	    } else {
-		ev.xclient.data.l[0] = 0;
-	    }
-	}
-	if (__isInteger(d2)) {
-	    ev.xclient.data.l[1] = __longIntVal(d2);
-	} else {
-	    if (__isExternalAddress(d2)) {
-		ev.xclient.data.l[1] = (INT)__externalAddressVal(d2);
-	    } else {
-		ev.xclient.data.l[1] = 0;
-	    }
-	}
-	if (__isInteger(d3)) {
-	    ev.xclient.data.l[2] = __longIntVal(d3);
-	} else {
-	    if (__isExternalAddress(d3)) {
-		ev.xclient.data.l[2] = (INT)__externalAddressVal(d3);
-	    } else {
-		ev.xclient.data.l[2] = 0;
-	    }
-	}
-	if (__isInteger(d4)) {
-	    ev.xclient.data.l[3] = __longIntVal(d4);
-	} else {
-	    if (__isExternalAddress(d4)) {
-		ev.xclient.data.l[3] = (INT)__externalAddressVal(d4);
-	    } else {
-		ev.xclient.data.l[3] = 0;
-	    }
-	}
-	if (__isInteger(d5)) {
-	    ev.xclient.data.l[4] = __longIntVal(d5);
-	} else {
-	    if (__isExternalAddress(d5)) {
-		ev.xclient.data.l[4] = (INT)__externalAddressVal(d5);
-	    } else {
-		ev.xclient.data.l[4] = 0;
-	    }
-	}
-
-	if (__isExternalAddress(windowID)) {
-	    ev.xclient.window = __WindowVal(windowID);
-	} else {
-	    ev.xclient.window = (Window)__longIntVal(windowID);
-	}
-
-	if (__isExternalAddress(targetWindowID)) {
-	    targetWindow = __WindowVal(targetWindowID);
-	} else {
-	    targetWindow = (Window)__longIntVal(targetWindowID);
-	}
-
-	ev.xclient.type              = ClientMessage;
-	ev.xclient.display           = dpy;
-	ev.xclient.message_type      = __longIntVal(msgType);
-	ev.xclient.format            = __longIntVal(msgFormat);
-
-	if (eventMask == nil) {
-	    __eventMask = NoEventMask;
-	} else {
-	    __eventMask = __longIntVal(eventMask);
-	}
-
-	ENTER_XLIB();
-	result = XSendEvent(dpy, targetWindow, (propagate == true ? True : False), __eventMask , &ev);
-	LEAVE_XLIB();
-
-	if ((result == BadValue) || (result == BadWindow)) {
-	    DPRINTF(("bad status in sendClientEvent\n"));
-	    RETURN ( false )
-	}
-	RETURN (true)
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false
-!
-
-sendKeyOrButtonEvent:typeSymbol x:xPos y:yPos keyOrButton:keySymCodeOrButtonNr state:stateMask toViewId:targetId
-    "send a keyPress/Release or buttonPress/Release event to some (possibly alien) view.
-     TypeSymbol must be one of: #keyPress, #keyRelease, #buttonPress , #buttonRelease.
-     For buttonEvents, the keySymCodeOrButtonNr must be the buttons number (1, 2 ...);
-     for key events, it can be either a symbol (as listen in X's keySyms)
-     or a numeric keysym code. If state is nil, the modifier bits (shift & control)
-     are computed from the keyboardMap - if non-nil, these are passed as modifierbits.
-     The non-nil case is the lowlevel entry, where state must include any shift/ctrl information
-     (not very user friendly)"
-
-    <context: #return>
-%{
-    int type;
-    int state;
-
-    if (__isSmallInteger(stateMask)) {
-	state = __intVal(stateMask);
-    } else {
-	state = 0;
-    }
-
-    if (ISCONNECTED
-     && __isSmallInteger(xPos) && __isSmallInteger(yPos)
-     && (__isSmallInteger(keySymCodeOrButtonNr) || __isStringLike(keySymCodeOrButtonNr))
-     && (__isExternalAddress(targetId) || __isInteger(targetId))) {
-	Display *dpy = myDpy;
-
-	XEvent ev;
-	Window target;
-	Status result;
-	KeySym keySym, *syms;
-	int screen = __intVal(__INST(screen));
-	char s[2];
-	int nSyms;
-
-	if ((typeSymbol == @symbol(keyPress))
-	 || (typeSymbol == @symbol(keyRelease))) {
-	    if (__isStringLike(keySymCodeOrButtonNr)) {
-		keySym = XStringToKeysym(__stringVal(keySymCodeOrButtonNr));
-	    } else {
-		if (__isCharacter(keySymCodeOrButtonNr)) {
-		    s[0] = __intVal(__characterVal(keySymCodeOrButtonNr));
-		    s[1] = '\0';
-		    keySym = XStringToKeysym(s);
-		} else {
-		    keySym = (KeySym) __intVal(keySymCodeOrButtonNr);
-		}
-	    }
-	    ev.xkey.keycode = XKeysymToKeycode(dpy, keySym);
-
-	    if (stateMask == nil) {
-		/*
-		 * get the modifier from the keySym
-		 */
-		nSyms = 0;
-		syms = XGetKeyboardMapping(dpy, ev.xkey.keycode, 1, &nSyms);
-		if (syms) {
-		    int i;
-
-		    for (i=0; i<nSyms; i++) {
-			if (syms[i] == keySym) {
-#ifdef MODIFIERDEBUG
-			    console_printf("modifier-index is %d\n", i);
-#endif
-			    if (i) state = (1 << (i-1));
-			    break;
-			}
-		    }
-		    XFree(syms);
-		}
-	    }
-	} else {
-	    if ((typeSymbol == @symbol(buttonPress))
-	     || (typeSymbol == @symbol(buttonRelease))) {
-		if (__isSmallInteger(keySymCodeOrButtonNr)) {
-		    ev.xbutton.button = __intVal(keySymCodeOrButtonNr);
-		} else {
-		    ev.xbutton.button = 1;
-		}
-	    } else {
-		DPRINTF(("invalid sendEvent typeSymbol\n"));
-		RETURN (false);
-	    }
-	}
-
-	if (typeSymbol == @symbol(keyPress))
-	    ev.xany.type = KeyPress;
-	else if (typeSymbol == @symbol(keyRelease))
-	    ev.xany.type = KeyRelease;
-	else if (typeSymbol == @symbol(buttonPress))
-	    ev.xany.type = ButtonPress;
-	else if (typeSymbol == @symbol(buttonRelease))
-	    ev.xany.type = ButtonRelease;
-
-	if (__isExternalAddress(targetId)) {
-	    target = __WindowVal(targetId);
-	} else {
-	    target = (Window) __longIntVal(targetId);
-	}
-	ev.xkey.window = target;
-	ev.xkey.same_screen = 1;
-	ev.xkey.subwindow = 0;
-	ev.xkey.root = RootWindow(dpy, screen);
-	ev.xkey.x = __intVal(xPos);
-	ev.xkey.y = __intVal(yPos);
-	ev.xkey.state = state;
-	ev.xkey.time = CurrentTime;
-
-	ENTER_XLIB();
-	result = XSendEvent(dpy, target, False, 0 , &ev);
-	LEAVE_XLIB();
-	if ((result == BadValue) || (result == BadWindow)) {
-	    DPRINTF(("bad status\n"));
-	    RETURN ( false )
-	}
-	RETURN (true)
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false
-! !
-
-!XWorkstation methodsFor:'font stuff'!
-
-createFontFor:aFontName
-    "a basic method for X-font allocation; this method allows
-     any font to be aquired (even those not conforming to
-     standard naming conventions, such as cursor, fixed or k14)"
-
-    <context: #return>
-
-%{  /* STACK: 100000 */
-    /*** UNLIMITEDSTACK */
-
-    XFontStruct *newFont;
-
-    if (ISCONNECTED
-     && __isStringLike(aFontName)) {
-
-	ENTER_XLIB();
-	newFont = XLoadQueryFont(myDpy, (char *)__stringVal(aFontName));
-	LEAVE_XLIB();
-#ifdef COUNT_RESOURCES
-	if (newFont)
-	    __cnt_font++;
-#endif
-
-	RETURN ( newFont ? __MKEXTERNALADDRESS(newFont) : nil );
-    }
-%}.
-    "/ --- disabled due to UNLIMITEDSTACK -- self primitiveFailedOrClosedConnection.
-    ^ nil
-!
-
-decomposeXFontName:aString into:aBlock
-    "extract family, face, style and size from an
-     X-font name
-     1 2     3      4    5     6         7 8      9    10   11   12 13 14       15
-      -brand-family-face-style-moreStyle- -height-size-resX-resY-??-??-registry-encoding;
-     evaluate aBlock with these"
-
-    |family face style moreStyle fheight size
-     resX resY registry encoding coding fields|
-
-    aString isNil ifTrue:[^ false].
-    fields := aString asCollectionOfSubstringsSeparatedBy:$-.
-    fields size == 3 ifTrue:[
-	"take care of old font names: family-style-size"
-	family := fields at:1.
-	style := fields at:2.
-	size := Number readFromString:(fields at:3) onError:[^ false].
-    ] ifFalse:[fields size == 2 ifTrue:[
-	"take care of old font names: family-size"
-	family := fields at:1.
-	size := Number readFromString:(fields at:2) onError:[^ false].
-    ] ifFalse:[fields size >= 15 ifTrue:[
-	family := fields at:3.
-	face := fields at:4.
-	style := fields at:5.
-	style = 'o' ifTrue:[
-	    style := 'oblique'
-	] ifFalse:[style = 'i' ifTrue:[
-	     style := 'italic'
-	] ifFalse:[style = 'r' ifTrue:[
-	     style := 'roman'
-	]]].
-	moreStyle := fields at:6.
-	(moreStyle ~= 'normal' and:[moreStyle size > 1]) ifTrue:[
-	    style := style, '-', moreStyle.
-	].
-	fheight := fields at:8.
-	size := (Number readFromString:(fields at:9) onError:[^ false]) / 10.
-	resX := fields at:10.
-	resY := fields at:11.
-	registry := fields at:14.
-	encoding := fields at:15.
-	coding := registry , '-' , encoding.
-    ] ifFalse:[
-	^ false
-    ]]].
-    aBlock value:family value:face value:style value:size value:coding.
-    ^ true
-!
-
-encodingOf:aFontId
-    "the fonts encoding - if the font does not provide that info,
-     return nil (and assume #ascii, which is a subset of #iso8859-1)."
-
-    |props reg enc coll|
-
-    props := self fontPropertiesOf:aFontId.
-    reg := props at:#'CHARSET_REGISTRY' ifAbsent:nil.
-    enc := props at:#'CHARSET_ENCODING' ifAbsent:nil.
-    coll := props at:#'CHARSET_COLLECTIONS' ifAbsent:nil.
-
-    reg notNil ifTrue:[ reg := self atomName:reg].
-    enc notNil ifTrue:[ enc := self atomName:enc].
-    coll notNil ifTrue:[ coll := self atomName:coll].
-
-    ^ self extractEncodingFromRegistry:reg encoding:enc charSetCollections:coll
-
-     "
-       Screen current encodingOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
-     "
-!
-
-extentsOf:aString from:index1 to:index2 inFont:aFontId into:anArray
-
-    <context: #return>
-
-%{  /* UNLIMITEDSTACK */
-
-    XFontStruct *f;
-    char *cp;
-    int len, n, i1, i2, l;
-#   define NLOCALBUFFER 200
-    XChar2b xlatebuffer[NLOCALBUFFER];
-    int nInstBytes;
-    int directionReturn, fontAscentReturn, fontDescentReturn;
-    XCharStruct overAllReturn;
-    OBJ *resultArray;
-
-    if (ISCONNECTED
-	 && __bothSmallInteger(index1, index2)
-	 && __isExternalAddress(aFontId)
-	 && __isNonNilObject(aString)) {
-	int lMax = __intVal(@global(MaxStringLength));
-	f = __FontVal(aFontId);
-	if (! f) goto fail;
-
-	if (__isArray(anArray) && __arraySize(anArray) > 0) {
-	    resultArray = __arrayVal(anArray);
-	} else {
-	    resultArray = 0;
-	}
-
-	i1 = __intVal(index1) - 1;
-
-	if (i1 >= 0) {
-	    OBJ cls;
-
-	    i2 = __intVal(index2) - 1;
-	    if (i2 < i1) {
-		RETURN ( __MKSMALLINT(0) );
-	    }
-
-	    cp = (char *) __stringVal(aString);
-	    l = i2 - i1 + 1;
-
-	    if (__isStringLike(aString)) {
-		n = __stringSize(aString);
-		if (i2 >= n) goto fail;
-		cp += i1;
-		len = XTextExtents(f, cp, l,
-					&directionReturn, &fontAscentReturn, &fontDescentReturn,
-					&overAllReturn);
-	    } else {
-		cls = __qClass(aString);
-		nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
-		cp += nInstBytes;
-		n = __byteArraySize(aString) - nInstBytes;
-
-		if (__isBytes(aString)) {
-		    if (i2 >= n) goto fail;
-
-		    cp += i1;
-		    len = XTextExtents(f, cp, l,
-					    &directionReturn, &fontAscentReturn, &fontDescentReturn,
-					    &overAllReturn);
-		} else  if (__isWords(aString)) { /* TWOBYTESTRINGS */
-		    union {
-			char b[2];
-			unsigned short s;
-		    } u;
-		    int i;
-		    XChar2b *cp2 = (XChar2b *)0;
-		    int mustFree = 0;
-
-		    n = n / 2;
-		    if (i2 >= n) goto fail;
-
-		    cp += (i1 * 2);
-		    if (l > lMax) l = lMax;
-
-		    /*
-		     * ST/X TwoByteStrings store the asciiValue in native byteOrder;
-		     * X expects them MSB first
-		     * convert as required
-		     */
-
-		    u.s = 0x1234;
-		    if (u.b[0] != 0x12) {
-			if (l <= NLOCALBUFFER) {
-			    cp2 = xlatebuffer;
-			} else {
-			    cp2 = (XChar2b *)(malloc(l * 2));
-			    mustFree = 1;
-			}
-			for (i=0; i<l; i++) {
-			    cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
-			    cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
-			}
-			cp = (char *) cp2;
-		    }
-
-		    len = XTextExtents16(f, (XChar2b *)cp, l,
-					    &directionReturn, &fontAscentReturn, &fontDescentReturn,
-					    &overAllReturn);
-
-		    if (mustFree) {
-			free(cp2);
-		    }
-		} else if (__isLongs(aString)) { /* FOURBYTESTRINGS */
-		    union {
-			char b[2];
-			unsigned short s;
-		    } u;
-		    int i;
-		    XChar2b *cp2 = (XChar2b *)0;
-		    int mustFree = 0;
-
-		    n = n / 4;
-		    if (i2 >= n) goto fail;
-
-		    cp += (i1 * 4);
-		    if (l > lMax) l = lMax;
-
-		    /*
-		     * For now: X does not support 32bit characters without the new 32Unicode extensions.
-		     * For now, treat chars above 0xFFFF as 0xFFFF (should we use default-char ?).
-		     */
-		    if (l <= NLOCALBUFFER) {
-			cp2 = xlatebuffer;
-		    } else {
-			cp2 = (XChar2b *)(malloc(l * 2));
-			mustFree = 1;
-		    }
-		    for (i=0; i<l; i++) {
-			int codePoint;
-
-			codePoint = ((unsigned int32 *)cp)[i];
-			if (codePoint > 0xFFFF) {
-			    codePoint = 0xFFFF;
-			}
-			cp2[i].byte1 = codePoint & 0xFF;
-			cp2[i].byte2 = (codePoint >> 8) & 0xFF;;
-		    }
-		    cp = (char *) cp2;
-
-		    len = XTextExtents16(f, (XChar2b *)cp, l,
-					    &directionReturn, &fontAscentReturn, &fontDescentReturn,
-					    &overAllReturn);
-		    if (mustFree) {
-			free(cp2);
-		    }
-		} else
-		    goto fail;      /*unknown string class */
-	    }
-	    if (resultArray) {
-		switch (__arraySize(anArray)) {
-		default:
-		case 8:
-		    resultArray[7] = __MKSMALLINT(directionReturn);
-		case 7:
-		    resultArray[6] = __MKSMALLINT(fontDescentReturn);
-		case 6:
-		    resultArray[5] = __MKSMALLINT(fontAscentReturn);
-		case 5:
-		    resultArray[4] = __MKSMALLINT(overAllReturn.descent);
-		case 4:
-		    resultArray[3] = __MKSMALLINT(overAllReturn.ascent);
-		case 3:
-		    resultArray[2] = __MKSMALLINT(overAllReturn.width);
-		case 2:
-		    resultArray[1] = __MKSMALLINT(overAllReturn.rbearing);
-		case 1:
-		    resultArray[0] = __MKSMALLINT(overAllReturn.lbearing);
-		case 0:
-		    break;
-		}
-	    }
-	    RETURN ( __MKSMALLINT(overAllReturn.width) );
-	}
-    }
-#undef NLOCALBUFFER
-fail: ;
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ 0
-
-    "
-      |result|
-      result := Array new:8.
-      Screen current
-	extentsOf:'hello World' from:1 to:11
-	inFont:(Screen current  getFontWithFoundry:'*'
-		    family:'courier new'
-		    weight:'medium'
-		    slant:'r'
-		    spacing:nil
-		    pixelSize:nil
-		    size:10
-		    encoding:#'iso10646-1'
-	    )
-	into:result.
-
-      result
-    "
-!
-
-extractEncodingFromRegistry:registry encoding:encoding charSetCollections:charSetCollections
-    "given registry and encoding as returned by X11,
-     generate a single symbol naming the ST/X encoding.
-     I.e. from registry='ISO8859' and encoding='1', generate #'iso8859-1'.
-     This is pure magic ..."
-
-    |enc charSets|
-
-    (registry size ~~ 0) ifTrue:[
-	enc := registry asLowercase.
-	encoding size ~~ 0 ifTrue:[
-	   enc := enc, '-', encoding asLowercase.
-	].
-	enc := enc asSymbol.
-    ] ifFalse:[
-	(encoding size ~~ 0) ifTrue:[
-	    enc := encoding asLowercase asSymbol
-	] ifFalse:[
-	    charSets := charSetCollections.
-	    (charSets notEmptyOrNil) ifTrue:[
-		charSets := charSets asUppercase asCollectionOfWords.
-		(charSets includes:'ISO8859-1') ifTrue:[
-		    enc := #'iso8859-1'
-		] ifFalse:[
-		    (charSets includes:'ISO8859') ifTrue:[
-			enc := #iso8859
-		    ] ifFalse:[
-			(charSets includes:'ASCII') ifTrue:[
-			    enc := #ascii
-			] ifFalse:[
-			    (charSets includes:'ADOBE-STANDARD') ifTrue:[
-				enc := #iso8859
-			    ]
-			]
-		    ]
-		]
-	    ]
-	]
-    ].
-    ^  enc
-
-    "Created: 17.4.1996 / 14:57:06 / cg"
-    "Modified: 17.4.1996 / 17:22:35 / cg"
-!
-
-flushListOfAvailableFonts
-    "flush the cached list of all available fonts on this display.
-     Required if new fonts have been added on the display server."
-
-    listOfXFonts := nil
-
-    "
-     Display flushListOfAvailableFonts.
-     Display listOfAvailableFonts
-    "
-
-    "Modified: 27.9.1995 / 10:54:47 / stefan"
-    "Created: 20.2.1996 / 22:55:52 / cg"
-!
-
-fontDescriptionFromXFontName:aFontNameString
-    "extract family, face, style and size from an
-     X-font name
-     1 2     3      4    5     6         7 8      9    10   11   12 13 14       15
-      -brand-family-face-style-moreStyle- -pxlSize-size-resX-resY-??-??-registry-encoding;
-     evaluate aBlock with these"
-
-    |family face style moreStyle size
-     resX resY registry encoding coding fields|
-
-    aFontNameString isNil ifTrue:[^ nil].
-
-    Error handle:[:ex |
-	family := nil.
-    ] do:[
-	fields := aFontNameString asCollectionOfSubstringsSeparatedBy:$-.
-	fields size == 3 ifTrue:[
-	    "take care of old font names: family-style-size"
-	    family := fields at:1.
-	    style := fields at:2.
-	    size := Number readFromString:(fields at:3).
-	] ifFalse:[
-	    fields size == 2 ifTrue:[
-		"take care of old font names: family-size"
-		family := fields at:1.
-		size := Number readFromString:(fields at:2).
-	    ] ifFalse:[
-		fields size >= 15 ifTrue:[
-		    family := fields at:3.
-		    face := fields at:4.
-		    style := fields at:5.
-		    style = 'o' ifTrue:[
-			style := 'oblique'
-		    ] ifFalse:[style = 'i' ifTrue:[
-			 style := 'italic'
-		    ] ifFalse:[style = 'r' ifTrue:[
-			 style := 'roman'
-		    ]]].
-		    moreStyle := fields at:6.
-		    (moreStyle ~= 'normal' and:[moreStyle size > 1]) ifTrue:[
-			style := style, '-', moreStyle.
-		    ].
-"/                    pxlSize := (Integer readFromString:(fields at:8)).
-		    size := (Number readFromString:(fields at:9)) / 10.
-		    resX := fields at:10.
-		    resY := fields at:11.
-		    registry := fields at:14.
-		    encoding := fields at:15.
-		    coding := registry , '-' , encoding.
-		] ifFalse:[
-		    "/ very old name (such as cursor, 5x7 etc)
-		]
-	    ]
-	].
-    ].
-
-    family notNil ifTrue:[
-       ^ FontDescription family:family face:face style:style size:size sizeUnit:#pt encoding:coding.
-    ].
-    ^ FontDescription name:aFontNameString
-
-    "
-     Screen current fontDescriptionFromXFontName:'-arabic-newspaper-medium-r-normal--32-246-100-100-p-137-iso10646-1'
-    "
-!
-
-fontMetricsOf:fontId
-    "return a fonts metrics info object"
-
-    <context: #return>
-
-    |info avgAscent avgDescent minCode maxCode dir
-     maxAscent maxDescent minWidth maxWidth avgWidth|
-
-%{  /* UNLIMITEDSTACK */
-    XFontStruct *f;
-    int len;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(fontId)) {
-	    f = __FontVal(fontId);
-	    if (f) {
-		minCode = __MKUINT((f->min_byte1<<8) + f->min_char_or_byte2);
-		maxCode = __MKUINT((f->max_byte1<<8) + f->max_char_or_byte2);
-
-		if (f->direction == FontLeftToRight) {
-		    dir = @symbol(LeftToRight);
-		} else if (f->direction == FontRightToLeft) {
-		    dir = @symbol(RightToLeft);
-		}
-		avgAscent = __MKSMALLINT(f->ascent);
-		avgDescent = __MKSMALLINT(f->descent);
-		maxAscent = __MKSMALLINT(f->max_bounds.ascent);
-		maxDescent = __MKSMALLINT(f->max_bounds.descent);
-		minWidth = __MKSMALLINT(f->min_bounds.width);
-		maxWidth = __MKSMALLINT(f->max_bounds.width);
-
-		ENTER_XLIB();
-		len = XTextWidth(f, "n", 1);
-		LEAVE_XLIB();
-
-		avgWidth = __MKSMALLINT( len );
-	    }
-	}
-    }
-%}.
-    avgAscent == nil ifTrue:[
-	self primitiveFailedOrClosedConnection.
-	^ nil
-    ].
-
-    "DingBats font returns 0 for maxAscent/maxDescent"
-    maxAscent := maxAscent max:avgAscent.
-    maxDescent := maxDescent max:avgDescent.
-
-    info := DeviceWorkstation::DeviceFontMetrics new.
-    info
-      ascent:avgAscent
-      descent:avgDescent
-      maxAscent:maxAscent
-      maxDescent:maxDescent
-      minWidth:minWidth
-      maxWidth:maxWidth
-      avgWidth:avgWidth
-      minCode:minCode
-      maxCode:maxCode
-      direction:dir.
-    ^ info
-
-    "
-     Screen current fontMetricsOf:(View defaultFont onDevice:Screen current) fontId
-     CharacterSetView openOn:(View defaultFont onDevice:Screen current)
-
-     Screen current fontMetricsOf:(MenuView defaultFont onDevice:Screen current) fontId
-     CharacterSetView openOn:(MenuView defaultFont onDevice:Screen current)
-    "
-!
-
-fontProperties:propertyNames of:aFontId
-    "Answer an array with selected property values of a font.
-     This is X11-Specific.
-     PropertyNames is an array with property names (symbols or strings).
-     Nonexistant properties are returned as nil"
-
-    |props|
-
-    props := self fontPropertiesOf:aFontId.
-    ^ propertyNames collect:[:propName | props at:propName ifAbsent:nil].
-
-    "
-     Screen current
-	fontProperties:#(#'PIXEL_SIZE' #'POINT_SIZE' RESOLUTION notExistant)
-	of:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
-    "
-!
-
-fontPropertiesOf:aFontId
-    "Answer an array with all the properties of a font.
-     This is X11-Specific.
-     Odd indices contain the property name (atom)
-     Even indices contain the property value (atom)
-
-     Answer nil, if there are no properties"
-
-    |propsArray result|
-
-%{
-    XFontStruct *f;
-    XFontProp *prop;
-    int n, i;
-    OBJ x;
-
-    if (__isExternalAddress(aFontId)) {
-	f = __FontVal(aFontId);
-	if (f && (prop = f->properties) != 0) {
-	    n = f->n_properties;
-	    propsArray = __ARRAY_NEW_INT(n*2);
-	    for (i = 0; n; n--, prop++) {
-		x = __MKUINT(prop->name); __ArrayInstPtr(propsArray)->a_element[i++] = x; __STORE(propsArray, x);
-		x = __MKUINT(prop->card32); __ArrayInstPtr(propsArray)->a_element[i++] = x; __STORE(propsArray, x);
-	    }
-	}
-    }
-%}.
-    result := Dictionary new.
-    propsArray notNil ifTrue:[
-	propsArray pairWiseDo:[:n :v | result at:(self atomName:n) put:v].
-    ].
-    ^ result
-
-    "
-     Screen current fontPropertiesOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
-     Dictionary withKeysAndValues:(Screen current fontPropertiesOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1'))
-
-     |d|
-     d := Dictionary new.
-     (Screen current fontPropertiesOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')) keysAndValuesDo:[:name :value|
-	  d at:name put:((Screen current atomName:value) ? value)
-     ].
-     d
-    "
-!
-
-fontResolutionOf:fontId
-    "return the resolution (as dpiX @ dpiY) of the font - this is usually the displays resolution,
-     but due to errors in some XServer installations, some use 75dpi fonts on higher
-     resolution displays and vice/versa."
-
-    |props res resX resY|
-
-    props := self fontProperties:#(#'RESOLUTION_X' #'RESOLUTION_Y' RESOLUTION) of:fontId.
-    resX := props at:1.
-    resY := props at:2.
-    (resX notNil and:[resY notNil]) ifTrue:[
-	^ resX @ resY
-    ].
-    res := props at:3.
-    res notNil ifTrue:[
-	^ res @ res
-    ].
-    ^ self resolution
-
-    "
-      Screen current fontResolutionOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
-    "
-!
-
-fullFontNameOf:aFontId
-    "the fonts fullName - this is very device specific and should only be
-     used for user feed-back (for example: in the fontPanel).
-     If the display/font does not provide that info, return nil."
-
-    |props fullName|
-
-    props := self fontPropertiesOf:aFontId.
-    #('FONT' 'FONT_NAME' 'FULL_NAME' 'FULLNAME' ) do:[:try |
-	|fullNameID|
-
-	fullNameID := props at:try ifAbsent:nil.
-	fullNameID notNil ifTrue:[
-	    fullName := self atomName:fullNameID.
-	    fullName notEmptyOrNil ifTrue:[
-		^ fullName
-	    ].
-	]
-    ].
-
-    ^ nil.
-
-    "
-     Screen current fullFontNameOf:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
-    "
-!
-
-getAvailableFontsMatching:pattern
-    "return an Array filled with font names matching aPattern"
-
-    <context: #return>
-
-%{  /* UNLIMITEDSTACK */
-
-    int nnames = 30000;
-    int available = nnames + 1;
-    char **fonts;
-    OBJ arr, str;
-    int i;
-
-    if (ISCONNECTED) {
-	if (__isStringLike(pattern)) {
-	    for (;;) {
-		ENTER_XLIB();
-		fonts = XListFonts(myDpy, __stringVal(pattern), nnames, &available);
-		LEAVE_XLIB();
-		if (fonts == 0) RETURN(nil);
-		if (available < nnames) break;
-		XFreeFontNames(fonts);
-		nnames = available * 2;
-	    }
-
-	    /*
-	     * now, that we know the number of font names,
-	     * create the array ...
-	     */
-	    arr = __ARRAY_NEW_INT(available);
-	    if (arr != nil) {
-		/*
-		 * ... and fill it
-		 */
-		for (i=0; i<available; i++) {
-		    __PROTECT__(arr);
-		    str = __MKSTRING(fonts[i]);
-		    __UNPROTECT__(arr);
-		    __ArrayInstPtr(arr)->a_element[i] = str; __STORE(arr, str);
-		}
-	    }
-	    XFreeFontNames(fonts);
-	    RETURN (arr);
-	}
-    }
-%}.
-    ^ nil
-
-    "
-      Screen current getAvailableFontsMatching:'*'
-    "
-!
-
-getDefaultFontWithEncoding:encoding
-    "return a default font id - used when class Font cannot
-     find anything usable"
-
-    |id|
-
-    id := self createFontFor:'-misc-fixed-*-*-*-*-*-*-*-*-*-*-', encoding.
-    id isNil ifTrue:[
-	id := self createFontFor:'fixed'
-    ].
-    ^ id.
-
-     "
-       Screen current getDefaultFontWithEncoding:#'iso10646-1'
-     "
-!
-
-getFontWithFamily:familyString face:faceString
-	    style:styleArgString size:sizeArgOrNil sizeUnit:sizeUnit encoding:encoding
-
-    "try to get the specified font, if not available, try next smaller
-     font. Access to X-fonts by name is possible, by passing the X font name
-     as family and the other parameters as nil. For example, the cursor font
-     can be aquired that way."
-
-    |styleString theName theId xlatedStyle
-     id spacing encodingMatch idx roundedSize pixelSize pointSize|
-
-    styleString := styleArgString.
-
-    sizeArgOrNil notNil ifTrue:[
-	roundedSize := sizeArgOrNil rounded asInteger.
-	sizeUnit == #px ifTrue:[
-	    pixelSize := roundedSize.
-	] ifFalse:[
-	    pointSize := roundedSize.
-	].
-    ].
-
-    "special: if face is nil, allow access to X-fonts"
-    faceString isNil ifTrue:[
-	roundedSize notNil ifTrue:[
-	    theName := familyString , '-' , roundedSize printString
-	] ifFalse:[
-	    theName := familyString
-	].
-	theName notNil ifTrue:[
-	    theId := self createFontFor:theName.
-	].
-	theId isNil ifTrue:[
-	    theId := self getDefaultFontWithEncoding:encoding
-	].
-	^ theId
-    ].
-
-    "/ spacing other than 'normal' is contained as last component
-    "/ in style
-
-    (styleString notNil
-     and:[(styleString endsWith:'-narrow')
-	  or:[styleString endsWith:'-semicondensed']]) ifTrue:[
-	|i|
-	i := styleString lastIndexOf:$-.
-	spacing := styleString copyFrom:(i+1).
-	styleString := styleString copyTo:(i-1).
-    ] ifFalse:[
-	spacing := 'normal'.
-    ].
-
-    xlatedStyle := styleString.
-    xlatedStyle notNil ifTrue:[
-	xlatedStyle := xlatedStyle first asString
-    ].
-
-    encoding isNil ifTrue:[
-	encodingMatch := '*-*'.
-    ] ifFalse:[
-	idx := encoding indexOf:$-.
-	idx ~~ 0 ifTrue:[
-	    encodingMatch := encoding
-	] ifFalse:[
-	    encodingMatch := encoding , '-*'.
-	].
-    ].
-
-    id := self
-	    getFontWithFoundry:'*'
-	    family:familyString asLowercase
-	    weight:faceString
-	    slant:xlatedStyle
-	    spacing:spacing
-	    pixelSize:pixelSize
-	    size:pointSize
-	    encoding:encodingMatch.
-
-    id isNil ifTrue:[
-	(encodingMatch notNil and:[encodingMatch ~= '*']) ifTrue:[
-	    "/ too stupid: registries come in both cases
-	    "/ and X does not ignore case
-	    "/
-	    id := self
-		    getFontWithFoundry:'*'
-		    family:familyString asLowercase
-		    weight:faceString
-		    slant:xlatedStyle
-		    spacing:spacing
-		    pixelSize:nil
-		    size:roundedSize
-		    encoding:encodingMatch asUppercase.
-	    id isNil ifTrue:[
-		id := self
-			getFontWithFoundry:'*'
-			family:familyString asLowercase
-			weight:faceString
-			slant:xlatedStyle
-			spacing:spacing
-			pixelSize:nil
-			size:roundedSize
-			encoding:encodingMatch asLowercase.
-	    ]
-	]
-    ].
-    ^ id
-
-    "Modified: 4.7.1996 / 11:38:47 / stefan"
-    "Modified: 10.4.1997 / 19:20:06 / cg"
-!
-
-getFontWithFoundry:foundry family:family weight:weight
-	      slant:slant spacing:spc pixelSize:pSize size:size
-	      encoding:encoding
-
-    "get the specified font, if not available, return nil.
-     This is the new font creation method - all others will be changed to
-     use this entry.
-     Individual attributes can be left empty (i.e. '') or nil to match any.
-
-     foundry: 'adobe', 'misc', 'dec', 'schumacher' ... usually '*'
-     family:  'helvetica' 'courier' 'times' ...
-     weight:  'bold' 'medium' 'demi' ...
-     slant:   'r(oman)' 'i(talic)' 'o(blique)'
-     spacing: 'narrow' 'normal' semicondensed' ... usually '*'
-     pixelSize: 16,18 ... usually left empty
-     size:      size in point (1/72th of an inch)
-     encoding:  iso8859-*, iso8859-1, iso10646-1 ... '*'
-    "
-
-    |theName sizeMatch
-     foundryMatch familyMatch weightMatch slantMatch spcMatch
-     pSizeMatch encodingMatch|
-
-    "this works only on 'Release >= 3' - X-servers"
-    "name is:
-	-foundry-family    -weight -slant-
-	 sony    helvetica bold     r
-	 adobe   courier   medium   i
-	 msic    fixed              o
-	 ...     ...
-    "
-
-    size isNil ifTrue:[
-	sizeMatch := '*'
-    ] ifFalse:[
-	sizeMatch := size printString , '0'
-    ].
-    foundry isNil ifTrue:[
-	foundryMatch := '*'
-    ] ifFalse:[
-	foundryMatch := foundry
-    ].
-    family isNil ifTrue:[
-	familyMatch := '*'
-    ] ifFalse:[
-	familyMatch := family
-    ].
-    weight isNil ifTrue:[
-	weightMatch := '*'
-    ] ifFalse:[
-	weightMatch := weight
-    ].
-    slant isNil ifTrue:[
-	slantMatch := '*'
-    ] ifFalse:[
-	slantMatch := slant
-    ].
-    spc isNil ifTrue:[
-	spcMatch := '*'
-    ] ifFalse:[
-	spcMatch := spc
-    ].
-    pSize isNil ifTrue:[
-	pSizeMatch := '*'
-    ] ifFalse:[
-	pSizeMatch := pSize printString
-    ].
-    encoding isNil ifTrue:[
-	encodingMatch := '*'
-    ] ifFalse:[
-	encodingMatch := encoding
-    ].
-
-    theName := ('-' , foundryMatch,
-		'-' , familyMatch,
-		'-' , weightMatch ,
-		'-' , slantMatch ,
-		'-' , spcMatch ,
-		'-*' ,
-		'-' , pSizeMatch ,
-		'-' , sizeMatch ,
-		'-*-*-*-*' ,
-		'-' , encodingMatch).
-
-"/  Transcript showCR:theName; endEntry.
-
-    ^ self createFontFor:theName.
-
-
-    "
-     Display
-	getFontWithFoundry:'*'
-	family:'courier'
-	weight:'medium'
-	slant:'r'
-	spacing:nil
-	pixelSize:nil
-	size:13
-	encoding:#'iso8859-1'.
-
-     Display
-	getFontWithFoundry:'*'
-	family:'courier'
-	weight:'medium'
-	slant:'r'
-	spacing:nil
-	pixelSize:nil
-	size:13
-	encoding:#'iso10646-1'
-    "
-
-    "Modified: 10.4.1997 / 19:15:44 / cg"
-!
-
-heightOf:aString from:index1 to:index2 inFont:aFontId
-    |resultArray|
-
-    resultArray := Array new:5.
-    self extentsOf:aString from:index1 to:index2 inFont:aFontId into:resultArray.
-    ^ (resultArray at:4) + (resultArray at:5).
-
-    "
-      Screen current
-	heightOf:'hello world' from:1 to:10
-	inFont:(Screen current  getFontWithFoundry:'*'
-		    family:'courier new'
-		    weight:'medium'
-		    slant:'r'
-		    spacing:nil
-		    pixelSize:nil
-		    size:13
-		    encoding:#'iso10646-1'
-	    ).
-
-      Screen current
-	heightOf:'hello World gggÖÜ' from:1 to:15
-	inFont:(Screen current getDefaultFontWithEncoding:#'iso10646-1')
-    "
-!
-
-listOfAvailableFonts
-    "return a list with all available fonts on this display.
-     Since this takes some time, keep the result of the query for the
-     next time. The elements of the returned collection are instances of
-     FontDescription."
-
-    |names|
-
-    listOfXFonts isNil ifTrue:[
-	names := self getAvailableFontsMatching:'*'.
-	names isNil ifTrue:[
-	    "no names returned ..."
-	    ^ nil
-	].
-	listOfXFonts := names collect:[:aName | self fontDescriptionFromXFontName:aName].
-	listOfXFonts := FontDescription genericFonts, listOfXFonts.
-    ].
-    ^ listOfXFonts
-
-    "
-     Display flushListOfAvailableFonts.
-     Display listOfAvailableFonts.
-
-     Display getAvailableFontsMatching:'*'.
-     Display getAvailableFontsMatching:'fixed'.
-     Display fontsInFamily:'fixed' filtering:nil.
-    "
-
-    "Modified: 27.9.1995 / 10:54:47 / stefan"
-    "Modified: 17.4.1996 / 15:27:57 / cg"
-!
-
-pixelSizesInFamily:aFamilyName face:aFaceName style:aStyleName filtering:filter
-    "return a set of all available font sizes in aFamily/aFace/aStyle
-     on this display.
-     Redefined to handle X's special case of 0-size (which stands for any)"
-
-    |sizes|
-
-    sizes := super pixelSizesInFamily:aFamilyName face:aFaceName style:aStyleName filtering:filter.
-    (sizes notNil and:[sizes isEmpty or:[sizes includes:0]]) ifTrue:[
-	"special: in X11R5 and above, size 0 means:
-	 there are scaled versions in all sizes available"
-
-	^ #(4 5 6 7 8 9 10 11 12 14 16 18 20 22 24 28 32 48 64 72 96 144 192 288)
-    ].
-    ^ sizes
-
-    "
-     Display pixelSizesInFamily:'courier' face:'bold' style:'roman' filtering:nil
-    "
-
-    "Created: 27.2.1996 / 01:38:15 / cg"
-!
-
-releaseFont:aFontId
-
-    <context: #return>
-%{
-    XFontStruct *f;
-
-    /*
-     * ignore closed connection
-     */
-    if (! ISCONNECTED) {
-	RETURN ( self );
-    }
-
-    if (__isExternalAddress(aFontId)) {
-	f = __FontVal(aFontId);
-	if (f) {
-
-	    ENTER_XLIB();
-	    XFreeFont(myDpy, f);
-	    LEAVE_XLIB();
-#ifdef COUNT_RESOURCES
-	    __cnt_font--;
-#endif
-	}
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailed
-!
-
-sizesInFamily:aFamilyName face:aFaceName style:aStyleName filtering:filter
-    "return a set of all available font sizes in aFamily/aFace/aStyle
-     on this display.
-     Redefined to handle X's special case of 0-size (which stands for any)"
-
-    |sizes|
-
-    sizes := super sizesInFamily:aFamilyName face:aFaceName style:aStyleName filtering:filter.
-    (sizes notNil and:[sizes includes:0]) ifTrue:[
-	"special: in X11R5 and above, size 0 means:
-	 there are scaled versions in all sizes available"
-
-	^ #(4 5 6 7 8 9 10 11 12 14 16 18 20 22 24 28 32 48 64 72 96 144 192 288)
-    ].
-    ^ sizes
-
-    "
-     Display sizesInFamily:'courier' face:'bold' style:'roman' filtering:nil
-    "
-
-    "Created: 27.2.1996 / 01:38:15 / cg"
-!
-
-widthOf:aString from:index1 to:index2 inFont:aFontId
-
-    <context: #return>
-
-%{  /* UNLIMITEDSTACK */
-
-    XFontStruct *f;
-    char *cp;
-    int len, n, i1, i2, l;
-#   define NLOCALBUFFER 200
-    XChar2b xlatebuffer[NLOCALBUFFER];
-    int nInstBytes;
-    int directionReturn, fontAscentReturn, fontDescentReturn;
-    XCharStruct overAllReturn;
-
-    if (ISCONNECTED) {
-	if (__bothSmallInteger(index1, index2)
-	 && __isExternalAddress(aFontId)
-	 && __isNonNilObject(aString)) {
-	    int lMax = __intVal(@global(MaxStringLength));
-	    f = __FontVal(aFontId);
-	    if (! f) goto fail;
-
-	    i1 = __intVal(index1) - 1;
-
-	    if (i1 >= 0) {
-		OBJ cls;
-
-		i2 = __intVal(index2) - 1;
-		if (i2 < i1) {
-		    RETURN ( __MKSMALLINT(0) );
-		}
-
-		cp = (char *) __stringVal(aString);
-		l = i2 - i1 + 1;
-
-		if (__isStringLike(aString)) {
-		    n = __stringSize(aString);
-		    if (i2 < n) {
-			cp += i1;
-
-#if 1
-			len = XTextExtents(f, cp, l,
-						&directionReturn, &fontAscentReturn, &fontDescentReturn,
-						&overAllReturn);
-			//console_printf("lBear:%d rBear:%d width:%d\n", overAllReturn.lbearing, overAllReturn.rbearing, overAllReturn.width);
-			RETURN ( __MKSMALLINT(overAllReturn.width) );
-#else
-			ENTER_XLIB();
-			len = XTextWidth(f, cp, l);
-			LEAVE_XLIB();
-			RETURN ( __MKSMALLINT(len) );
-#endif
-		    }
-		}
-
-		cls = __qClass(aString);
-		nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
-		cp += nInstBytes;
-
-		if (__isBytes(aString)) {
-		    n = __byteArraySize(aString) - nInstBytes;
-		    if (i2 < n) {
-			cp += i1;
-
-#if 1
-			len = XTextExtents(f, cp, l,
-						&directionReturn, &fontAscentReturn, &fontDescentReturn,
-						&overAllReturn);
-			RETURN ( __MKSMALLINT(overAllReturn.width) );
-#else
-			ENTER_XLIB();
-			len = XTextWidth(f, cp, l);
-			LEAVE_XLIB();
-			RETURN ( __MKSMALLINT(len) );
-#endif
-		    }
-		}
-
-		/* TWOBYTESTRINGS */
-		if (__isWords(aString)) {
-		    n = (__byteArraySize(aString) - nInstBytes) / 2;
-
-		    if (i2 < n) {
-			union {
-			    char b[2];
-			    unsigned short s;
-			} u;
-			int i;
-			XChar2b *cp2 = (XChar2b *)0;
-			int mustFree = 0;
-
-			cp += (i1 * 2);
-			if (l > lMax) l = lMax;
-
-			/*
-			 * ST/X TwoByteStrings store the asciiValue in native byteOrder;
-			 * X expects them MSB first
-			 * convert as required
-			 */
-
-			u.s = 0x1234;
-			if (u.b[0] != 0x12) {
-			    if (l <= NLOCALBUFFER) {
-				cp2 = xlatebuffer;
-			    } else {
-				cp2 = (XChar2b *)(malloc(l * 2));
-				mustFree = 1;
-			    }
-			    for (i=0; i<l; i++) {
-				cp2[i].byte1 = (((XChar2b *)cp)[i]).byte2;
-				cp2[i].byte2 = (((XChar2b *)cp)[i]).byte1;
-			    }
-			    cp = (char *) cp2;
-			}
-
-#if 1
-			len = XTextExtents16(f, (XChar2b *)cp, l,
-						&directionReturn, &fontAscentReturn, &fontDescentReturn,
-						&overAllReturn);
-			len = overAllReturn.width;
-#else
-			ENTER_XLIB();
-			len = XTextWidth16(f, (XChar2b *)cp, l);
-			LEAVE_XLIB();
-#endif
-
-			if (mustFree) {
-			    free(cp2);
-			}
-
-			RETURN ( __MKSMALLINT(len) );
-		    }
-		}
-		/* FOURBYTESTRINGS */
-		if (__isLongs(aString)) {
-		    int i;
-		    XChar2b *cp2;
-		    int mustFree = 0;
-
-		    n = (__byteArraySize(aString) - nInstBytes) / 4;
-		    if (i2 < n) {
-			union {
-			    char b[2];
-			    unsigned short s;
-			} u;
-			int i;
-			XChar2b *cp2 = (XChar2b *)0;
-			int mustFree = 0;
-
-			cp += (i1 * 4);
-			if (l > lMax) l = lMax;
-
-			/*
-			 * For now: X does not support 32bit characters without the new 32Unicode extensions.
-			 * For now, treat chars above 0xFFFF as 0xFFFF (should we use default-char ?).
-			 */
-			if (l <= NLOCALBUFFER) {
-			    cp2 = xlatebuffer;
-			} else {
-			    cp2 = (XChar2b *)(malloc(l * 2));
-			    mustFree = 1;
-			}
-			for (i=0; i<l; i++) {
-			    int codePoint;
-
-			    codePoint = ((unsigned int32 *)cp)[i];
-			    if (codePoint > 0xFFFF) {
-				codePoint = 0xFFFF;
-			    }
-			    cp2[i].byte1 = codePoint & 0xFF;
-			    cp2[i].byte2 = (codePoint >> 8) & 0xFF;;
-			}
-			cp = (char *) cp2;
-
-#if 1
-			len = XTextExtents16(f, (XChar2b *)cp, l,
-						&directionReturn, &fontAscentReturn, &fontDescentReturn,
-						&overAllReturn);
-			len = overAllReturn.width;
-#else
-			ENTER_XLIB();
-			len = XTextWidth16(f, (XChar2b *)cp, l);
-			LEAVE_XLIB();
-#endif
-
-			if (mustFree) {
-			    free(cp2);
-			}
-
-			RETURN ( __MKSMALLINT(len) );
-		    }
-		}
-	    }
-	}
-    }
-#undef NLOCALBUFFER
-fail: ;
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ 0
-! !
-
-!XWorkstation methodsFor:'grabbing'!
-
-allowEvents:mode
-    <context: #return>
-%{
-
-    int _mode, ok = 1;
-
-    if (mode == @symbol(asyncPointer))
-	_mode = AsyncPointer;
-    else if (mode == @symbol(syncPointer))
-	_mode = SyncPointer;
-    else if (mode == @symbol(asyncKeyboard))
-	_mode = AsyncKeyboard;
-    else if (mode == @symbol(syncKeyboard))
-	_mode = SyncKeyboard;
-    else if (mode == @symbol(syncBoth))
-	_mode = SyncBoth;
-    else if (mode == @symbol(asyncBoth))
-	_mode = AsyncBoth;
-    else if (mode == @symbol(replayPointer))
-	_mode = ReplayPointer;
-    else if (mode == @symbol(replayKeyboard))
-	_mode = ReplayKeyboard;
-    else
-	ok = 0;
-
-    if (ok
-     && ISCONNECTED) {
-	ENTER_XLIB();
-	XAllowEvents(myDpy, _mode, CurrentTime);
-	LEAVE_XLIB();
-
-	RETURN (self);
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-grabKeyboardIn:aWindowId
-    "grab the keyboard"
-
-    <context: #return>
-%{
-    int result, ok;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aWindowId)) {
-
-	    ENTER_XLIB();
-	    result = XGrabKeyboard(myDpy,
-				   __WindowVal(aWindowId),
-				   True /* False */,
-				   GrabModeAsync,
-				   GrabModeAsync,
-				   CurrentTime);
-	    LEAVE_XLIB();
-
-	    ok = 0;
-	    switch(result) {
-		case AlreadyGrabbed:
-		    if (@global(ErrorPrinting) == true) {
-			console_fprintf(stderr, "XWorkstation [warning]: grab keyboard: AlreadyGrabbed\n");
-		    }
-		    break;
-		case GrabNotViewable:
-		    if (@global(ErrorPrinting) == true) {
-			console_fprintf(stderr, "XWorkstation [warning]: grab keyboard: GrabNotViewable\n");
-		    }
-		    break;
-		case GrabInvalidTime:
-		    if (@global(ErrorPrinting) == true) {
-			console_fprintf(stderr, "XWorkstation [warning]: grab keyboard: InvalidTime\n");
-		    }
-		    break;
-		case GrabFrozen:
-		    if (@global(ErrorPrinting) == true) {
-			console_fprintf(stderr, "XWorkstation [warning]: grab keyboard: Frozen\n");
-		    }
-		    break;
-		default:
-		    ok = 1;
-		    break;
-	    }
-	    if (! ok) {
-		ENTER_XLIB();
-		XUngrabKeyboard(myDpy, CurrentTime);
-		LEAVE_XLIB();
-		RETURN (false);
-	    }
-
-	    RETURN ( true );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false
-!
-
-grabPointerIn:aWindowId withCursor:aCursorId eventMask:eventMask pointerMode:pMode keyboardMode:kMode confineTo:confineId
-    "grap the pointer - return true if ok"
-
-    <context: #return>
-%{
-
-    int result, ok, evMask;
-    Window confineWin;
-    Cursor curs;
-    int pointer_mode, keyboard_mode;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aWindowId)) {
-	    if (__isExternalAddress(confineId))
-		confineWin = __WindowVal(confineId);
-	    else
-		confineWin = (Window) None;
-
-	    if (__isExternalAddress(aCursorId))
-		curs = __CursorVal(aCursorId);
-	    else
-		curs = (Cursor) None;
-
-	    if (pMode == @symbol(sync))
-		pointer_mode = GrabModeSync;
-	    else
-		pointer_mode = GrabModeAsync;
-
-	    if (kMode == @symbol(sync))
-		keyboard_mode = GrabModeSync;
-	    else
-		keyboard_mode = GrabModeAsync;
-
-	    if (__isSmallInteger(eventMask))
-		evMask = __intVal(eventMask);
-	    else
-		evMask = ButtonPressMask | ButtonMotionMask | PointerMotionMask | ButtonReleaseMask;
-
-
-/*
-	    ENTER_XLIB();
-*/
-	    result = XGrabPointer(myDpy,
-				  __WindowVal(aWindowId),
-				  False,
-				  evMask,
-				  pointer_mode, keyboard_mode,
-				  confineWin,
-				  curs,
-				  CurrentTime);
-/*
-	    LEAVE_XLIB();
-*/
-
-
-	    ok = 0;
-	    switch (result) {
-		case AlreadyGrabbed:
-		    if (@global(ErrorPrinting) == true) {
-			console_fprintf(stderr, "XWorkstation [warning]: grab pointer: AlreadyGrabbed\n");
-		    }
-		    break;
-		case GrabNotViewable:
-		    if (@global(ErrorPrinting) == true) {
-			console_fprintf(stderr, "XWorkstation [warning]: grab pointer: GrabNotViewable\n");
-		    }
-		    break;
-		case GrabInvalidTime:
-		    if (@global(ErrorPrinting) == true) {
-			console_fprintf(stderr, "XWorkstation [warning]: grab pointer: InvalidTime\n");
-		    }
-		    break;
-		case GrabFrozen:
-		    if (@global(ErrorPrinting) == true) {
-			console_fprintf(stderr, "XWorkstation [warning]: grab pointer: Frozen\n");
-		    }
-		    break;
-		default:
-		    ok = 1;
-		    break;
-	    }
-
-	    if (! ok) {
-/*
-		ENTER_XLIB();
-*/
-		XUngrabPointer(myDpy, CurrentTime);
-/*
-		LEAVE_XLIB();
-*/
-		RETURN (false);
-	    }
-	    RETURN ( true );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false
-!
-
-grabPointerIn:aWindowId withCursor:aCursorId pointerMode:pMode keyboardMode:kMode confineTo:confineId
-    "grap the pointer - return true if ok"
-
-    ^ self
-	grabPointerIn:aWindowId
-	withCursor:aCursorId
-	eventMask:nil
-	pointerMode:pMode
-	keyboardMode:kMode
-	confineTo:confineId
-
-    "Modified: / 28.7.1998 / 02:47:51 / cg"
-!
-
-primUngrabKeyboard
-    "release the keyboard"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	ENTER_XLIB();
-	XUngrabKeyboard(dpy, CurrentTime);
-	XSync(dpy, 0);
-	LEAVE_XLIB();
-
-    }
-%}.
-!
-
-primUngrabPointer
-    "release the pointer"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	ENTER_XLIB();
-	XUngrabPointer(dpy, CurrentTime);
-	XSync(dpy, 0);
-	LEAVE_XLIB();
-
-    }
-%}.
-!
-
-ungrabKeyboard
-    "release the keyboard"
-
-    activeKeyboardGrab notNil ifTrue:[
-	activeKeyboardGrab := nil.
-	self primUngrabKeyboard.
-    ]
-!
-
-ungrabPointer
-    "release the pointer"
-
-    activePointerGrab notNil ifTrue:[
-	activePointerGrab := nil.
-	self primUngrabPointer.
-    ]
-! !
-
-!XWorkstation methodsFor:'graphic context stuff'!
-
-noClipIn:aDrawableId gc:aGCId
-    "disable clipping rectangle"
-
-    <context: #return>
-%{
-
-    XGCValues gcv;
-    GC gc;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)) {
-	    gc = __GCVal(aGCId);
-	    gcv.clip_mask = None;
-	    ENTER_XLIB();
-	    XChangeGC(myDpy, gc, GCClipMask, &gcv);
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setBackground:bgColorIndex in:aGCId
-    "set background color to be drawn with"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)
-	 && __isSmallInteger(bgColorIndex)) {
-	    ENTER_XLIB();
-	    XSetBackground(myDpy, __GCVal(aGCId), __intVal(bgColorIndex));
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setBitmapMask:aBitmapId in:aGCId
-    "set or clear the drawing mask - a bitmap mask using current fg/bg"
-
-    <context: #return>
-%{
-
-    GC gc;
-    Pixmap bitmap;
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	if (__isExternalAddress(aGCId)) {
-	    gc = __GCVal(aGCId);
-	    if (__isExternalAddress(aBitmapId)) {
-		bitmap = __PixmapVal(aBitmapId);
-		ENTER_XLIB();
-		XSetStipple(dpy, gc, bitmap);
-		XSetFillStyle(dpy, gc, FillOpaqueStippled);
-		LEAVE_XLIB();
-		RETURN ( self );
-	    }
-	    if (aBitmapId == nil) {
-		ENTER_XLIB();
-		XSetFillStyle(dpy, gc, FillSolid);
-		LEAVE_XLIB();
-		RETURN ( self );
-	    }
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setClipByChildren:aBool in:aDrawableId gc:aGCId
-    "enable/disable drawing into child views"
-
-    <context: #return>
-%{
-
-    XGCValues gcv;
-    GC gc;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)) {
-	    gc = __GCVal(aGCId);
-	    if (aBool == true)
-		gcv.subwindow_mode = ClipByChildren;
-	    else
-		gcv.subwindow_mode = IncludeInferiors;
-
-	    ENTER_XLIB();
-	    XChangeGC(myDpy, gc, GCSubwindowMode, &gcv);
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setClipX:clipX y:clipY width:clipWidth height:clipHeight in:drawableId gc:aGCId
-    "clip to a rectangle"
-
-    <context: #return>
-%{
-
-    XRectangle r;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)
-	 && __bothSmallInteger(clipX, clipY)
-	 && __bothSmallInteger(clipWidth, clipHeight)) {
-	    r.x = __intVal(clipX);
-	    r.y = __intVal(clipY);
-	    r.width = __intVal(clipWidth);
-	    r.height = __intVal(clipHeight);
-	    ENTER_XLIB();
-	    XSetClipRectangles(myDpy, __GCVal(aGCId), 0, 0, &r, 1, Unsorted);
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setDashes:dashList dashOffset:offset in:aGCId
-    "set line attributes"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)
-	 && __isSmallInteger(offset)
-	 && __isByteArrayLike(dashList)) {
-	    ENTER_XLIB();
-	    XSetDashes(myDpy, __GCVal(aGCId),
-		       __intVal(offset),
-		       __ByteArrayInstPtr(dashList)->ba_element,
-		       __byteArraySize(dashList));
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-bad: ;
-%}.
-    "
-     either aGCId is invalid,
-     and/or dashList is not a byteArray
-     and/or offset is not a smallInteger
-    "
-    self primitiveFailedOrClosedConnection
-!
-
-setFont:aFontId in:aGCId
-    "set font to be drawn in"
-
-    <context: #return>
-%{
-
-    XFontStruct *f;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aFontId)
-	 && __isExternalAddress(aGCId)) {
-	    f = (XFontStruct *) __FontVal(aFontId);
-	    ENTER_XLIB();
-	    XSetFont(myDpy, __GCVal(aGCId), f->fid);
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    "
-     aGCId and/or aFontId are invalid
-    "
-    self primitiveFailedOrClosedConnection
-!
-
-setForeground:fgColorIndex background:bgColorIndex in:aGCId
-    "set foreground and background colors to be drawn with"
-
-    <context: #return>
-%{
-
-    GC gc;
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-	if (__bothSmallInteger(fgColorIndex, bgColorIndex)
-	 && __isExternalAddress(aGCId)) {
-	    gc = __GCVal(aGCId);
-
-	    ENTER_XLIB();
-	    XSetForeground(dpy, gc, __intVal(fgColorIndex));
-	    XSetBackground(dpy, gc, __intVal(bgColorIndex));
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setForeground:fgColorIndex in:aGCId
-    "set foreground color to be drawn with"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)
-	 && __isSmallInteger(fgColorIndex)) {
-	    ENTER_XLIB();
-	    XSetForeground(myDpy, __GCVal(aGCId), __intVal(fgColorIndex));
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setFunction:aFunctionSymbol in:aGCId
-    "set alu function to be drawn with"
-
-    <context: #return>
-%{
-
-    GC gc;
-    int fun = -1;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)) {
-	    gc = __GCVal(aGCId);
-	    if (aFunctionSymbol == @symbol(copy)) fun = GXcopy;
-	    else if (aFunctionSymbol == @symbol(copyInverted)) fun = GXcopyInverted;
-	    else if (aFunctionSymbol == @symbol(xor)) fun = GXxor;
-	    else if (aFunctionSymbol == @symbol(and)) fun = GXand;
-	    else if (aFunctionSymbol == @symbol(andReverse)) fun = GXandReverse;
-	    else if (aFunctionSymbol == @symbol(andInverted)) fun = GXandInverted;
-	    else if (aFunctionSymbol == @symbol(or)) fun = GXor;
-	    else if (aFunctionSymbol == @symbol(orReverse)) fun = GXorReverse;
-	    else if (aFunctionSymbol == @symbol(orInverted)) fun = GXorInverted;
-	    else if (aFunctionSymbol == @symbol(invert)) fun = GXinvert;
-	    else if (aFunctionSymbol == @symbol(clear)) fun = GXclear;
-	    else if (aFunctionSymbol == @symbol(set)) fun = GXset;
-	    else if (aFunctionSymbol == @symbol(noop)) fun = GXnoop;
-	    else if (aFunctionSymbol == @symbol(equiv)) fun = GXequiv;
-	    else if (aFunctionSymbol == @symbol(nand)) fun = GXnand;
-	    if (fun != -1) {
-		ENTER_XLIB();
-		XSetFunction(myDpy, gc, fun);
-		LEAVE_XLIB();
-		RETURN ( self );
-	    }
-	}
-    }
-%}.
-    "
-     either aGCId is not an integer, or an invalid symbol
-     was passed ... valid functions are #copy, #copyInverted, #xor, #and, #andReverse,
-     #andInverted, #or, #orReverse, #orInverted. See Xlib documentation for more details.
-    "
-    self primitiveFailedOrClosedConnection
-!
-
-setGraphicsExposures:aBoolean in:aGCId
-    "set or clear the graphics exposures flag"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)) {
-	    ENTER_XLIB();
-	    XSetGraphicsExposures(myDpy, __GCVal(aGCId), (aBoolean==true)?1:0);
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setLineWidth:aNumber style:lineStyle cap:capStyle join:joinStyle in:aGCId
-    "set line attributes;
-     lineStyle must be one of #solid, #dashed or #doubleDashed;
-     capStyle one of: #notLast, #butt, #round or #projecting;
-     joinStyle one of: #miter, #bevel or #round."
-
-    <context: #return>
-%{
-
-    int x_style, x_cap, x_join;
-    static char dashList[2] = { 1,1 };
-    static char dotList[2]  = { 4,4 };
-    static char dashDotList[4]    = { 4,1 , 1,1 };
-    static char dashDotDotList[6] = { 4,1 , 1,1 , 1,1 };
-    char *x_dashes = 0;
-    int x_nDash;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aGCId)
-	 && __isSmallInteger(aNumber)) {
-	    Display *dpy = myDpy;
-
-	    if (lineStyle == @symbol(solid)) {
-		x_dashes = (char *)0;
-		x_style = LineSolid;
-	    } else if (lineStyle == @symbol(dashed)) {
-		x_dashes = dashList;
-		x_nDash = sizeof(dashList);
-		x_style = LineOnOffDash;
-	    } else if (lineStyle == @symbol(doubleDashed)) {
-		x_dashes = dashList;
-		x_nDash = sizeof(dashList);
-		x_style = LineDoubleDash;
-	    } else if (lineStyle == @symbol(dotted)) {
-		x_dashes = dotList;
-		x_nDash = sizeof(dotList);
-		x_style = LineOnOffDash;
-	    } else if (lineStyle == @symbol(dashDot)) {
-		x_dashes = dashDotList;
-		x_nDash = sizeof(dashDotList);
-		x_style = LineOnOffDash;
-	    } else if (lineStyle == @symbol(dashDotDot)) {
-		x_dashes = dashDotDotList;
-		x_nDash = sizeof(dashDotDotList);
-		x_style = LineOnOffDash;
-	    } else goto bad;
-
-	    if (capStyle == @symbol(notLast)) x_cap = CapNotLast;
-	    else if (capStyle == @symbol(butt)) x_cap = CapButt;
-	    else if (capStyle == @symbol(round)) x_cap  = CapRound;
-	    else if (capStyle == @symbol(projecting)) x_cap  = CapProjecting;
-	    else goto bad;
-
-	    if (joinStyle == @symbol(miter)) x_join = JoinMiter;
-	    else if (joinStyle == @symbol(bevel)) x_join = JoinBevel;
-	    else if (joinStyle == @symbol(round)) x_join  = JoinRound;
-	    else goto bad;
-
-	    ENTER_XLIB();
-	    if (x_dashes) {
-		XSetDashes(dpy, __GCVal(aGCId), 0, x_dashes, x_nDash);
-	    }
-	    XSetLineAttributes(dpy,
-			       __GCVal(aGCId), __intVal(aNumber),
-			       x_style, x_cap, x_join);
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-bad: ;
-%}.
-    "
-     either aGCId is invalid,
-     and/or lineWidth is not a smallInteger,
-     and/or lineStyle is none of #solid, #dashed, #doubleDashed
-     and/or capStyle is none of #notLast, #butt, #round, #projecting
-     and/or joinStyle is none of #miter, #bevel, #round
-    "
-    self primitiveFailedOrClosedConnection
-!
-
-setMaskOriginX:orgX y:orgY in:aGCid
-    "set the mask origin"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-	if (__bothSmallInteger(orgX, orgY) && __isExternalAddress(aGCid)) {
-	    ENTER_XLIB();
-	    XSetTSOrigin(myDpy, __GCVal(aGCid), __intVal(orgX), __intVal(orgY));
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setPixmapMask:aPixmapId in:aGCId
-    "set or clear the drawing mask - a pixmap mask providing full color"
-
-    <context: #return>
-%{
-
-    GC gc;
-    Pixmap pixmap;
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	if (__isExternalAddress(aGCId)) {
-	    gc = __GCVal(aGCId);
-	    if (__isExternalAddress(aPixmapId)) {
-		pixmap = __PixmapVal(aPixmapId);
-		ENTER_XLIB();
-		XSetTile(dpy, gc, pixmap);
-		XSetFillStyle(dpy, gc, FillTiled);
-		LEAVE_XLIB();
-		RETURN ( self );
-	    }
-	    if (aPixmapId == nil) {
-		ENTER_XLIB();
-		XSetFillStyle(dpy, gc, FillSolid);
-		LEAVE_XLIB();
-		RETURN ( self );
-	    }
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-! !
-
-!XWorkstation methodsFor:'initialization & release'!
-
-closeConnection
-    "close down the connection to the X-server"
-
-    <context: #return>
-
-"/ 'closing' errorPrintCR.
-"/ thisContext fullPrintAll.
-
-%{ /* UNLIMITEDSTACK */   /* calls XSync()! */
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-
-	__INST(displayId) = nil;
-	ENTER_XLIB();
-	XCloseDisplay(dpy);
-	LEAVE_XLIB();
-    }
-%}
-!
-
-emergencyCloseConnection
-    "low level close of the displays connection (without sending any buffered
-     requests to the display). Only used in case of emergency (brokenConnection)"
-
-%{
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	__INST(displayId) = nil;
-	close(ConnectionNumber(dpy));
-    }
-%}
-!
-
-eventBufferSize
-%{
-    RETURN ( __MKSMALLINT(sizeof(XEvent) + 100) );
-%}
-!
-
-getWindowGroupWindow
-    "Creates a fake WindowGroup view. This window is used
-     in XWMHints & _NET_WM_LEADER properties to define
-     application window group"
-
-    windowGroupWindow isNil ifTrue:[
-	windowGroupWindow := WindowGroupWindow new create.
-    ].
-    ^ windowGroupWindow
-!
-
-initializeDefaultValues
-    activateOnClick := false.
-    maxOperationsUntilFlush := nil.
-
-    super initializeDefaultValues.
-
-    "JV@2012: On X11, mouse buttons are: left=1, middle=2, right=3
-    Even on 2-button mouse (button 2 is simply not reported).
-    Here the middle button is mapped to button #paste (which in EditTextView
-    pastes the PRIMARY selection). 128 is here to make clear that this
-    is somewhat special value.
-
-    This remapping kludge is here to have all the widget's code backward/windows
-    compatible while still having X11's middle button behavior.
-
-    Also note, that buttonTranslation is overwritten in display.rc,
-    the code is here just for a case display.rc is not read/available
-    and for documentation (symbol references does not search .rc files).
-    "
-
-    buttonTranslation := buttonTranslation copy.
-    buttonTranslation at: 2 put: #paste
-
-    "Modified (comment): / 17-04-2012 / 21:18:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-initializeDeviceSignals
-    super initializeDeviceSignals.
-
-    deviceIOTimeoutErrorSignal := deviceIOErrorSignal newSignal.
-    deviceIOTimeoutErrorSignal nameClass:self message:#deviceIOTimeoutErrorSignal.
-
-    ObjectMemory registerErrorInterruptHandler:self class forID:#DisplayError.
-    ObjectMemory registerErrorInterruptHandler:self class forID:#DisplayIOError.
-    ObjectMemory registerErrorInterruptHandler:self class forID:#DisplayIOTimeoutError.
-!
-
-initializeFor:aDisplayName
-    "initialize the receiver for a connection to an X-Server;
-     the argument, aDisplayName may be nil (for the default server from
-     DISPLAY-variable or command line argument) or the name of the server
-     as hostname:number"
-
-    displayId notNil ifTrue:[
-	"/ already connected - you bad guy try to trick me manually ?
-	^ self
-    ].
-
-    displayId := self openConnectionTo:aDisplayName.
-    displayId isNil ifTrue:[
-	"/ could not connect.
-	DeviceOpenErrorSignal raiseWith:aDisplayName.
-	^ nil
-    ].
-
-    xlibTimeout := xlibTimeout ? DefaultXLibTimeout.
-    xlibTimeoutForWindowCreation := xlibTimeoutForWindowCreation ? DefaultXLibTimeoutForWindowCreation.
-    hasConnectionBroken := false.
-
-    dispatching := false.
-    dispatchingExpose := false.
-    isSlow := false.
-    shiftDown := false.
-    ctrlDown := false.
-    metaDown := false.
-    altDown := false.
-    motionEventCompression := true.
-    buttonsPressed := 0.
-    displayName := aDisplayName.
-
-    listOfXFonts := nil.
-
-    atoms := nil.
-
-    "These values are initialized by primitive code in #createWindowFor:..."
-    protocolsAtom := nil.
-    deleteWindowAtom := nil.
-    saveYourselfAtom := nil.
-    quitAppAtom := nil.
-
-    self initializeDeviceResourceTables.
-    self initializeScreenProperties.
-
-    self initializeDefaultValues.
-    self initializeSpecialFlags.
-    self initializeKeyboardMap.
-    self initializeDeviceSignals.
-
-    self initializeViewStyle.
-!
-
-initializeModifierMappings
-    "initialize keyboard modifiers.
-     We assume that mod1 are the META modifiers and mod2 are the ALT modifiers,
-     but if any of them contains the Num_Lock key, it is disregarded."
-
-    |map|
-
-    super initializeModifierMappings.
-
-    rawKeySymTranslation := RawKeySymTranslation.
-
-    map := self modifierMapping.
-    map isNil ifTrue:[
-	"/
-	"/ mhmh - a crippled Xlib which does not provide modifier mappings
-	"/ setup some reasonable default. If that is not sufficient,
-	"/ you have to change things from your display.rc file.
-	"/
-	altModifierMask := self modifier1Mask.
-	metaModifierMask := self modifier2Mask.
-    ] ifFalse:[
-	| mod symbolFromKeyCode nonNilOnes |
-
-	altModifierMask := 0.
-	metaModifierMask := 0.
-
-	symbolFromKeyCode := [:key | self symbolFromKeycode:key].
-	nonNilOnes := [:str | str notNil].
-
-	mod := map at:1.
-	mod notNil ifTrue:[
-	    shiftModifiers := mod collect:symbolFromKeyCode thenSelect:nonNilOnes.
-	].
-	mod := map at:3.
-	mod notNil ifTrue:[
-	    ctrlModifiers  := mod collect:symbolFromKeyCode thenSelect:nonNilOnes.
-	].
-	mod := map at:4.
-	mod notNil ifTrue:[
-	    mod := mod collect:symbolFromKeyCode thenSelect:nonNilOnes.
-	    (mod includes:#'Num_Lock') ifFalse:[
-		metaModifiers := mod.
-		metaModifierMask := 1 bitShift:(4-1).
-	    ].
-	].
-	mod := map at:5.
-	mod notNil ifTrue:[
-	    mod := mod collect:symbolFromKeyCode thenSelect:nonNilOnes.
-	    (mod includes:#'Num_Lock') ifFalse:[
-		altModifiers   := mod.
-		altModifierMask := 1 bitShift:(5-1).
-	    ].
-	]
-    ].
-
-    "
-     Display initializeModifierMappings
-    "
-
-    "Modified: 1.12.1995 / 23:44:40 / stefan"
-!
-
-initializeScreenBounds
-    self isXineramaActive ifTrue:[
-	|rect|
-
-	self monitorBounds do:[:eachRect|
-	    rect isNil ifTrue:[
-		rect := eachRect.
-	    ] ifFalse:[
-		rect := rect merge:eachRect.
-	    ]
-	].
-	width := rect width.
-	height := rect height.
-
-	"propagate possible size changes to our rottView"
-	rootView notNil ifTrue:[
-	    rootView initialize.
-	].
-    ] ifFalse:[
-	width := self queryWidth.
-	height := self queryHeight.
-    ].
-    widthMM := self queryWidthMM.
-    heightMM := self queryHeightMM.
-
-    "
-      Display initializeScreenBounds
-    "
-!
-
-initializeScreenProperties
-    |masks|
-
-    super initializeScreenProperties.
-
-    hasShapeExtension := self queryShapeExtension.
-    hasShmExtension := self querySHMExtension.
-    hasDPSExtension := self queryDPSExtension.
-    hasXVideoExtension := self queryXVideoExtension.
-    hasMbufExtension := self queryMBUFExtension.
-    hasPEXExtension := self queryPEXExtension.
-    hasImageExtension := self queryXIEExtension.
-    hasInputExtension := self queryXIExtension.
-    hasXineramaExtension := self queryXineramaExtension.
-    hasRenderExtension := self queryRenderExtension.
-    hasXftLibrary := self queryXftLibrary.
-
-    primaryAtom := self atomIDOf:#PRIMARY.
-    stringAtom := self atomIDOf:#STRING.
-    clipboardAtom := self atomIDOf:#CLIPBOARD.
-
-    altModifierMask := self modifier2Mask.
-    metaModifierMask := self modifier1Mask.
-
-    screen := self queryDefaultScreen.
-
-    self initializeScreenBounds.
-
-    depth := self queryDepth.
-    ncells := self queryCells.
-    blackpixel := self queryBlackPixel.
-    whitepixel := self queryWhitePixel.
-
-    monitorType := #unknown.
-    visualType := self queryDefaultVisualType.
-
-    hasColors := hasGreyscales := true.
-    (visualType == #StaticGray
-     or:[ visualType == #GrayScale]) ifTrue:[
-	hasColors := false.
-	monitorType := #monochrome.
-    ].
-
-    ncells == 2 ifTrue:[
-	hasColors := hasGreyscales := false.
-    ].
-
-    masks := self queryRGBMasks.
-    redMask := masks at:1.
-    greenMask := masks at:2.
-    blueMask := masks at:3.
-    bitsPerRGB := masks at:4.
-
-    visualType == #TrueColor ifTrue:[
-	redShift := redMask lowBit - 1.
-	greenShift := greenMask lowBit - 1.
-	blueShift := blueMask lowBit - 1.
-
-	bitsRed := redMask highBit - redMask lowBit + 1.
-	bitsGreen := greenMask highBit - greenMask lowBit + 1.
-	bitsBlue := blueMask highBit - blueMask lowBit + 1.
-    ].
-
-%{
-
-    Display *dpy;
-    int scr;
-    Visual *visual;
-    XVisualInfo viproto;
-    XVisualInfo *vip;                   /* returned info */
-    int maxRGBDepth, maxRGBADepth;
-    int rgbRedMask, rgbGreenMask, rgbBlueMask;
-    int rgbaRedMask, rgbaGreenMask, rgbaBlueMask, rgbaAlphaMask;
-    int rgbVisualID, rgbaVisualID;
-    int nvi, i;
-    char *type, *nm;
-    int dummy;
-
-    if (ISCONNECTED) {
-	dpy = myDpy;
-
-	/*
-	 * look for RGB visual with the highest depth
-	 */
-	nvi = 0;
-	viproto.screen = scr;
-	vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi);
-	maxRGBDepth = maxRGBADepth = 0;
-	for (i = 0; i < nvi; i++) {
-	    int thisDepth = vip[i].depth;
-
-	    switch (vip[i].class) {
-		case TrueColor:
-		    if (thisDepth > maxRGBDepth) {
-			if (thisDepth <= 24) {
-			    maxRGBDepth = thisDepth;
-			    rgbRedMask = vip[i].red_mask;
-			    rgbGreenMask = vip[i].green_mask;
-			    rgbBlueMask = vip[i].blue_mask;
-			    rgbVisualID = vip[i].visualid;
-			} else {
-			    if (thisDepth > maxRGBADepth) {
-				// printf("found rgba visual!\n");
-				maxRGBADepth = thisDepth;
-				rgbaRedMask = vip[i].red_mask;
-				rgbaGreenMask = vip[i].green_mask;
-				rgbaBlueMask = vip[i].blue_mask;
-				rgbaVisualID = vip[i].visualid;
-			    }
-			}
-		    }
-		    break;
-	    }
-	}
-	if (vip) XFree ((char *) vip);
-
-	if (maxRGBDepth) {
-	    __INST(rgbVisual) = __MKEXTERNALADDRESS(rgbVisualID); __STORESELF(rgbVisual);
-	}
-	if (maxRGBADepth) {
-	    __INST(rgbaVisual) = __MKEXTERNALADDRESS(rgbaVisualID); __STORESELF(rgbaVisual);
-	    if (!maxRGBDepth) {
-		__INST(rgbVisual) = __INST(rgbaVisual); __STORESELF(rgbVisual);
-	    }
-	}
-    }
-%}.
-!
-
-initializeSpecialFlags
-    "perform additional special server implementation flags"
-
-    "/
-    "/ assume we have it ... (should check)
-    "/
-    hasSaveUnder := true.
-    ignoreBackingStore := false.
-
-    (self serverVendor = 'X11/NeWS') ifTrue:[
-	"/
-	"/ this is a kludge around a bug in the X11/NeWS server,
-	"/ which does not correctly handle saveUnder
-	"/
-	hasSaveUnder := false.
-    ].
-!
-
-initializeUniqueID
-    uniqueDeviceID isNil ifTrue:[
-	uniqueDeviceID := UUID genUUID.
-    ]
-!
-
-openConnectionTo:dpyName
-    "open a connection to some display;
-     return the displayId if ok, nil of not ok"
-
-%{ /* STACK:100000 */    /* XOpenDisplay() calls gethostbyname() */
-    Display *dpy;
-    int i;
-    char *nm;
-
-    if (__isStringLike(dpyName))
-	nm = (char *) __stringVal(dpyName);
-    else {
-	nm = NULL;
-    }
-    dpy = XOpenDisplay(nm);
-
-    if (dpy) {
-	static int firstCall = 1;
-	OBJ dpyID;
-
-	dpyID = __MKEXTERNALADDRESS(dpy);
-
-	if (firstCall) {
-	    firstCall = 0;
-	    XSetErrorHandler(__XErrorHandler__);
-	    XSetIOErrorHandler(__XIOErrorHandler__);
-	}
-	RETURN (dpyID);
-    }
-%}.
-    ^ nil
-!
-
-queryBlackPixel
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	int scr;
-
-	dpy = myDpy;
-	scr = DefaultScreen(dpy);
-	RETURN ( __MKSMALLINT(BlackPixel(dpy, scr)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryBlackPixel
-    "
-!
-
-queryCells
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	int scr;
-
-	dpy = myDpy;
-	scr = DefaultScreen(dpy);
-	RETURN ( __MKSMALLINT(DisplayCells(dpy, scr)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryCells
-    "
-!
-
-queryDPSExtension
-%{  /* NOCONTEXT */
-
-#ifdef DPS
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XQueryExtension(dpy, "DPSExtension", &dummy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryDPSExtension
-    "
-!
-
-queryDefaultScreen
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-
-	dpy = myDpy;
-	RETURN ( __MKSMALLINT(DefaultScreen(dpy)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryDefaultScreen
-    "
-!
-
-queryDefaultVisualType
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	Visual *visual;
-
-	dpy = myDpy;
-	visual = DefaultVisualOfScreen(DefaultScreenOfDisplay(dpy));
-	switch (visual->class) {
-	    case StaticGray:
-		RETURN ( @symbol(StaticGray) );
-	    case GrayScale:
-		RETURN ( @symbol(GrayScale) );
-	    case StaticColor:
-		RETURN ( @symbol(StaticColor) );
-	    case PseudoColor:
-		RETURN ( @symbol(PseudoColor) );
-	    case TrueColor:
-		RETURN ( @symbol(TrueColor) );
-	    case DirectColor:
-		RETURN ( @symbol(DirectColor) );
-	}
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryDefaultVisualType
-    "
-!
-
-queryDepth
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	int scr;
-
-	dpy = myDpy;
-	scr = DefaultScreen(dpy);
-	RETURN ( __MKSMALLINT(DisplayPlanes(dpy, scr)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryDepth
-    "
-!
-
-queryHeight
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	int scr;
-
-	dpy = myDpy;
-	scr = DefaultScreen(dpy);
-	RETURN ( __MKSMALLINT(DisplayHeight(dpy, scr)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryHeight
-    "
-!
-
-queryHeightMM
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	int scr;
-
-	dpy = myDpy;
-	scr = DefaultScreen(dpy);
-	RETURN ( __MKSMALLINT(DisplayHeightMM(dpy, scr)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryHeightMM
-    "
-!
-
-queryMBUFExtension
-%{  /* NOCONTEXT */
-
-#ifdef MBUF
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XQueryExtension(dpy, "Multi-Buffering", &dummy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryMBUFExtension
-    "
-!
-
-queryPEXExtension
-%{  /* NOCONTEXT */
-
-#ifdef PEX5
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XQueryExtension(dpy, PEX_NAME_STRING, &dummy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryPEXExtension
-    "
-!
-
-queryRGBMasks
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	Visual *visual;
-	OBJ redMask, greenMask, blueMask, bprgb;
-
-	dpy = myDpy;
-	visual = DefaultVisualOfScreen(DefaultScreenOfDisplay(dpy));
-	redMask   = __MKSMALLINT(visual->red_mask);
-	greenMask = __MKSMALLINT(visual->green_mask);
-	blueMask  = __MKSMALLINT(visual->blue_mask);
-	bprgb  = __MKSMALLINT(visual->bits_per_rgb);
-	RETURN ( __ARRAY_WITH4(redMask, greenMask, blueMask, bprgb) );
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryRGBMasks
-    "
-!
-
-queryRenderExtension
-%{  /* NOCONTEXT */
-
-#ifdef XRENDER
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XRenderQueryExtension (dpy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryRenderExtension
-    "
-!
-
-querySHMExtension
-%{  /* NOCONTEXT */
-
-#ifdef xxSHM
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XQueryExtension(dpy, "MIT_SHM", &dummy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display querySHMExtension
-    "
-!
-
-queryShapeExtension
-%{  /* NOCONTEXT */
-
-#ifdef SHAPE
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XShapeQueryExtension(dpy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryShapeExtension
-    "
-!
-
-queryWhitePixel
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	int scr;
-
-	dpy = myDpy;
-	scr = DefaultScreen(dpy);
-	RETURN ( __MKSMALLINT(WhitePixel(dpy, scr)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryWhitePixel
-    "
-!
-
-queryWidth
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	int scr;
-
-	dpy = myDpy;
-	scr = DefaultScreen(dpy);
-	RETURN ( __MKSMALLINT(DisplayWidth(dpy, scr)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryWidth
-    "
-!
-
-queryWidthMM
-%{  /* NOCONTEXT */
-
-    if (ISCONNECTED) {
-	Display *dpy;
-	int scr;
-
-	dpy = myDpy;
-	scr = DefaultScreen(dpy);
-	RETURN ( __MKSMALLINT(DisplayWidthMM(dpy, scr)));
-    }
-%}.
-    ^ nil
-
-    "
-     Display queryWidthMM
-    "
-!
-
-queryXIEExtension
-%{  /* NOCONTEXT */
-
-#ifdef XIE
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XQueryExtension(dpy, xieExtName, &dummy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryXIEExtension
-    "
-!
-
-queryXIExtension
-%{  /* NOCONTEXT */
-
-#ifdef XI
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XQueryExtension(dpy, "XInputExtension", &dummy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryXIExtension
-    "
-!
-
-queryXVideoExtension
-%{  /* NOCONTEXT */
-
-#ifdef XVIDEO
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XQueryExtension(dpy, "XVideo", &dummy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryXVideoExtension
-    "
-!
-
-queryXftLibrary
-%{
-#ifndef XFT
-    RETURN (false);
-#endif
-%}.
-    ^ self queryRenderExtension
-!
-
-queryXineramaExtension
-%{  /* NOCONTEXT */
-
-#ifdef XINERAMA
-    if (ISCONNECTED) {
-	Display *dpy;
-	int dummy;
-
-	dpy = myDpy;
-
-	if (XineramaQueryExtension (dpy, &dummy, &dummy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display queryXineramaExtension
-    "
-!
-
-reinitialize
-    preWaitAction notNil ifTrue:[
-	Processor removePreWaitAction:preWaitAction.
-	preWaitAction := nil.
-    ].
-    virtualRootId := rootId := nil.
-    selectionFetchers := nil.
-    super reinitialize.
-    dispatchingExpose := nil
-!
-
-releaseDeviceResources
-    preWaitAction notNil ifTrue:[
-	Processor removePreWaitAction:preWaitAction.
-	preWaitAction := nil.
-    ].
-    selectionFetchers := nil.
-    super releaseDeviceResources.
-! !
-
-!XWorkstation methodsFor:'keyboard mapping'!
-
-altModifierMask
-    "return the mask (in motionEvents) for the alt-key modifier.
-     Notice: ST/X may use the left ALT key as CMD/Meta key,
-     therefore return a variable here, which can be changed during startup."
-
-    ^ altModifierMask
-
-    "Created: 23.3.1996 / 12:43:22 / cg"
-    "Modified: 23.3.1996 / 12:44:56 / cg"
-!
-
-altModifierMask:aSmallInteger
-    "define which key takes the role of an alt-key.
-     By default, this is X's modifier1, which is the ALT key on
-     most keyboards. However, there may be exceptions to this,
-     and the setting can be changed with:
-	Display altModifierMask:(Display modifier2Mask)
-     Setting the mask to 0 disables the ALT key (in ST/X) altogether.
-    "
-
-    altModifierMask := aSmallInteger
-!
-
-ctrlModifierMask
-    "return the Xlib mask bit for the control modifier key"
-
-%{  /* NOCONTEXT */
-    RETURN (__MKSMALLINT(ControlMask));
-%}
-!
-
-metaModifierMask
-    "return the mask (in motionEvents) for the meta-key modifier.
-     Notice: ST/X may use the left ALT key as CMD/Meta key,
-     therefore return a variable here, which can be changed during startup."
-
-    ^ metaModifierMask
-
-    "Created: 23.3.1996 / 12:43:39 / cg"
-    "Modified: 23.3.1996 / 12:45:09 / cg"
-!
-
-metaModifierMask:aSmallInteger
-    "define which key takes the role of a meta key.
-     By default, this is X's modifier2, which is the 2nd ALT key on
-     most keyboards (if present at all).
-     However, there may be exceptions to this, and the setting can
-     be changed with:
-	Display metaModifierMask:(Display modifier1Mask)
-     Setting the mask to 0 disables the META key (in ST/X) altogether.
-     As reported, some Xservers place the Meta-key onto NumLock,
-     and having NumLock enabled makes ST/X think, that meta is pressed
-     all the time. On those, you should disable the meta key by setting
-     the mask to 0.
-    "
-
-    metaModifierMask := aSmallInteger
-!
-
-modifier1Mask
-    "return the Xlib mask bit for the 1st modifier key.
-     See comment in altModifierMask: / metaModifierMask: for what
-     this could be used."
-
-%{  /* NOCONTEXT */
-    RETURN (__MKSMALLINT(Mod1Mask));
-%}
-!
-
-modifier2Mask
-    "return the Xlib mask bit for the 2nd modifier key.
-     See comment in altModifierMask: / metaModifierMask: for what
-     this could be used."
-
-%{  /* NOCONTEXT */
-    RETURN (__MKSMALLINT(Mod2Mask));
-%}
-!
-
-modifier3Mask
-    "return the Xlib mask bit for the 3rd modifier key.
-     See comment in altModifierMask: / metaModifierMask: for what
-     this could be used."
-
-%{  /* NOCONTEXT */
-    RETURN (__MKSMALLINT(Mod3Mask));
-%}
-!
-
-modifier4Mask
-    "return the Xlib mask bit for the 4th modifier key.
-     See comment in altModifierMask: / metaModifierMask: for what
-     this could be used."
-
-%{  /* NOCONTEXT */
-    RETURN (__MKSMALLINT(Mod4Mask));
-%}
-!
-
-modifier5Mask
-    "return the Xlib mask bit for the 5th modifier key.
-     See comment in altModifierMask: / metaModifierMask: for what
-     this could be used."
-
-%{  /* NOCONTEXT */
-    RETURN (__MKSMALLINT(Mod5Mask));
-%}
-!
-
-modifierMapping
-    "Get the Modifier Mapping.
-     We return an array of arrays of keycodes"
-
-    |modifierKeyMap maxKeyPerMod ret nextKey|
-
-    modifierKeyMap := self rawModifierMapping.
-    modifierKeyMap isEmptyOrNil ifTrue:[^ nil].
-    maxKeyPerMod := modifierKeyMap size // 8.
-
-    ret := Array new:8.
-    nextKey := 1.
-    1 to:8 do:[ :i |
-	(modifierKeyMap at:nextKey) ~= 0 ifTrue:[
-	    |mod|
-
-	    mod := OrderedCollection new:maxKeyPerMod.
-	    modifierKeyMap from:nextKey to:(nextKey+maxKeyPerMod-1) do:[ :key |
-		key ~= 0 ifTrue:[
-		    mod add:key
-		].
-	    ].
-	    ret at:i put:mod asArray.
-	].
-	nextKey := nextKey+maxKeyPerMod.
-    ].
-
-    ^ ret
-
-    "
-     Display modifierMapping
-    "
-
-    "
-     |mapping|
-
-     mapping := Display modifierMapping.
-     ^ mapping collect:[:eachRow |
-			     eachRow notNil ifTrue:[
-				 eachRow collect:[ :key | Display stringFromKeycode:key ].
-			     ] ifFalse:[
-				 nil
-			     ]
-		       ].
-    "
-!
-
-rawKeySymTranslation
-    "Get the raw keyboard mapping (maps some special X-keySyms to STX-internal names
-     and can also be used to untranslate a stupid x-mapping (as on hpux)."
-
-    ^ rawKeySymTranslation
-
-
-    "
-     Display rawKeySymTranslation
-    "
-!
-
-rawModifierMapping
-    "Get the raw Modifier Mapping."
-
-    |modifierKeyMap|
-
-%{
-    XModifierKeymap *modmap;
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	if ((modmap = XGetModifierMapping(dpy)) != 0) {
-	   modifierKeyMap = __BYTEARRAY_UNINITIALIZED_NEW_INT(modmap->max_keypermod * 8);
-	   if (modifierKeyMap != nil) {
-		memcpy((char *)__ByteArrayInstPtr(modifierKeyMap)->ba_element,
-		       (char *)modmap->modifiermap, modmap->max_keypermod * 8);
-	   }
-	   XFreeModifiermap(modmap);
-	}
-    }
-%}.
-    ^ modifierKeyMap
-
-    "
-	Display rawModifierMapping
-    "
-!
-
-shiftModifierMask
-    "return the Xlib mask bit for the shift modifier key"
-
-%{  /* NOCONTEXT */
-    RETURN (__MKSMALLINT(ShiftMask));
-%}
-!
-
-superModifierMask
-    "return the Xlib mask bit for the super modifier key"
-
-    ^ self modifier4Mask
-!
-
-symbolFromKeycode:code
-    "Get a KeySymbol (a smalltalk symbol) from the keycode."
-
-    |str|
-
-%{
-    KeySym keysym;
-    char *keystring;
-
-    if (ISCONNECTED && __isSmallInteger(code)) {
-	Display *dpy = myDpy;
-
-// Our Windows Xlib does not support Xkb as of 2013-01
-//        if ((keysym = XkbKeycodeToKeysym(dpy, __intVal(code), 0, 0)) != NoSymbol
-	if ((keysym = XKeycodeToKeysym(dpy, __intVal(code), 0)) != NoSymbol
-	    && (keystring = XKeysymToString(keysym)) != 0)
-	    str = __MKSYMBOL(keystring, 0);
-    }
-%}.
-    ^ str
-
-    "
-	Display symbolFromKeycode:50
-    "
-! !
-
-!XWorkstation methodsFor:'misc'!
-
-beep
-    "output an audible beep or bell"
-
-    UserPreferences current beepEnabled ifTrue:[
-	self beep:0 volume:50
-    ]
-
-    "Modified: / 3.12.1999 / 17:13:59 / ps"
-!
-
-beep:aSymbolOrInteger volume:volumeInPercent
-    "output an audible beep. aSymbolOrInteger determines the sound, but is ignored here
-     (kept for comaptibilty with WinWorkstation)."
-
-    <context: #return>
-%{
-    int volume;
-
-    if (__isSmallInteger(volumeInPercent)
-     && ISCONNECTED) {
-	/* stupid: X wants -100 .. 100 and calls this percent */
-	volume = __intVal(volumeInPercent) * 2 - 100;
-	if (volume < -100) volume = -100;
-	else if (volume > 100) volume = 100;
-
-	ENTER_XLIB();
-	XBell(myDpy, volume);
-	LEAVE_XLIB();
-    }
-%}
-!
-
-buffered
-    "buffer drawing - do not send it immediately to the display.
-     This is the default anyway.
-     See #unBuffered for additional info."
-
-    <context: #return>
-%{
-    if (ISCONNECTED) {
-	ENTER_XLIB();
-	XSynchronize(myDpy, 0);
-	LEAVE_XLIB();
-    }
-%}
-    "
-     Display buffered
-    "
-!
-
-flush
-    "send all buffered drawing to the display.
-     This may be required to make certain, that all previous operations
-     are really sent to the display before continuing. For example,
-     after a cursor-change with a followup long computation.
-     (otherwise, the cursor change request may still be in the output buffer)
-     See also #sync, which even waits until the request has been processed."
-
-    <context: #return>
-%{
-    if (ISCONNECTED) {
-	ENTER_XLIB();
-	XFlush(myDpy);
-	LEAVE_XLIB();
-    }
-%}.
-
-    operationsUntilFlush := maxOperationsUntilFlush.
-!
-
-flushDpsContext:aDPSContext
-    <context: #return>
-%{
-#ifdef DPS
-    if (ISCONNECTED
-	&& __isExternalAddress(aDPSContext)) {
-	ENTER_XLIB();
-	DPSFlushContext(__DPSContextVal(aDPSContext));
-	LEAVE_XLIB();
-
-	RETURN ( self );
-    }
-#endif
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-primSync
-    "send all buffered drawing to the display AND wait until the display
-     has finished drawing it.
-     This is almost never needed, except if you are about to read previously
-     drawn pixels back from the display screen, or you want to wait for a beep
-     to be finished. See also #flush."
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-
-	ENTER_XLIB();
-	XSync(myDpy, 0);
-	LEAVE_XLIB();
-
-    }
-%}.
-    operationsUntilFlush := maxOperationsUntilFlush.
-!
-
-refreshKeyboardMapping:eB
-    <context: #return>
-%{
-    XMappingEvent *ev;
-
-    if (ISCONNECTED && __isByteArrayLike(eB)) {
-	ev = (XMappingEvent *)(__ByteArrayInstPtr(eB)->ba_element);
-	ENTER_XLIB();
-	XRefreshKeyboardMapping(ev);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-roundTripTime
-    "answer the round trip time in milliSeconds.
-     May be used to detect slow X11 connections"
-
-    self sync.
-    ^ Timestamp millisecondsToRun:[ self primSync ].
-
-    "
-     Screen current roundTripTime
-    "
-!
-
-setInputFocusTo:aWindowId
-    "set the focus to the view as defined by aWindowId.
-     When released, return the focus to the root window"
-
-"/    self setInputFocusTo:aWindowId revertTo:#parent
-    self setInputFocusTo:aWindowId revertTo:#root
-!
-
-setInputFocusTo:aWindowId revertTo:revertSymbol
-    "set the focus to the view as defined by aWindowId.
-     Passing nil set the focus to no window and lets the display discard all
-     input until a new focus is set.
-     RevertSymbol specifies what should happen if the view becomes invisible;
-     passing one of #parent, #root or nil specifies that the focus should be
-     given to the parent view, the root view or no view."
-
-    <context: #return>
-%{
-    int arg;
-    Window focusWindow;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aWindowId)) {
-	    focusWindow = __WindowVal(aWindowId);
-	} else if (aWindowId == nil) {
-	    focusWindow = None;
-	} else
-	    goto err;
-	if (revertSymbol == @symbol(parent))
-	    arg = RevertToParent;
-	else if (revertSymbol == @symbol(root))
-	    arg = RevertToPointerRoot;
-	else
-	    arg = RevertToNone;
-
-
-	ENTER_XLIB();
-	XSetInputFocus(myDpy, focusWindow, arg, CurrentTime);
-	LEAVE_XLIB();
-
-	RETURN ( self );
-    }
-err:;
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-sync
-    "send all buffered drawing to the display AND wait until the display
-     has finished drawing it.
-     This is almost never needed, except if you are about to read previously
-     drawn pixels back from the display screen, or you want to wait for a beep
-     to be finished. See also #flush."
-
-    self primSync.
-    self dispatchPendingEvents.
-!
-
-unBuffered
-    "make all drawing be sent immediately to the display.
-     This makes all graphics synchronous and turns off any buffering
-     (i.e. each individual draw-request is sent immediately without
-      packing multiple requests into a larger message buffer).
-     Be prepared, that this slows down graphics considerably.
-     However, it allows display errors to be handled immediately and
-     may be useful if you get Xdisplay errors and want to find the request
-     which was responsible for it. See also #buffered."
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-
-	ENTER_XLIB();
-	XSynchronize(myDpy, 1);
-	LEAVE_XLIB();
-
-    }
-%}
-    "
-     Display unBuffered
-    "
-! !
-
-!XWorkstation methodsFor:'pointer stuff'!
-
-anyButtonStateMask
-    "return an integer for masking out any button from a
-     buttonStates value."
-
-    "/ should use ``Display buttonXMotionMask bitOr:....''
-
-    ^ 256 + 512 + 1024
-
-    "Modified: 23.3.1996 / 12:41:33 / cg"
-    "Created: 23.3.1996 / 12:46:35 / cg"
-!
-
-buttonStates
-    "return an integer representing the state of the pointer buttons;
-     a one-bit in positions 0.. represent a pressed button.
-     See the button1Mask/button2Mask/button3Mask,
-     shiftMask/controlMask and modifierMask methods for the meaning of the bits."
-
-    <context: #return>
-%{
-    Window w;
-    int screen = __intVal(__INST(screen));
-    Window rootRet, childRet;
-    int rootX, rootY, winX, winY;
-    unsigned int mask;
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	w = RootWindow(dpy, screen);
-	if (w) {
-
-	    ENTER_XLIB();
-	    XQueryPointer(dpy, w, &rootRet, &childRet,
-				 &rootX, &rootY,
-				 &winX, &winY,
-				 &mask);
-	    LEAVE_XLIB();
-
-	    RETURN (__MKSMALLINT(mask));
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ nil
-
-    "
-     Display buttonStates
-    "
-
-    "is the control-key pressed ?
-
-     Display buttonStates bitTest:(Display controlMask)
-    "
-
-    "is the alt/meta-key pressed ?
-
-     Display buttonStates bitTest:(Display altModifierMask)
-     Display buttonStates bitTest:(Display metaModifierMask)
-    "
-!
-
-leftButtonStateMask
-    "return an integer for masking out the left button from a
-     buttonStates value"
-
-    "/ should use ``Display button1MotionMask''
-
-    ^ 256
-
-    "Modified: 23.3.1996 / 12:41:33 / cg"
-!
-
-middleButtonStateMask
-    "return an integer for masking out the middle button from a
-     buttonStates value"
-
-    "/ should use ``Display button2MotionMask''
-
-    ^ 512
-
-    "Modified: 23.3.1996 / 12:41:43 / cg"
-!
-
-pointerPosition
-    "return the current pointer position in (virtual) root-window coordinates"
-
-    <context: #return>
-
-    |xpos ypos rootWindowId|
-
-    rootWindowId := self rootWindowId.
-
-%{
-    int screen = __intVal(__INST(screen));
-    Window rootRet, childRet;
-    int rootX, rootY, winX, winY;
-    unsigned int mask;
-
-    if (ISCONNECTED && rootWindowId != nil) {
-	Display *dpy = myDpy;
-	Window w = (Window)__externalAddressVal(rootWindowId);
-
-	ENTER_XLIB();
-	XQueryPointer(dpy, w, &rootRet, &childRet,
-			      &rootX, &rootY,
-			      &winX, &winY,
-			      &mask);
-	LEAVE_XLIB();
-	xpos = __MKSMALLINT(rootX);
-	ypos = __MKSMALLINT(rootY);
-
-    }
-%}.
-    xpos isNil ifTrue:[
-	self primitiveFailedOrClosedConnection.
-	^ nil
-    ].
-    ^ xpos @ ypos
-!
-
-rightButtonStateMask
-    "return an integer for masking out the right button from a
-     buttonStates value"
-
-    "/ should use ``Display button3MotionMask''
-
-    ^ 1024
-
-    "Modified: 23.3.1996 / 12:41:52 / cg"
-!
-
-rootPositionOfLastEvent
-    "return the position in root-window coordinates
-     of the last button, key or pointer event"
-
-    ^ eventRootX @ eventRootY
-!
-
-setPointerPosition:newPosition in:aWindowId
-    "change the pointer position to a new position relative to the
-     given windows origin (which may be the rootWindow).
-     Be careful with this - its usually not very ergonomically
-     to change the mousePointer position.
-     This interface is provided for special applications (presentation
-     playback) and should not be used in normal applications."
-
-    <context: #return>
-
-    |xpos ypos|
-
-    xpos := newPosition x.
-    ypos := newPosition y.
-
-%{
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __bothSmallInteger(xpos, ypos)) {
-	Display *dpy = myDpy;
-	Window w = __WindowVal(aWindowId);
-
-	ENTER_XLIB();
-	XWarpPointer(dpy,
-		     None,  /* src window */
-		     w,  /* dst window */
-		     0,  /* src_x */
-		     0,  /* src_y */
-		     0,  /* src_w */
-		     0,  /* src_h */
-		     __intVal(xpos),  /* dst_x */
-		     __intVal(ypos)   /* dst_y */
-		    );
-	LEAVE_XLIB();
-    }
-%}.
-    ^ self
-
-    "
-     Display setPointerPosition:1000@1000
-    "
-! !
-
-!XWorkstation methodsFor:'private'!
-
-addSelectionHandler:someone
-    "register someone to be notified when the selection changes"
-
-    selectionHandlers isNil ifTrue:[
-	selectionHandlers := IdentitySet new.
-    ].
-    selectionHandlers add:someone
-!
-
-findSelectionFetcher:aDrawableId
-    "find the SelectionFetcher that receives selection events for aDrawableId.
-     Answer nil, if there is none"
-
-    selectionFetchers isNil ifTrue:[
-	^ nil.
-    ].
-
-    ^ selectionFetchers at:aDrawableId ifAbsent:[].
-!
-
-registerSelectionFetcher:aSelectionFetcher
-    "register a SelectionFetcher that receives selection events for aDrawableId"
-
-    selectionFetchers isNil ifTrue:[
-	selectionFetchers := Dictionary new.
-    ].
-
-    selectionFetchers at:aSelectionFetcher drawableID put:aSelectionFetcher.
-!
-
-removeSelectionHandler:someone
-    "no longer tell someone about selection changes"
-
-    selectionHandlers notNil ifTrue:[
-	selectionHandlers remove:someone ifAbsent:nil.
-	selectionHandlers := selectionHandlers asNilIfEmpty
-    ].
-!
-
-unregisterSelectionFetcher:aSelectionFetcher
-    "unregister a SelectionFetcher that received selection events for aDrawableId"
-
-    selectionFetchers removeKey:aSelectionFetcher drawableID.
-! !
-
-!XWorkstation methodsFor:'properties'!
-
-deleteProperty:propertyID for:aWindowID
-    "delete a property in the XServer"
-
-    <context: #return>
-
-%{
-    if (ISCONNECTED && __isAtomID(propertyID)) {
-	Display *dpy = myDpy;
-	Atom prop;
-	Window window;
-
-	prop = __AtomVal(propertyID);
-
-	if (__isExternalAddress(aWindowID)) {
-	    window = __WindowVal(aWindowID);
-	} else if (aWindowID == nil) {
-	    window = DefaultRootWindow(dpy);
-	} else if (__isInteger(aWindowID)) {
-	    window = (Window)__unsignedLongIntVal(aWindowID);
-	} else {
-	    goto fail;
-	}
-
-	ENTER_XLIB();
-	XDeleteProperty(dpy, window, prop);
-	LEAVE_XLIB();
-	RETURN(true);
-    }
-fail:;
-%}.
-    self primitiveFailedOrClosedConnection.
-!
-
-getProperty:propertySymbolOrAtomID from:aWindowOrWindowIDOrNil delete:doDelete
-    "get a property as an association propertyType->propertyValue"
-
-    <context: #return>
-
-    |val typeID propertyID windowID|
-
-    propertySymbolOrAtomID isString ifTrue:[
-	propertyID := self atomIDOf:propertySymbolOrAtomID create:false.
-	propertyID isNil ifTrue:[^ nil].
-    ] ifFalse:[
-	propertyID := propertySymbolOrAtomID.
-    ].
-    aWindowOrWindowIDOrNil isView ifTrue:[
-	windowID := aWindowOrWindowIDOrNil id.
-    ] ifFalse:[
-	windowID := aWindowOrWindowIDOrNil.
-    ].
-
-%{
-    Window window;
-    Atom property;
-    char *cp, *cp2;
-    Atom actual_type;
-    int actual_format;
-    unsigned long nitems, bytes_after, nread;
-    unsigned char *data;
-    int ok = 1;
-#   define PROP_SIZE    2048
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	if (__isAtomID(propertyID)) {
-	    property = __AtomVal(propertyID);
-
-	    if (__isExternalAddress(windowID)) {
-		window = __WindowVal(windowID);
-	    } else if (windowID == nil) {
-		window = DefaultRootWindow(dpy);
-	    } else
-		goto fail;
-
-	    nread = 0;
-	    cp = 0;
-#ifdef PROPERTY_DEBUG
-	    console_fprintf(stderr, "getProperty %x\n", property);
-#endif
-
-	    do {
-		int retVal;
-
-		ENTER_XLIB();
-		retVal = XGetWindowProperty(dpy, window, property, nread/4, PROP_SIZE,
-					    doDelete == true,
-					    AnyPropertyType, &actual_type, &actual_format,
-					    &nitems, &bytes_after, (unsigned char **)&data);
-		LEAVE_XLIB();
-		if (retVal != Success) {
-#ifdef PROPERTY_DEBUG
-		    console_fprintf(stderr, "- no success\n");
-#endif
-		    ok = 0;
-		    break;
-		}
-#ifdef PROPERTY_DEBUG
-		console_fprintf(stderr, "- type:%x\n", actual_type);
-#endif
-		nitems *= (actual_format / 8);
-		typeID = __MKATOMOBJ(actual_type);
-		if (! cp) {
-		    cp = cp2 = (char *)malloc(nitems+bytes_after);
-		} else {
-		    cp2 = cp + nread;
-		}
-		if (! cp) {
-		    XFree(data);
-		    goto fail;
-		}
-
-		nread += nitems;
-		bcopy(data, cp2, nitems);
-		XFree(data);
-#ifdef PROPERTY_DEBUG
-		console_fprintf(stderr, "- <nitems:%d bytes_after:%d>\n", nitems, bytes_after);
-#endif
-	    } while (bytes_after > 0);
-
-	    if (ok) {
-		switch (actual_format) {
-		case 32:
-		    val = __stArrayFromCUIntArray((unsigned int*)cp, nread/4);
-		    break;
-		case 16:
-		    val = __stArrayFromCUShortArray((unsigned short*)cp, nread/2);
-		    break;
-		case 8:
-		default:
-		    if (actual_type == XA_STRING) {
-			val = __MKSTRING_L(cp, nread);
-		    } else {
-			val = __MKBYTEARRAY(cp, nread);
-		    }
-		    break;
-		}
-	    }
-	    if (cp)
-		free(cp);
-	}
-    }
-fail: ;
-%}.
-    (typeID isNil or:[typeID == 0]) ifTrue:[
-	"typeID == 0 (None): The property does not exist in the specified window"
-	^ nil
-    ].
-    ^ typeID->val
-
-    "
-     Display
-	getProperty:#'_NET_WM_ICON_GEOMETRY'
-	from:nil
-	delete:false
-    "
-!
-
-propertiesOf:aWindowOrWindowIDOrNil
-    "return a collection of all properties' atomIDs of a window.
-     Returns the rootWindows props for a nil window argument."
-
-    <context: #return>
-
-    |windowID atoms|
-
-    aWindowOrWindowIDOrNil isView ifTrue:[
-	windowID := aWindowOrWindowIDOrNil id.
-    ] ifFalse:[
-	windowID := aWindowOrWindowIDOrNil.
-    ].
-
-%{
-    Window window;
-    Atom *atomListPtr;
-    int i;
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-	int numProps = 0;
-
-	if (__isExternalAddress(windowID)) {
-	    window = __WindowVal(windowID);
-	} else if (windowID == nil) {
-	    window = DefaultRootWindow(dpy);
-	} else if (__isInteger(windowID)) {
-	    window = (Window)__unsignedLongIntVal(windowID);
-	} else {
-	    goto fail;
-	}
-
-	ENTER_XLIB();
-	atomListPtr = XListProperties(dpy, window, &numProps);
-	LEAVE_XLIB();
-
-	if (atomListPtr == NULL) {
-	    RETURN (nil);
-	}
-
-	atoms = __ARRAY_NEW_INT(numProps);
-
-	if (atoms == nil) {
-	    goto fail;
-	}
-
-	for (i=0; i<numProps; i++) {
-	    OBJ atm;
-
-	    atm = __MKATOMOBJ(atomListPtr[i]);
-	    __ArrayInstPtr(atoms)->a_element[i] = atm; __STORE(atoms, atm);
-	}
-	XFree(atomListPtr);
-	RETURN (atoms);
-    }
-fail: ;
-%}.
-    ^ self primitiveFailed
-
-    "
-     Display propertiesOf:nil
-     Display propertiesOf:Transcript view id
-    "
-    "
-     (Display propertiesOf:nil) do:[:atm |
-	|v prop|
-
-	Transcript show:((Display atomName:atm) printStringLeftPaddedTo:5).
-	Transcript show:': '.
-	prop := Display getProperty:atm from:nil delete:false.
-	Transcript showCR:prop value.
-     ]
-    "
-!
-
-setIcon:anIcon for:aWindowID
-    |iconAtom typeAtom buffer iWidth iHeight|
-
-    iconAtom := self atomIDOf:#'_NET_WM_ICON' create:false.
-    iconAtom isNil ifTrue:[
-	"/Hmm, no such property, not running under EWMH compliant WM?
-	^ self
-    ].
-    typeAtom := self atomIDOf:#'CARDINAL' create:false.
-    typeAtom isNil ifTrue:[
-	"/Hmm, no such property, not running under EWMH compliant WM?
-	^ self
-    ].
-    iWidth  := anIcon width.
-    iHeight := anIcon height.
-    buffer := IntegerArray new:(iWidth*iHeight+2).
-    buffer at:1 put:iWidth.
-    buffer at:2 put:iHeight.
-
-    self setProperty:iconAtom type:typeAtom value:buffer for:aWindowID
-
-    "
-	Display setIcon:0 for:0
-    "
-!
-
-setProperty:propertyID type:typeID value:anObject for:aWindowID
-    "set a property in the XServer"
-
-    <context: #return>
-
-    |retval|
-
-    retval := false.
-
-%{  /* UNLIMITEDSTACK */
-    if (ISCONNECTED && __isAtomID(propertyID) && __isAtomID(typeID)) {
-	Display *dpy = myDpy;
-	Atom prop, type;
-	Window window;
-
-	prop = __AtomVal(propertyID);
-	type = __AtomVal(typeID);
-
-	if (__isExternalAddress(aWindowID)) {
-	    window = __WindowVal(aWindowID);
-	} else if (aWindowID == nil) {
-	    window = DefaultRootWindow(dpy);
-	} else if (__isInteger(aWindowID)) {
-	    window = (Window)__unsignedLongIntVal(aWindowID);
-	} else {
-	    RETURN(false);
-	}
-
-	retval = true;
-
-	ENTER_XLIB();
-	if (__isInteger(anObject)) {
-	    unsigned INT value = __longIntVal(anObject);
-	    XChangeProperty(dpy, window, prop, type, 32,
-			    PropModeReplace,
-			    (unsigned char *)&value, 1);
-	} else if (__isByteArrayLike(anObject)) {
-	    XChangeProperty(dpy, window, prop, type, 8,
-			    PropModeReplace,
-			    __byteArrayVal(anObject),
-			    __byteArraySize(anObject));
-	} else if (__isWords(anObject)) {
-	    /* wordArray-like (16bit-string) object */
-	    XChangeProperty(dpy, window, prop, type, 16,
-			    PropModeReplace,
-			    __stringVal(anObject),
-			    __wordArraySize(anObject));
-	} else if (__isIntegerArray(anObject)) {
-	    /* array of atoms */
-	    XChangeProperty(dpy, window, prop, type, 32,
-			    PropModeReplace,
-			    (char *)__integerArrayVal(anObject),
-			    __integerArraySize(anObject));
-	} else if (__isStringLike(anObject)) {
-	    XChangeProperty(dpy, window, prop, type, 8,
-			    PropModeReplace,
-			    __stringVal(anObject),
-			    __stringSize(anObject));
-	} else {
-	    retval = false;
-	}
-	LEAVE_XLIB();
-
-	DPRINTF(("changeProp win=%"_lx_" prop=%"_lx_" type=%"_lx_"\n", (INT)window, (INT)prop, (INT)type));
-    }
-%}.
-    ^ retval
-! !
-
-!XWorkstation methodsFor:'queries'!
-
-defaultExtentForTopViews
-    "redefined, to define the default extent for the default monitor"
-    |extent|
-
-    "the standard monitor is the first entry in monitorBounds"
-    extent := self monitorBounds first extent.
-
-    self isPDA ifTrue:[
-	^ extent - (16 @ 20)
-    ].
-    ^ extent * 2 // 3
-!
-
-isXineramaActive
-%{  /* NOCONTEXT */
-
-#ifdef XINERAMA
-    if (ISCONNECTED) {
-	Display *dpy;
-	dpy = myDpy;
-
-	if (XineramaIsActive(dpy)) {
-	    RETURN ( true );
-	}
-    }
-#endif
-%}.
-    ^ false
-
-    "
-     Display isXineramaActive
-    "
-!
-
-supportedClipboards
-    "answer a collection of symbols with the supported clipboards.
-     X11 additionaly supports a buffer containing the currently selected text
-     (in xterm) - the PRIMARY selection"
-
-    ^ #(clipboard selection)
-!
-
-supportsUTF8WindowLabels
-    "answer true, if window labels are to be utf-8 encoded"
-
-    ^ false
-!
-
-supportsVariableHeightFonts
-    "are fonts with variable height supported?"
-
-    ^ false
-! !
-
-!XWorkstation methodsFor:'resources'!
-
-atomIDOf:aStringOrSymbol
-    "return an X11 atoms ID.
-     This is highly X specific and only for local use (with selections).
-     The default is to create the atom, if it does not exist, in order to
-     speed up future lookups"
-
-    ^ self atomIDOf:aStringOrSymbol create:true
-
-    "
-     Display atomIDOf:#'FACE_NAME'
-     Display atomIDOf:#'FULL_NAME'
-     Display atomIDOf:#DndProtocol
-     Display atomIDOf:#DndSelection
-    "
-
-    "Modified: 4.4.1997 / 13:38:48 / cg"
-!
-
-atomIDOf:aStringOrSymbol create:create
-    "return an Atoms ID given its name.
-     If it already exists, return its ID.
-     If not and the create argument is true, it is created.
-     Otherwise, nil is returned.
-     This is highly X specific and only for local use (with selections)."
-
-    |atomSymbol atom|
-
-    atomSymbol := aStringOrSymbol asSymbol.
-    (atoms notNil and:[(atom := atoms at:atomSymbol ifAbsent:nil) notNil]) ifTrue:[
-	^ atom.
-    ].
-
-    atom := self primAtomIDOf:atomSymbol create:create.
-    atom notNil ifTrue:[
-	atoms isNil ifTrue:[
-	    atoms := IdentityDictionary new.
-	].
-	atoms at:atomSymbol put:atom.
-    ].
-
-    ^ atom
-
-    "
-     Display atomIDOf:#'VT_SELECTION' create:false
-     Display atomIDOf:#CLIPBOARD create:false
-     Display atomIDOf:'STRING' create:false
-     Display atomIDOf:'PRIMARY' create:false
-     Display atomIDOf:'blabla' create:false
-    "
-!
-
-atomName:anAtomID
-    "given an AtomID, return its name.
-     This is highly X specific and only for local use (with selections)."
-
-    <context: #return>
-
-%{
-    OBJ str;
-    char *name;
-
-    if (ISCONNECTED && __isAtomID(anAtomID)) {
-	ENTER_XLIB();
-	name = XGetAtomName(myDpy, __AtomVal(anAtomID));
-	LEAVE_XLIB();
-	if (name == 0) {
-	    RETURN (nil);
-	}
-	str = __MKSTRING(name);
-	XFree(name);
-	RETURN ( str );
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ nil
-
-    "
-     Display atomName:1    'PRIMARY'
-     Display atomName:130  '_DEC_DEVICE_FONTNAMES'
-     Display atomName:132  'FONTNAME_REGISTRY'
-     Display atomName:135 'FOUNDRY'
-     Display atomName:150  'CHARSET_REGISTRY'
-     Display atomName:151  'ISO8859'
-     Display atomName:152 'CHARSET_ENCODING'
-     Display atomName:154
-    "
-!
-
-getResource:name class:cls
-    "access the displays resource database for a default value
-     of name in a resource class.
-     This is highly X specific and  currently not used.
-
-     Notice:
-	we do not plan to use X's resources for ST/X's defaults,
-	styles or resources. This would make porting of applications
-	to different platforms much more difficult (Windows has no resource
-	database). If you stay within ST/X's resource files, these can be
-	easily transported to other platforms.
-
-     This method is provided for special applications which want to access
-     existing X resources and are not planned to be ever ported to other
-     platforms."
-
-%{
-    char *rslt;
-
-    if (ISCONNECTED
-     && __isStringLike(name)
-     && __isStringLike(cls)) {
-
-	rslt = XGetDefault(myDpy, (char *) __stringVal(cls),
-				  (char *) __stringVal(name));
-
-	RETURN (rslt ? __MKSTRING(rslt) : nil );
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ nil.
-
-    "if your ~/.Xdefaults contains an entry such as:
-	OpenWindows.Beep:       notices
-     the following returns 'notices'.
-
-	 Display getResource:'Beep' class:'OpenWindows'
-
-     if your ~/.Xdefaults contains an entry such as:
-	*.beNiceToColormap:       false
-     the following return 'false'.
-
-	 Display getResource:'beNiceToColormap' class:'any'
-	 Display getResource:'beNiceToColormap' class:''
-    "
-!
-
-primAtomIDOf:aStringOrSymbol create:create
-    "return an Atoms ID; if create is true, create it if not already present.
-     This is highly X specific and only for local use (with selections)."
-
-    <context: #return>
-
-%{
-    Atom prop;
-
-    if (ISCONNECTED
-     && __isStringLike(aStringOrSymbol)) {
-
-	ENTER_XLIB();
-	prop = XInternAtom(myDpy, __stringVal(aStringOrSymbol),
-				  (create == true) ? False : True);
-	LEAVE_XLIB();
-	if (prop == None) {
-	    RETURN (nil);
-	}
-	RETURN ( __MKATOMOBJ(prop) );
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ nil
-
-    "
-     Display primAtomIDOf:'VT_SELECTION' create:false
-     Display primAtomIDOf:'CUT_BUFFER0' create:false
-     Display primAtomIDOf:'STRING' create:false
-     Display primAtomIDOf:'PRIMARY' create:false
-    "
-! !
-
-!XWorkstation methodsFor:'retrieving pixels'!
-
-getBitsFromId:aDrawableId x:srcx y:srcy width:w height:h into:imageBits
-    "get bits from a drawable into the imageBits. The storage for the bits
-     must be big enough for the data to fit. If ok, returns an array with some
-     info and the bits in imageBits. The info contains the depth, bitOrder and
-     number of bytes per scanline. The number of bytes per scanline is not known
-     in advance, since the X-server is free to return whatever it thinks is a good padding."
-
-    |rawInfo info|
-
-    ((w <= 0) or:[h <= 0]) ifTrue:[
-	self primitiveFailed.
-	^ nil
-    ].
-
-    rawInfo := Array new:8.
-		  "1 -> bit order"
-		  "2 -> depth"
-		  "3 -> bytes_per_line"
-		  "4 -> byte_order"
-		  "5 -> format"
-		  "6 -> bitmap_unit"
-		  "7 -> bitmap_pad"
-		  "8 -> bits_per_pixel"
-
-    "/ had to extract the getPixel call into a separate method, to specify
-    "/ unlimitedStack (some implementations use alloca and require huge amounts
-    "/ of temporary stack space
-
-    (self primGetBitsFrom:aDrawableId x:srcx y:srcy width:w height:h into:imageBits infoInto:rawInfo) ifTrue:[
-	info := IdentityDictionary new.
-	info at:#bitOrder put:(rawInfo at:1).
-	info at:#depth put:(rawInfo at:2).
-	info at:#bytesPerLine put:(rawInfo at:3).
-	info at:#byteOrder put:(rawInfo at:4).
-	info at:#format put:(rawInfo at:5).
-	info at:#bitmapUnit put:(rawInfo at:6).
-	info at:#bitmapPad put:(rawInfo at:7).
-	info at:#bitsPerPixel put:(rawInfo at:8).
-	^ info
-    ].
-    "
-     some error occured - either args are not smallintegers, imageBits is not a ByteArray
-     or is too small to hold the bits
-    "
-    self primitiveFailedOrClosedConnection.
-    ^ nil
-!
-
-getPixelX:x y:y from:aDrawableId with:dummyGCId
-    "return the pixel value at x/y; coordinates start at 0/0 for the upper left.
-     Nil is returned for invalid coordinates or if any other problem arises."
-
-    <context: #return>
-
-%{  /* UNLIMITEDSTACK */
-
-    Window win;
-    XImage *img;
-    int ret;
-    int xpos, ypos;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aDrawableId) && __bothSmallInteger(x, y)) {
-	win = __WindowVal(aDrawableId);
-	xpos = __intVal(x);
-	ypos = __intVal(y);
-	if ((xpos < 0) || (ypos < 0)) {
-	    RETURN ( __MKSMALLINT(0) );
-	}
-	ENTER_XLIB();
-	img = XGetImage(myDpy, win, xpos, ypos, 1, 1, (unsigned)~0, ZPixmap);
-	LEAVE_XLIB();
-	if (img != 0) {
-	    ret = XGetPixel(img, 0, 0);
-	    XDestroyImage(img);
-	    RETURN (  __MKSMALLINT(ret) );
-	}
-    }
-%}.
-    ^ nil
-!
-
-primGetBitsFrom:aDrawableId x:srcx y:srcy width:w height:h into:imageBits infoInto:info
-    "since XGetImage may allocate huge amount of stack space
-     (some implementations use alloca), this must run with unlimited stack."
-
-    <context: #return>
-
-%{  /* UNLIMITEDSTACK */
-
-    Window win;
-    XImage *image = (XImage *)0;
-    int pad, bytes_per_line, numBytes;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aDrawableId)
-     && __bothSmallInteger(srcx, srcy)
-     && __bothSmallInteger(w, h)
-     && __isArray(info)
-     && __isByteArray(imageBits)) {
-	Display *dpy = myDpy;
-
-	win = __WindowVal(aDrawableId);
-	ENTER_XLIB();
-	image = XGetImage(dpy, win, __intVal(srcx), __intVal(srcy),
-				    __intVal(w), __intVal(h),
-				    (unsigned)AllPlanes, ZPixmap);
-	LEAVE_XLIB();
-
-	if (! image) {
-	    RETURN ( false );
-	}
-
-	pad = image->bitmap_pad;
-#ifdef SUPERDEBUG
-	console_printf("pad:%d depth:%d\n", image->bitmap_pad, image->depth);
-#endif
-	switch (image->depth) {
-	    case 1:
-	    case 2:
-	    case 4:
-	    case 8:
-	    case 16:
-	    case 24:
-	    case 32:
-		numBytes = image->bytes_per_line * image->height;
-		break;
-
-	    default:
-		/* unsupported depth ? */
-		console_fprintf(stderr, "possibly unsupported depth:%d in primGetBits\n", image->depth);
-		numBytes = image->bytes_per_line * image->height;
-		break;
-	}
-
-#ifdef SUPERDEBUG
-	console_printf("bytes need:%d bytes given:%d\n", numBytes, __byteArraySize(imageBits));
-#endif
-
-	if (numBytes > __byteArraySize(imageBits)) {
-	    /* imageBits too small */
-	    console_fprintf(stderr, "Workstation [warning]: byteArray too small in primGetBits\n");
-	    console_fprintf(stderr, "  bytes need:%d given:%d\n", numBytes, (int)__byteArraySize(imageBits));
-	    console_fprintf(stderr, "  pad:%d depth:%d imgBytesPerLine:%d\n",
-				image->bitmap_pad, image->depth, image->bytes_per_line);
-	    goto fail;
-	}
-	if (image->bitmap_bit_order == MSBFirst)
-	    __ArrayInstPtr(info)->a_element[0] = @symbol(msbFirst);
-	else
-	    __ArrayInstPtr(info)->a_element[0] = @symbol(lsbFirst);
-	__ArrayInstPtr(info)->a_element[1] = __MKSMALLINT(image->depth);
-	__ArrayInstPtr(info)->a_element[2] = __MKSMALLINT(image->bytes_per_line);
-	if (image->byte_order == MSBFirst)
-	    __ArrayInstPtr(info)->a_element[3] = @symbol(msbFirst);
-	else
-	    __ArrayInstPtr(info)->a_element[3] = @symbol(lsbFirst);
-	if (image->format == XYBitmap)
-	    __ArrayInstPtr(info)->a_element[4] = @symbol(XYBitmap);
-	else if (image->format == XYPixmap)
-	    __ArrayInstPtr(info)->a_element[4] = @symbol(XYPixmap);
-	else if (image->format == ZPixmap)
-	    __ArrayInstPtr(info)->a_element[4] = @symbol(ZPixmap);
-
-	__ArrayInstPtr(info)->a_element[5] = __MKSMALLINT(image->bitmap_unit);
-	__ArrayInstPtr(info)->a_element[6] = __MKSMALLINT(image->bitmap_pad);
-	__ArrayInstPtr(info)->a_element[7] = __MKSMALLINT(image->bits_per_pixel);
-	bcopy(image->data, __ByteArrayInstPtr(imageBits)->ba_element, numBytes);
-	XDestroyImage(image);
-	RETURN ( true );
-    }
-fail:
-    if (image) {
-	XDestroyImage(image);
-    }
-%}.
-    ^ false
-! !
-
-!XWorkstation methodsFor:'selection fetching'!
-
-getClipboardObjectFor:drawableId
-    "get the object selection.
-     Returns nil, if no selection is available.
-
-     Smalltalk puts ST_OBJECT only into the CLIPBOARD"
-
-    |selectionOwnerWindowId selection|
-
-    selectionOwnerWindowId := self getSelectionOwnerOf:clipboardAtom.
-    selectionOwnerWindowId isNil ifTrue:[
-	"no selection. There is the possibilty that one of our (modal)
-	 views has been closed. Get the selection from the copyBuffer"
-	^ copyBuffer.
-    ].
-    selectionOwnerWindowId = selectionOwner ifTrue:[
-	"I still hold the selection, so return my locally buffered data"
-	^ copyBuffer
-    ].
-
-    drawableId notNil ifTrue:[
-	"sorry, cannot fetch a selection, if there is no drawableId.
-	 Should I borrow a drawableId from another window?"
-
-	selection := SelectionFetcher
-	    requestSelection:clipboardAtom
-	    type:(self atomIDOf:#'ST_OBJECT')
-	    onDevice:self for:drawableId.
-
-	"/ should not happen
-false ifTrue:[
-	"/ cg: disabled the code below: I don't want any string here (when asking for an object)
-	selection isEmptyOrNil ifTrue:[
-	    selection := SelectionFetcher
-		requestSelection:clipboardAtom
-		type:(self atomIDOf:#'UTF8_STRING')
-		onDevice:self for:drawableId.
-
-	    selection isNil ifTrue:[
-		selection := SelectionFetcher
-		    requestSelection:clipboardAtom
-		    type:(self atomIDOf:#STRING)
-		    onDevice:self for:drawableId.
-	    ].
-	].
-].
-    ].
-    selection isEmptyOrNil ifTrue:[ ^ copyBuffer ].
-
-    ^ selection.
-
-    "
-       Display getClipboardObjectFor:Transcript id
-    "
-!
-
-getClipboardText:selectionBufferSymbol for:drawableId
-    "get the text selection.
-     Returns nil, if no selection is available"
-
-    |selectionId selectionOwnerWindowId selection|
-
-    selectionBufferSymbol == #selection ifTrue:[
-	selectionId := primaryAtom.
-    ] ifFalse:[
-	selectionId := clipboardAtom.
-    ].
-
-    selectionOwnerWindowId := self getSelectionOwnerOf:selectionId.
-    selectionOwnerWindowId isNil ifTrue:[
-	"no selection. There is the possibilty that one of our (modal)
-	 views has been closed. Get the selection from the copyBuffer"
-	^ self copyBufferAsString.
-    ].
-
-    selectionOwnerWindowId = selectionOwner ifTrue:[
-	"I still hold the selection, so return my locally buffered data"
-	"JV@2012-04-02: Added support for PRIMARY/SELECTION buffers."
-	^ selectionId == primaryAtom ifTrue:[
-	    self primaryBufferAsString
-	] ifFalse:[
-	    self copyBufferAsString.
-	]
-    ].
-
-    drawableId notNil ifTrue:[
-	"sorry, cannot fetch a selection, if there is no drawableId.
-	 Should I borrow a drawableId from another window?"
-
-	selection := SelectionFetcher
-	    requestSelection:selectionId
-	    type:(self atomIDOf:#'UTF8_STRING')
-	    onDevice:self for:drawableId.
-
-	selection isNil ifTrue:[
-	    selection := SelectionFetcher
-		requestSelection:selectionId
-		type:(self atomIDOf:#STRING)
-		onDevice:self for:drawableId.
-	].
-    ].
-
-    ^ selection
-
-     "
-       Display getTextSelection:#clipboard for:Transcript id
-       Display getTextSelection:#selection for:Transcript id
-     "
-
-    "Modified: / 02-04-2012 / 10:34:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-! !
-
-!XWorkstation methodsFor:'selection sending'!
-
-selectionBuffer:bufferGetSelector as:aTargetAtomID
-    "convert the current selection to the format defined by aTargetAtom.
-     Answer an association with the type of converted selection (an atomID)
-     and the converted selection"
-
-    |buffer bufferAsString|
-
-    buffer := self perform:bufferGetSelector.
-
-    (aTargetAtomID == (self atomIDOf:#'ST_OBJECT')) ifTrue:[
-	"/ 'st-object' printCR.
-	"send the selection in binaryStore format"
-	"require libboss to be loaded"
-	(Smalltalk isClassLibraryLoaded:'libstx_libboss') ifFalse:[
-	    'XWorkstation: cannot use binary store for copy buffer (libboss missing)' errorPrintCR.
-	    ^ nil -> nil.
-	].
-
-	[
-	    ^ aTargetAtomID -> (buffer binaryStoreBytes).
-	] on:Error do:[:ex|
-	    'XWorkstation: error on binary store of copy buffer: ' infoPrint.
-	    ex description infoPrintCR.
-	    ^ nil -> nil.
-	].
-    ].
-
-    bufferAsString := self class bufferAsString:buffer.
-
-    (aTargetAtomID == (self atomIDOf:#STRING)
-     or:[aTargetAtomID == (self atomIDOf:#'text/plain')]
-    ) ifTrue:[
-	"/ 'string' printCR.
-	"the other view wants the selection as string"
-	^ aTargetAtomID -> (bufferAsString asSingleByteStringReplaceInvalidWith:$#).
-    ].
-
-    (aTargetAtomID == (self atomIDOf:#UTF8_STRING)
-     or:[aTargetAtomID == (self atomIDOf:#'text/plain;codeset=utf-8')]
-    ) ifTrue:[
-	"/ 'utf string' printCR.
-	"the other view wants the selection as utf8 string"
-	^ aTargetAtomID -> (bufferAsString utf8Encoded).
-    ].
-
-    aTargetAtomID == (self atomIDOf:#LENGTH) ifTrue:[
-	"the other one wants to know the size of our selection.
-	 LENGTH is deprecated, since we do not know how the selection is
-	 going to be converted. The client must not rely on the length returned"
-
-	^ (self atomIDOf:#INTEGER) -> (bufferAsString size).
-    ].
-
-    "we do not support the requestet target type"
-    ^ nil -> nil.
-
-    "Modified: / 23-08-2006 / 15:56:08 / cg"
-!
-
-setClipboardObject:anObject owner:aWindowId
-    "set the object selection, and make aWindowId be the owner.
-     This can be used by other Smalltalk(X) applications only.
-     We set only the CLIPBOARD selection"
-
-    clipboardSelectionTime := lastEventTime.
-    self setSelectionOwner:aWindowId of:clipboardAtom time:clipboardSelectionTime
-!
-
-setClipboardText:aString owner:aWindowId
-    "set the text selection, and make aWindowId be the owner.
-     This can be used by any other X application.
-
-     We set both the PRIMARY and CLIPBOARD, so that you can paste
-     into xterm."
-
-    clipboardSelectionTime := primarySelectionTime := lastEventTime.
-
-    self setSelectionOwner:aWindowId of:clipboardAtom time:clipboardSelectionTime.
-    self setSelectionOwner:aWindowId of:primaryAtom time:primarySelectionTime.
-
-    "Modified: / 17.6.1998 / 19:48:54 / cg"
-!
-
-setPrimaryText:aString owner:aWindowId
-    "set the PRIMARY selection, and make aWindowId be the owner.
-     This can be used by any other X application when middle-click
-     pasting. X Window specific."
-
-    primarySelectionTime := lastEventTime.
-
-    self setSelectionOwner:aWindowId of:primaryAtom time:primarySelectionTime.
-
-    "Created: / 27-03-2012 / 14:16:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-supportedTargetAtoms
-    "answer an integer array containing the list of supported targets
-     i.e. supported clipboard formats"
-
-    "Note: some sender code assumes that ST_OBJECT is first"
-    ^ #(ST_OBJECT STRING UTF8_STRING TIMESTAMP TARGETS LENGTH
-      #'text/plain' #'text/plain;codeset=utf-8'
-    ) collect:[:eachTargetSymbol|
-	    self atomIDOf:eachTargetSymbol
-	] as:IntegerArray.
-! !
-
-!XWorkstation methodsFor:'selections-basic'!
-
-getSelectionOwnerOf:selectionAtomSymbolOrID
-    "get the owner of a selection, aDrawableID.
-     Answer nil, if there is no owner"
-
-    <context:#return>
-
-    |selectionAtomID|
-
-    selectionAtomSymbolOrID isString ifTrue:[
-	selectionAtomID := self atomIDOf:selectionAtomSymbolOrID create:false.
-    ] ifFalse:[
-	selectionAtomID := selectionAtomSymbolOrID.
-    ].
-
-%{
-    Window window;
-
-    if (__isAtomID(selectionAtomID) && ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	ENTER_XLIB();
-	window = XGetSelectionOwner(dpy, __AtomVal(selectionAtomID));
-	LEAVE_XLIB();
-	RETURN ((window == None) ? nil : __MKEXTERNALADDRESS(window));
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ nil
-!
-
-requestSelection:selectionID type:typeID for:aWindowId intoProperty:propertyID
-    "ask the server to send us the selection - the view with id aWindowID
-     will later receive a SelectionNotify event for it (once the Xserver replies
-     with the selections value)."
-
-    <context:#return>
-
-    |anIntegerTimestamp|
-
-    anIntegerTimestamp := lastEventTime.
-
-%{
-
-    if (ISCONNECTED
-     && __isAtomID(typeID)
-     && __isAtomID(propertyID)
-     && __isAtomID(selectionID)) {
-	Display *dpy = myDpy;
-	Window w;
-	Time time;
-
-	if (__isExternalAddress(aWindowId)) {
-	    w = __WindowVal(aWindowId);
-	} else if (aWindowId == nil) {
-	    w = (Window)0;
-	} else
-	    goto err;
-
-	if (anIntegerTimestamp == nil) {
-	    /*
-	     * the ICCCM convention says: you should set the time to the time when
-	     * the selection was requested and not to CurrentTime
-	     */
-	    time = CurrentTime;
-	} else if (__isInteger(anIntegerTimestamp)) {
-	    time = __unsignedLongIntVal(anIntegerTimestamp);
-	} else
-	    goto err;
-
-	ENTER_XLIB();
-	XConvertSelection(dpy, __AtomVal(selectionID), __AtomVal(typeID),
-			       __AtomVal(propertyID), w, time);
-	LEAVE_XLIB();
-
-	RETURN (true);
-err:;
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false
-
-    "
-     Display
-	requestSelection:(Display atomIDOf:'PRIMARY')
-	property:(Display atomIDOf:'VT_SELECTION')
-	type:(Display atomIDOf:'STRING')
-	for:Transcript id
-    "
-    "
-     Display
-	requestSelection:(Display atomIDOf:'PRIMARY')
-	property:(Display atomIDOf:'VT_SELECTION')
-	type:(Display atomIDOf:'C_STRING')
-	for:Transcript id
-    "
-!
-
-sendNotifySelection:selectionID property:propertyID target:targetID time:aTime to:requestorID
-    "send a selectionNotify back from a SelectionRequest.
-     PropertyID should be the same as requested  or nil, if the selection
-     could not be converted.
-     TargetId should be the same as requested.
-     Time should be the time when the selection has been acquired"
-
-    <context: #return>
-%{
-    if (ISCONNECTED
-	&& (__isAtomID(propertyID) || propertyID == nil)
-	&& __isAtomID(targetID) && __isAtomID(selectionID)) {
-	Display *dpy = myDpy;
-	XEvent ev;
-	Window requestor;
-	Status result;
-
-	if (__isExternalAddress(requestorID)) {
-	    requestor = __WindowVal(requestorID);
-	} else if (__isSmallInteger(requestorID)) {
-	    requestor = (Window)__smallIntegerVal(requestorID);
-	} else if (requestorID == nil) {
-	    requestor = DefaultRootWindow(dpy);
-	} else {
-	    requestor = (Window)__unsignedLongIntVal(requestorID);
-	}
-
-	ev.xselection.type = SelectionNotify;
-	ev.xselection.display = dpy;
-	ev.xselection.selection = __AtomVal(selectionID);
-	ev.xselection.target = __AtomVal(targetID);
-	ev.xselection.requestor = requestor;
-
-	if (__isExternalAddress(aTime)) {
-	    ev.xselection.time = (INT)(__externalAddressVal(aTime));
-	} else if (__isSmallInteger(aTime)) {
-	    ev.xselection.time = __smallIntegerVal(aTime);
-	} else if (aTime == nil) {
-	    ev.xselection.time = CurrentTime;
-	} else {
-	    ev.xselection.time = (INT)__unsignedLongIntVal(aTime);
-	}
-#if 0
-	console_printf("ev.xselection.selection: %x\n", ev.xselection.selection);
-	console_printf("ev.xselection.target: %x\n", ev.xselection.target);
-	console_printf("ev.xselection.requestor: %x\n", ev.xselection.requestor);
-	console_printf("ev.xselection.time: %x\n", ev.xselection.time);
-	console_printf("requestor: %x\n", requestor);
-#endif
-
-	/* send nil property if selection cannot be converted */
-	if (propertyID == nil)
-	    ev.xselection.property = None;
-	else
-	    ev.xselection.property = __AtomVal(propertyID);
-
-
-	DPRINTF(("sending SelectionNotify sel=%"_lx_" prop=%"_lx_" target=%"_lx_" requestor=%"_lx_" to %"_lx_"\n",
-		(INT)ev.xselection.selection,
-		(INT)ev.xselection.property,
-		(INT)ev.xselection.target,
-		(INT)ev.xselection.requestor,
-		(INT)requestor));
-
-	ENTER_XLIB();
-	result = XSendEvent(dpy, requestor, False, 0 , &ev);
-	LEAVE_XLIB();
-
-	if ((result == BadValue) || (result == BadWindow)) {
-	    DPRINTF(("bad status\n"));
-	    RETURN (false);
-	}
-	ENTER_XLIB();
-	XFlush(dpy);
-	LEAVE_XLIB();
-	RETURN (true)
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false
-
-    "Modified: / 17.6.1998 / 20:23:20 / cg"
-!
-
-setSelectionOwner:aWindowId of:selectionAtomSymbolOrID time:anIntegerTimestamp
-    "set the owner of a selection; return false if failed"
-
-    <context: #return>
-
-    |selectionAtomID|
-
-    "store the current owner of the selection.
-     If we still own the selection on paste,
-     we can avoid the X11 overhead"
-
-    selectionOwner := aWindowId.
-
-    selectionAtomSymbolOrID isString ifTrue:[
-	selectionAtomID := self atomIDOf:selectionAtomSymbolOrID create:false.
-    ] ifFalse:[
-	selectionAtomID := selectionAtomSymbolOrID.
-    ].
-
-%{
-    Window win;
-
-    if (__isExternalAddress(aWindowId)
-     && __isAtomID(selectionAtomID)
-     && ISCONNECTED) {
-	Display *dpy = myDpy;
-	Time time;
-
-	win = __WindowVal(aWindowId);
-
-	if (anIntegerTimestamp == nil) {
-	    /*
-	     * the ICCCM convention says: you should set the time to the time when
-	     * the selection was acquired and not to CurrentTime
-	     */
-	    time = CurrentTime;
-	} else if (__isInteger(anIntegerTimestamp)) {
-	    time = __unsignedLongIntVal(anIntegerTimestamp);
-	} else
-	    goto err;
-
-	DPRINTF(("setOwner prop=%"_lx_" win=%"_lx_"\n", (INT)__AtomVal(selectionAtomID), (INT)win));
-	ENTER_XLIB();
-	XSetSelectionOwner(dpy, __AtomVal(selectionAtomID), win, time);
-	RETURN (self);
-	LEAVE_XLIB();
-    }
-err:;
-%}.
-    self primitiveFailedOrClosedConnection.
-! !
-
-!XWorkstation methodsFor:'window queries'!
-
-allChildIdsOf:aWindowId
-    "return all children-ids of the given window.
-     Allows for all windows to be enumerated, if we start at the root."
-
-    |childIDs allChildIDs|
-
-    allChildIDs := OrderedCollection new.
-    childIDs := self childIdsOf:aWindowId.
-    childIDs notNil ifTrue:[
-	allChildIDs addAll:childIDs.
-	childIDs do:[:eachChildId |
-	    allChildIDs addAll:(self allChildIdsOf:eachChildId).
-	].
-    ].
-    ^ allChildIDs
-
-    "
-     Display allChildIdsOf:(Display rootWindowId)
-    "
-
-    "
-     |deviceIDAtom uuidAtom|
-
-     deviceIDAtom := (Display atomIDOf:#'STX_DEVICE_ID').
-     uuidAtom     := (Display atomIDOf:#'UUID').
-     (Display allChildIdsOf:(Display rootWindowId))
-	select:[:id |
-	    |uuid|
-
-	    Display
-		getProperty:deviceIDAtom
-		from:id
-		delete:false
-		into:[:type :value |
-		    type == uuidAtom ifTrue:[
-			uuid := UUID fromBytes:value.
-		    ].
-		].
-	    uuid notNil.
-	]
-    "
-!
-
-childIdsOf:aWindowId
-    "return all children-ids of the given window. Allows for all windows to be
-     enumerated, if we start at the root."
-
-    |childIdArray|
-%{
-    OBJ id;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	Display *dpy = myDpy;
-	Window win = __WindowVal(aWindowId);
-	Window rootReturn, parentReturn;
-	Window* children = (Window *)0;
-	unsigned int numChildren;
-	int i;
-	int rslt;
-
-	ENTER_XLIB();
-	rslt = XQueryTree(dpy, win,
-		       &rootReturn, &parentReturn,
-		       &children, &numChildren);
-	LEAVE_XLIB();
-	if (rslt) {
-	    childIdArray = __ARRAY_NEW_INT(numChildren);
-	    if (childIdArray != nil) {
-		for (i=0; i < numChildren; i++) {
-		    if (children[i]) {
-			OBJ childId;
-
-			childId = __MKEXTERNALADDRESS(children[i]);
-			__ArrayInstPtr(childIdArray)->a_element[i] = childId;
-			__STORE(childIdArray, childId);
-		    }
-		}
-		if (children) XFree(children);
-	    }
-	    RETURN (childIdArray);
-	}
-    }
-%}.
-    ^ nil.
-
-    "
-      Display childIdsOf:(Display rootWindowId)
-    "
-!
-
-realRootWindowId
-    "return the id of the real root window.
-     This may not be the window you see as background,
-     since some window managers install a virtual root window on top
-     of it. Except for very special cases, use #rootWindowId, which takes
-     care of any virtual root."
-
-%{
-    int screen = __intVal(__INST(screen));
-    Window root;
-    OBJ id;
-
-    if (__INST(rootId) != nil) {
-	RETURN (__INST(rootId));
-    }
-
-    if (ISCONNECTED) {
-	root = RootWindow(myDpy, screen);
-	if (! root) {
-	    id = nil;
-	} else {
-	    id = __MKEXTERNALADDRESS(root); __INST(rootId) = id; __STORE(self, id);
-	}
-	RETURN (id);
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ nil
-
-    "
-      Display rootWindowId
-      Display realRootWindowId
-    "
-!
-
-rootWindowId
-    "return the id of the root window.
-     This is the window you see as background,
-     however, it may or may not be the real physical root window,
-     since some window managers install a virtual root window on top
-     of the real one. If this is the case, that views id is returned here."
-
-%{
-    int screen = __intVal(__INST(screen));
-    Window rootWin, vRootWin = 0;
-    OBJ id;
-
-    if (__INST(virtualRootId) != nil) {
-	RETURN (__INST(virtualRootId));
-    }
-
-    if (ISCONNECTED) {
-	Display *dpy = myDpy;
-
-	rootWin = RootWindow(dpy, screen);
-#ifndef IRIS
-
-	/*
-	 * on IRIS, this creates a badwindow error - why ?
-	 * children contains a funny window (000034)
-	 */
-
-	/*
-	 * care for virtual root windows (tvtwm & friends)
-	 */
-	{
-	    Atom vRootAtom, kwinAtom;
-	    int i;
-	    Window rootReturn, parentReturn;
-	    Window* children = (Window *)0;
-	    unsigned int numChildren;
-	    int ignoreVRoot = 0;
-
-	    /*
-	     * Take care of KDE 2.1.
-	     * they define _SWM_ROOT but this is not the parent of
-	     * the application windows.
-	     * Instead it is used for background painting
-	     */
-
-	    kwinAtom = XInternAtom(dpy, "KWIN_RUNNING", True);
-	    if (kwinAtom != None) {
-		Atom actual_type;
-		int actual_format;
-		unsigned long nitems, bytesafter;
-		unsigned char *retVal = 0;
-
-		ignoreVRoot = XGetWindowProperty(dpy, rootWin, kwinAtom,
-				       0L, 1L, False, kwinAtom,
-				       &actual_type, &actual_format,
-				       &nitems, &bytesafter, &retVal) == Success
-			      && actual_type != 0;
-		if (retVal)
-		    XFree(retVal);
-	    }
-
-	    if (!ignoreVRoot) {
-		vRootAtom = XInternAtom(dpy, "__SWM_VROOT", True);
-		if (vRootAtom != None) {
-		    if (XQueryTree(dpy, rootWin,
-				       &rootReturn, &parentReturn,
-				       &children, &numChildren)) {
-			for (i=0; i < numChildren; i++) {
-			    Atom actual_type;
-			    int actual_format;
-			    unsigned long nitems, bytesafter;
-			    Window* newRoot = (Window*) 0;
-
-			    if (children[i]) {
-				if (XGetWindowProperty(dpy, children[i], vRootAtom,
-						       0L, 1L, False, XA_WINDOW,
-						       &actual_type, &actual_format,
-						       &nitems, &bytesafter,
-						       (unsigned char**) &newRoot
-						      ) == Success && newRoot) {
-				    vRootWin = *newRoot;
-				    XFree(newRoot); /* XXX */
-				    break;
-				}
-			    }
-			}
-			if (children) XFree(children);
-		    }
-		}
-	     }
-	}
-#endif
-    }
-
-    if (! vRootWin) {
-	vRootWin = rootWin;
-	if (! vRootWin) {
-	    RETURN ( nil );
-	}
-    }
-    id = __MKEXTERNALADDRESS(rootWin); __INST(rootId) = id; __STORE(self, id);
-    id = __MKEXTERNALADDRESS(vRootWin); __INST(virtualRootId) = id; __STORE(self, id);
-    RETURN ( id );
-%}
-
-    "
-      Display rootWindowId
-    "
-! !
-
-!XWorkstation methodsFor:'window stuff'!
-
-clearRectangleX:x y:y width:width height:height in:aWindowId
-    "clear a rectangular area to viewbackground"
-
-    <context: #return>
-%{
-
-    int w, h;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aWindowId)
-	 && __bothSmallInteger(x, y)
-	 && __bothSmallInteger(width, height)) {
-	    w = __intVal(width);
-	    h = __intVal(height);
-	    /*
-	     * need this check here: some servers simply dump core with bad args
-	     */
-	    if ((w >= 0) && (h >= 0)) {
-		ENTER_XLIB();
-		XClearArea(myDpy, __WindowVal(aWindowId), __intVal(x), __intVal(y), w, h, 0);
-		LEAVE_XLIB();
-	    }
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-!
-
-clearWindow:aWindowId
-    "clear a window to viewbackground"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aWindowId)) {
-	    ENTER_XLIB();
-	    XClearWindow(myDpy, __WindowVal(aWindowId));
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-configureWindow:aWindowId sibling:siblingId stackMode:modeSymbol
-    "configure stacking operation of aWindowId w.r.t siblingId"
-
-    <context: #return>
-%{
-
-    XWindowChanges chg;
-    int mask = CWSibling | CWStackMode;
-
-    if (ISCONNECTED) {
-	if (__isExternalAddress(aWindowId)
-	 && __isExternalAddress(siblingId)) {
-	    if (modeSymbol == @symbol(above)) {
-		chg.stack_mode = Above;
-	    } else if (modeSymbol == @symbol(below)) {
-		chg.stack_mode = Below;
-	    } else if (modeSymbol == @symbol(topIf)) {
-		chg.stack_mode = TopIf;
-	    } else if (modeSymbol == @symbol(bottomIf)) {
-		chg.stack_mode = BottomIf;
-	    } else if (modeSymbol == @symbol(opposite)) {
-		chg.stack_mode = Opposite;
-	    } else {
-		mask = CWSibling;
-	    }
-
-	    chg.sibling = __WindowVal(siblingId);
-	    ENTER_XLIB();
-	    XConfigureWindow(myDpy, __WindowVal(aWindowId),
-				    mask, &chg);
-	    LEAVE_XLIB();
-	    RETURN ( self );
-	}
-    }
-bad: ;
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-getGeometryOf:aWindowId
-    "get a windows geometry.
-     NOTICE: X-WindowManagers usually do wrap client topViews into their own
-     decoration views (top label, resize boundaries etc.).
-     Thus, the numbers returned here for topViews are the physical (real) dimensions
-     relative to such a wrapper.
-     In contrast, the values found in the views instance variables are virtual dimensions
-     (i.e. ST/X makes this decoration view transparent to the program."
-
-    <context: #return>
-
-    |x y width height depth borderWidth info|
-
-%{
-    int x_ret, y_ret;
-    unsigned int width_ret, height_ret,
-		 border_width_ret, depth_ret;
-    Window root_ret;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	ENTER_XLIB();
-	XGetGeometry(myDpy, __WindowVal(aWindowId),
-		     &root_ret,
-		     &x_ret, &y_ret,
-		     &width_ret, &height_ret, &border_width_ret,
-		     &depth_ret);
-	LEAVE_XLIB();
-
-	x = __MKSMALLINT(x_ret);
-	y = __MKSMALLINT(y_ret);
-	width = __MKSMALLINT(width_ret);
-	height = __MKSMALLINT(height_ret);
-	depth = __MKSMALLINT(depth_ret);
-	borderWidth = __MKSMALLINT(border_width_ret);
-    }
-%}.
-    borderWidth isNil ifTrue:[
-	self primitiveFailedOrClosedConnection.
-	^ nil
-    ].
-    info := Dictionary new.
-    info at:#origin put:(x @ y).
-    info at:#extent put:(width @ height).
-    info at:#depth  put:depth.
-    info at:#borderWidth put:borderWidth.
-    ^ info
-
-    "
-     Transcript topView device
-	getGeometryOf:(Transcript id)
-    "
-    "
-     Transcript topView device
-	getGeometryOf:(Transcript topView id)
-    "
-    "
-     Display
-	getGeometryOf:(Display viewIdFromUser)
-    "
-    "
-     |d|
-
-     d := Transcript topView device.
-     d getGeometryOf:(d parentWindowIdOf:Transcript topView id)
-    "
-!
-
-isValidWindowId:aWindowId
-    "return true, if the given window ID is (still) valid.
-     Especially useful, if the passed windowID is
-     an alien (external) windows id."
-
-    |ret|
-
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	char *name = NULL;
-	Status ok;
-	Window root, parent, *children = NULL;
-	unsigned int nChildren;
-
-/*        ENTER_XLIB(); */
-	ok = XQueryTree(myDpy, __WindowVal(aWindowId),
-			&root, &parent, &children, &nChildren);
-	if (children) {
-	    XFree(children);
-	}
-/*        LEAVE_XLIB();   */
-	if (ok) {
-	    RETURN (true);
-	}
-	RETURN (false);
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false
-
-    "
-     |v aWindowId ok|
-
-     v := StandardSystemView new.
-     v label:'hello'.
-     v openAndWait.
-     aWindowId := v id.
-     ok := Display isValidWindowId:aWindowId.
-     Transcript showCR:'ok is: ' , ok printString.
-     Delay waitForSeconds:1.
-     v destroy.
-     ok := Display isValidWindowId:aWindowId.
-     Transcript showCR:'ok is: ' , ok printString.
-    "
-!
-
-lowerWindow:aWindowId
-    "bring a window to back"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	ENTER_XLIB();
-	XLowerWindow(myDpy, __WindowVal(aWindowId));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-mapView:aView id:aWindowId iconified:aBoolean atX:xPos y:yPos
-	      width:w height:h minExtent:minExt maxExtent:maxExt
-
-    <context: #return>
-
-    "make a window visible - either as icon or as a real view
-     in addition, allow change of extend, position, minExtend and maxExtent.
-     Needed for restart, to allow recreating a view as iconified,
-     and to collaps/expand windows."
-
-    |wicon wiconId iconMaskId wiconView wiconViewId wlabel minW minH maxW maxH|
-
-    aBoolean ifTrue:[
-	wicon := aView icon.
-	wicon notNil ifTrue:[
-	    wiconId := wicon id.
-	    wicon mask notNil ifTrue:[
-		iconMaskId := wicon mask id.
-	    ].
-	].
-	wiconView := aView iconView.
-	wiconView notNil ifTrue:[
-	    wiconViewId := wiconView id
-	].
-	wlabel := aView label.
-    ].
-    minExt notNil ifTrue:[
-	minW := minExt x.
-	minH := minExt y.
-    ].
-    maxExt notNil ifTrue:[
-	maxW := maxExt x.
-	maxH := maxExt y.
-    ].
-%{
-
-    XWMHints wmhints;
-    XSizeHints szhints;
-    Window win;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	Display *dpy = myDpy;
-
-	win = __WindowVal(aWindowId);
-
-	szhints.flags = 0;
-	if (__bothSmallInteger(xPos, yPos)) {
-	    szhints.x = __intVal(xPos);
-	    szhints.y = __intVal(yPos);
-	    szhints.flags |= USPosition;
-	}
-	if (__bothSmallInteger(w, h)) {
-	    szhints.width = __intVal(w);
-	    szhints.height = __intVal(h);
-	    szhints.flags |= USSize;
-	}
-	if (__bothSmallInteger(minW, minH)) {
-	    szhints.flags |= PMinSize;
-	    szhints.min_width = __intVal(minW);
-	    szhints.min_height = __intVal(minH);
-	}
-	if (__bothSmallInteger(maxW, maxH)) {
-	    szhints.flags |= PMaxSize;
-	    szhints.max_width = __intVal(maxW);
-	    szhints.max_height = __intVal(maxH);
-	}
-
-	if (aBoolean == true) {
-	    char *windowName = "";
-	    Pixmap iconBitmap = (Pixmap)0;
-	    Pixmap iconMask = (Pixmap)0;
-	    Window iconWindow = (Window)0;
-
-	    if (__isExternalAddress(wiconId))
-		iconBitmap = __PixmapVal(wiconId);
-
-	    if (__isExternalAddress(iconMaskId)) {
-		iconMask = __PixmapVal(iconMaskId);
-	    }
-
-	    if (__isExternalAddress(wiconViewId))
-		iconWindow = __WindowVal(wiconViewId);
-
-	    if (__isStringLike(wlabel))
-		windowName = (char *) __stringVal(wlabel);
-
-	    if (iconBitmap || windowName) {
-		ENTER_XLIB();
-		XSetStandardProperties(dpy, win,
-					windowName, windowName,
-					iconBitmap,
-					0, 0, &szhints);
-		LEAVE_XLIB();
-	    }
-
-	    wmhints.flags = 0;
-	    if (iconBitmap) {
-		wmhints.flags |= IconPixmapHint;
-		wmhints.icon_pixmap = iconBitmap;
-	    }
-	    if (iconMask) {
-		wmhints.flags |= IconMaskHint;
-		wmhints.icon_mask = iconMask;
-	    }
-	    if (iconWindow) {
-		wmhints.flags |= IconWindowHint;
-		wmhints.icon_window = iconWindow;
-	    }
-
-	    wmhints.initial_state = IconicState;
-	    wmhints.flags |= StateHint;
-	    ENTER_XLIB();
-	    XSetWMHints(dpy, win, &wmhints);
-	    LEAVE_XLIB();
-	}
-
-	if (szhints.flags) {
-	    ENTER_XLIB();
-	    XSetNormalHints(dpy, win, &szhints);
-	    LEAVE_XLIB();
-	}
-
-	ENTER_XLIB();
-	XMapWindow(dpy, win);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-mapWindow:aWindowId
-    "make a window visible"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	ENTER_XLIB();
-	XMapWindow(myDpy, __WindowVal(aWindowId));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-moveResizeWindow:aWindowId x:x y:y width:w height:h
-    "move and resize a window"
-
-    <context: #return>
-%{
-
-    int newWidth, newHeight;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __bothSmallInteger(w, h)
-     && __bothSmallInteger(x, y)) {
-	newWidth = __intVal(w);
-	newHeight = __intVal(h);
-	if (newWidth < 1) newWidth = 1;
-	if (newHeight < 1) newHeight = 1;
-	ENTER_XLIB();
-	XMoveResizeWindow(myDpy, __WindowVal(aWindowId),
-			      __intVal(x), __intVal(y),
-			      newWidth, newHeight);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-moveWindow:aWindowId x:x y:y
-    "move a window"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId) && __bothSmallInteger(x, y)) {
-	ENTER_XLIB();
-	XMoveWindow(myDpy, __WindowVal(aWindowId), __intVal(x), __intVal(y));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-parentWindowIdOf:aWindowId
-    "return a windows parent-window id.
-     Useful with getGeometryOf:, to compute information about the decoration."
-
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	Status ok;
-	Window root, parent, *children = NULL;
-	unsigned int nChildren;
-
-/*        ENTER_XLIB(); */
-	ok = XQueryTree(myDpy, __WindowVal(aWindowId),
-			&root, &parent, &children, &nChildren);
-	if (children) {
-	    XFree(children);
-	}
-/*        LEAVE_XLIB();   */
-	if (! ok) {
-	    RETURN ( nil );
-	}
-	RETURN ( __MKEXTERNALADDRESS(parent) );
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false
-
-    "
-     |id|
-
-     id := Transcript device parentWindowIdOf:(Transcript id).
-     self assert: ( Transcript container id = id ).
-    "
-!
-
-raiseWindow:aWindowId
-    "bring a window to front"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	ENTER_XLIB();
-	XRaiseWindow(myDpy, __WindowVal(aWindowId));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-reparentWindow:windowId to:newParentWindowId
-    "change a windows parent (an optional interface)"
-
-    <context: #return>
-%{
-    if (ISCONNECTED
-     && __isExternalAddress(windowId)
-     && __isExternalAddress(newParentWindowId)) {
-	Display *dpy = myDpy;
-	Window _child, _newParent;
-	int i;
-
-	_child = __WindowVal(windowId);
-	_newParent = __WindowVal(newParentWindowId);
-	ENTER_XLIB();
-
-#if 0
-	XWithdrawWindow (dpy, _child, DefaultScreen(dpy));
-	XSync (dpy, 0);
-#endif
-	/*
-	 * Code 'stolen' from xswallow source ...
-	 * ... mhmh - what is this loop for ?
-	 */
-	for (i=0; i<5; i++) {
-	    XReparentWindow (dpy, _child, _newParent, 0, 0);
-	    XSync (dpy, 0);
-	}
-#if 0
-	XMapWindow (dpy, _child);
-	XSync (dpy, 0);
-#endif
-	LEAVE_XLIB();
-	RETURN ( true );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-resizeWindow:aWindowId width:w height:h
-    "resize a window"
-
-    <context: #return>
-%{
-
-    int newWidth, newHeight;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId) && __bothSmallInteger(w, h)) {
-	newWidth = __intVal(w);
-	newHeight = __intVal(h);
-	if (newWidth < 1) newWidth = 1;
-	if (newHeight < 1) newHeight = 1;
-	ENTER_XLIB();
-	XResizeWindow(myDpy, __WindowVal(aWindowId), newWidth, newHeight);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setBackingStore:how in:aWindowId
-    "turn on/off backing-store for a window"
-
-    <context: #return>
-%{
-
-    XSetWindowAttributes wa;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	if (__INST(ignoreBackingStore) != true) {
-	    if (how == @symbol(always)) wa.backing_store = Always;
-	    else if (how == @symbol(whenMapped)) wa.backing_store = WhenMapped;
-	    else if (how == true) wa.backing_store = Always;
-	    else wa.backing_store = 0;
-
-	    ENTER_XLIB();
-	    XChangeWindowAttributes(myDpy, __WindowVal(aWindowId), CWBackingStore, &wa);
-	    LEAVE_XLIB();
-
-	}
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setBitGravity:how in:aWindowId
-    "set bit gravity for a window"
-
-    <context: #return>
-%{
-
-    XSetWindowAttributes wa;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	if (how == @symbol(NorthWest)) {
-	    wa.bit_gravity = NorthWestGravity;
-	} else if (how == @symbol(NorthEast)) {
-	    wa.bit_gravity = NorthEastGravity;
-	} else if (how == @symbol(SouthWest)) {
-	    wa.bit_gravity = SouthWestGravity;
-	} else if (how == @symbol(SouthEast)) {
-	    wa.bit_gravity = SouthEastGravity;
-	} else if (how == @symbol(Center)) {
-	    wa.bit_gravity = CenterGravity;
-	} else if (how == @symbol(North)) {
-	    wa.bit_gravity = NorthGravity;
-	} else if (how == @symbol(South)) {
-	    wa.bit_gravity = SouthGravity;
-	} else if (how == @symbol(West)) {
-	    wa.bit_gravity = WestGravity;
-	} else if (how == @symbol(East)) {
-	    wa.bit_gravity = EastGravity;
-	} else {
-	    wa.bit_gravity = NorthWestGravity;
-	}
-
-
-	ENTER_XLIB();
-	XChangeWindowAttributes(myDpy, __WindowVal(aWindowId), CWBitGravity, &wa);
-	LEAVE_XLIB();
-
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setCursor:aCursorId in:aWindowId
-    "define a windows cursor"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __isExternalAddress(aCursorId)) {
-	Display *dpy = myDpy;
-	Window w = __WindowVal(aWindowId);
-	Cursor c = __CursorVal(aCursorId);
-
-	if (w && c) {
-	    ENTER_XLIB();
-	    XDefineCursor(dpy, w, c);
-	    LEAVE_XLIB();
-	}
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setForegroundWindow:aWindowId
-    "bring a window to front.
-     Send a specific message to the WindowManager"
-
-    |activeWindowAtom|
-
-"/    self raiseWindow:aWindowId.
-
-    activeWindowAtom := self atomIDOf:#'_NET_ACTIVE_WINDOW' create:false.
-    activeWindowAtom notNil ifTrue:[
-	self
-	    sendClientEvent:activeWindowAtom
-	    format:32
-	    to:(self rootWindowId)
-	    propagate:false
-	    eventMask:((self eventMaskFor:#substructureNotify) bitOr:(self eventMaskFor:#substructureRedirect))
-	    window:aWindowId
-	    data1:2                 "activate request from pager. This is a trick: kwm ignores requests from applications (1)"
-	    data2:nil
-	    data3:nil
-	    data4:nil
-	    data5:nil.
-    ].
-
-    "
-      Transcript topView setForegroundWindow
-    "
-!
-
-setIconName:aString in:aWindowId
-    "define a windows iconname"
-
-    <context: #return>
-
-    |utf8StringAtom utf8String simpleString|
-
-    utf8StringAtom := self atomIDOf:#UTF8_STRING create:true.
-
-    utf8String := aString utf8Encoded.
-    aString isWideString ifTrue:[
-	"/ X does not like 2-byte labels ...
-	simpleString := aString asSingleByteStringReplaceInvalidWith:$?
-    ] ifFalse:[
-	simpleString := aString.
-    ].
-
-%{
-    XTextProperty titleProperty;
-
-    if (ISCONNECTED
-     && __isStringLike(utf8String)
-     && __isStringLike(simpleString)
-     && __isExternalAddress(aWindowId)) {
-
-	titleProperty.value =  __stringVal(utf8String);
-	titleProperty.encoding = __smallIntegerVal(utf8StringAtom);
-	titleProperty.format = 8;
-	titleProperty.nitems = __stringSize(utf8String);
-
-	ENTER_XLIB();
-	XSetIconName(myDpy, __WindowVal(aWindowId), (char *) __stringVal(simpleString));
-	/* alternative settings for UTF8-Strings */
-	XSetWMIconName(myDpy, __WindowVal(aWindowId), &titleProperty);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setSaveUnder:yesOrNo in:aWindowId
-    "turn on/off save-under for a window"
-
-    <context: #return>
-%{
-
-    XSetWindowAttributes wa;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	if (__INST(hasSaveUnder) == true) {
-	    wa.save_under = (yesOrNo == true) ? 1 : 0;
-	    ENTER_XLIB();
-	    XChangeWindowAttributes(myDpy, __WindowVal(aWindowId), CWSaveUnder, &wa);
-	    LEAVE_XLIB();
-	}
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setTransient:aWindowId for:aMainWindowId
-    "set aWindowId to be a transient of aMainWindow"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	Window w;
-
-	if ((aMainWindowId == nil) || (aMainWindowId == __MKSMALLINT(0))) {
-	    w = (Window) 0;
-	} else {
-	    if (__isExternalAddress(aMainWindowId)) {
-		w = __WindowVal(aMainWindowId);
-	    } else {
-		goto getOutOfHere;
-	    }
-	}
-	ENTER_XLIB();
-	XSetTransientForHint(myDpy, __WindowVal(aWindowId), w);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
- getOutOfHere: ;
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowBackground:aColorIndex in:aWindowId
-    "set the windows background color. This is the color with which
-     the view is filled whenever exposed. Do not confuse this with
-     the background drawing color, which is used with opaque drawing."
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __isSmallInteger(aColorIndex)) {
-	ENTER_XLIB();
-	XSetWindowBackground(myDpy, __WindowVal(aWindowId), __intVal(aColorIndex));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowBackgroundPixmap:aPixmapId in:aWindowId
-    "set the windows background pattern to be a form.
-     This is the pattern with which the view is filled whenever exposed.
-     Do not confuse this with the background drawing color, which is used
-     with opaque drawing."
-
-    <context: #return>
-%{  /* STACK: 64000 */
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __isExternalAddress(aPixmapId)) {
-	ENTER_XLIB();
-	XSetWindowBackgroundPixmap(myDpy, __WindowVal(aWindowId), __PixmapVal(aPixmapId));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowBorderColor:aColorIndex in:aWindowId
-    "set the windows border color"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __isSmallInteger(aColorIndex)) {
-	ENTER_XLIB();
-	XSetWindowBorder(myDpy, __WindowVal(aWindowId), __intVal(aColorIndex));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowBorderPixmap:aPixmapId in:aWindowId
-    "set the windows border pattern"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __isExternalAddress(aPixmapId)) {
-	ENTER_XLIB();
-	XSetWindowBorderPixmap(myDpy, __WindowVal(aWindowId), __PixmapVal(aPixmapId));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowBorderShape:aPixmapId in:aWindowId
-    "set the windows border shape"
-
-    <context: #return>
-
-    hasShapeExtension ifFalse:[^ self].
-
-%{
-
-#ifdef SHAPE
-    Pixmap shapeBitmap;
-
-    if (__isExternalAddress(aPixmapId))
-	shapeBitmap = __PixmapVal(aPixmapId);
-    else
-	shapeBitmap = (Pixmap)0;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	ENTER_XLIB();
-	XShapeCombineMask(myDpy, __WindowVal(aWindowId), ShapeBounding,
-			  0, 0, shapeBitmap, ShapeSet);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-#endif
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowBorderWidth:aNumber in:aWindowId
-    "set the windows border width"
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)
-     && __isSmallInteger(aNumber)) {
-	ENTER_XLIB();
-	XSetWindowBorderWidth(myDpy, __WindowVal(aWindowId), __intVal(aNumber));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowClass:wClass name:wName in:aWindowId
-    "define class and name of a window.
-     This may be used by the window manager to
-     select client specific resources."
-
-    <context: #return>
-%{
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	XClassHint classhint;
-
-	classhint.res_class = classhint.res_name = 0;
-
-	if (__isStringLike(wClass)) {
-	    classhint.res_class = (char *) __stringVal(wClass);
-	} else if (wClass != nil)
-	    goto error;
-
-	if (__isStringLike(wName)) {
-	    classhint.res_name = (char *) __stringVal(wName);
-	} else if (wName != nil)
-	    goto error;
-
-	ENTER_XLIB();
-	XSetClassHint(myDpy, __WindowVal(aWindowId), &classhint);
-	LEAVE_XLIB();
-	RETURN ( self );
-error:;
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowGravity:how in:aWindowId
-    "set window gravity for a window"
-
-    <context: #return>
-%{
-
-    XSetWindowAttributes wa;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	if (how == @symbol(NorthWest)) {
-	    wa.win_gravity = NorthWestGravity;
-	} else if (how == @symbol(NorthEast)) {
-	    wa.win_gravity = NorthEastGravity;
-	} else if (how == @symbol(SouthWest)) {
-	    wa.win_gravity = SouthWestGravity;
-	} else if (how == @symbol(SouthEast)) {
-	    wa.win_gravity = SouthEastGravity;
-	} else if (how == @symbol(Center)) {
-	    wa.win_gravity = CenterGravity;
-	} else if (how == @symbol(North)) {
-	    wa.win_gravity = NorthGravity;
-	} else if (how == @symbol(South)) {
-	    wa.win_gravity = SouthGravity;
-	} else if (how == @symbol(West)) {
-	    wa.win_gravity = WestGravity;
-	} else if (how == @symbol(East)) {
-	    wa.win_gravity = EastGravity;
-	} else {
-	    wa.win_gravity = NorthWestGravity;
-	}
-
-
-	ENTER_XLIB();
-	XChangeWindowAttributes(myDpy, __WindowVal(aWindowId), CWWinGravity, &wa);
-	LEAVE_XLIB();
-
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowIcon:aForm in:aWindowId
-    "define a bitmap to be used as icon"
-
-    <context: #return>
-
-    |iconId|
-
-    aForm notNil ifTrue:[
-	iconId := aForm id
-    ].
-%{
-    if (ISCONNECTED
-     && __isExternalAddress(iconId)
-     && __isExternalAddress(aWindowId)) {
-	XWMHints hints;
-
-	hints.icon_pixmap = __PixmapVal(iconId);
-	hints.flags = IconPixmapHint;
-	ENTER_XLIB();
-	XSetWMHints(myDpy, __WindowVal(aWindowId), &hints);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowIcon:aForm mask:aMaskForm in:aWindowId
-    "define a windows icon and (optional) iconMask."
-
-    <context: #return>
-
-    |iconId maskId|
-
-    aForm notNil ifTrue:[
-	iconId := aForm id
-    ].
-    aMaskForm notNil ifTrue:[
-	maskId := aMaskForm id.
-    ].
-%{
-    if (ISCONNECTED
-     && __isExternalAddress(iconId)
-     && __isExternalAddress(aWindowId)) {
-	XWMHints hints;
-
-	hints.icon_pixmap = __PixmapVal(iconId);
-	hints.flags = IconPixmapHint;
-	if ((maskId != nil)
-	 && __isExternalAddress(maskId)) {
-	    hints.icon_mask = __PixmapVal(maskId);
-	    hints.flags |= IconMaskHint;
-	}
-	ENTER_XLIB();
-	XSetWMHints(myDpy, __WindowVal(aWindowId), &hints);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-
-!
-
-setWindowIconWindow:aView in:aWindowId
-    "define a window to be used as icon"
-
-    <context: #return>
-
-    |iconWindowId|
-
-    aView notNil ifTrue:[
-	iconWindowId := aView id
-    ].
-%{
-    if (ISCONNECTED
-     && __isExternalAddress(iconWindowId)
-     && __isExternalAddress(aWindowId)) {
-	XWMHints wmhints;
-
-	wmhints.icon_window = __WindowVal(iconWindowId);
-	wmhints.flags = IconWindowHint;
-	ENTER_XLIB();
-	XSetWMHints(myDpy, __WindowVal(aWindowId), &wmhints);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowMinExtentX:minW y:minH maxExtentX:maxW y:maxH in:aWindowId
-    "set a windows minimum & max extents.
-     nil arguments are ignored."
-
-    <context: #return>
-%{
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	Display *dpy = myDpy;
-	XSizeHints szhints;
-	Window win;
-
-	win = __WindowVal(aWindowId);
-
-	szhints.flags = 0;
-	if (__bothSmallInteger(minW, minH)) {
-	    szhints.flags |= PMinSize;
-	    szhints.min_width = __intVal(minW);
-	    szhints.min_height = __intVal(minH);
-	}
-	if (__bothSmallInteger(maxW, maxH)) {
-	    szhints.flags |= PMaxSize;
-	    szhints.max_width = __intVal(maxW);
-	    szhints.max_height = __intVal(maxH);
-	}
-
-	if (szhints.flags) {
-	    ENTER_XLIB();
-	    XSetNormalHints(dpy, win, &szhints);
-	    LEAVE_XLIB();
-	}
-    }
-%}.
-!
-
-setWindowName:aString in:aWindowId
-    "define a windows name"
-
-    <context: #return>
-
-    |utf8StringAtom utf8String simpleString|
-
-    utf8StringAtom := self atomIDOf:#UTF8_STRING create:true.
-
-    utf8String := aString utf8Encoded.
-    aString isWideString ifTrue:[
-	"/ X does not like 2-byte labels ...
-	simpleString := aString asSingleByteStringReplaceInvalidWith:$?
-    ] ifFalse:[
-	simpleString := aString.
-    ].
-
-%{
-
-    XTextProperty titleProperty;
-
-    if (ISCONNECTED
-     && __isStringLike(utf8String)
-     && __isStringLike(simpleString)
-     && __isExternalAddress(aWindowId)) {
-
-	titleProperty.value =  __stringVal(utf8String);
-	titleProperty.encoding = __smallIntegerVal(utf8StringAtom);
-	titleProperty.format = 8;
-	titleProperty.nitems = __stringSize(utf8String);
-
-	ENTER_XLIB();
-	XStoreName(myDpy, __WindowVal(aWindowId), (char *) __stringVal(simpleString));
-	/* alternative settings for UTF8-Strings */
-	XSetWMName(myDpy, __WindowVal(aWindowId), &titleProperty);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowPid:anIntegerOrNil in:aWindowId
-    "Sets the _NET_WM_PID property for the window.
-     This may be used by the window manager to group windows.
-     If anIntegerOrNil is nil, then PID of currently running
-     Smalltalk is used"
-
-    | propertyID typeId pid |
-
-    propertyID := self atomIDOf: '_NET_WM_PID' create: false.
-    propertyID isNil ifTrue:[ ^ self ].
-    pid := anIntegerOrNil isNil ifTrue:[OperatingSystem getProcessId] ifFalse:[anIntegerOrNil].
-    typeId := self atomIDOf:#'CARDINAL' create:false.
-
-    self setProperty:propertyID type:typeId value:pid for:aWindowId
-
-    "Created: / 04-01-2013 / 16:03:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-setWindowShape:aPixmapId in:aWindowId
-    "set the windows shape.
-     Returns false, if the display does not support the
-     X shape extension."
-
-    <context: #return>
-
-    hasShapeExtension ifFalse:[^ self].
-
-%{
-
-#ifdef SHAPE
-    Pixmap shapeBitmap;
-
-    if (__isExternalAddress(aPixmapId))
-	shapeBitmap = __PixmapVal(aPixmapId);
-    else
-	shapeBitmap = (Pixmap)0;
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	ENTER_XLIB();
-	XShapeCombineMask(myDpy, __WindowVal(aWindowId), ShapeClip,
-			  0, 0,
-			  shapeBitmap, ShapeSet);
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-#endif
-%}.
-    self primitiveFailedOrClosedConnection
-!
-
-setWindowState:aSymbol in:aWindowId
-    "tell the window type to the window manager.
-     Send a specific message to the WindowManager"
-
-    |netWmWindowStateAtom stateAtom|
-
-    netWmWindowStateAtom := self atomIDOf:#'_NET_WM_WINDOW_STATE' create:false.
-    stateAtom := self atomIDOf:aSymbol create:false.
-
-    (netWmWindowStateAtom notNil and:[stateAtom notNil]) ifTrue:[
-	self
-	    sendClientEvent:netWmWindowStateAtom
-	    format:32
-	    to:(self rootWindowId)
-	    propagate:true
-	    eventMask:((self eventMaskFor:#substructureNotify) bitOr:(self eventMaskFor:#substructureRedirect))
-	    window:aWindowId
-	    data1:(self atomIDOf:#'_NET_WM_STATE_ADD' create:false)
-	    data2:stateAtom
-	    data3:nil
-	    data4:1
-	    data5:nil.
-    ] ifFalse:[self halt.].
-
-    "
-      |v|
-
-      v := TopView new create.
-      Display setWindowState:#'_NET_WM_WINDOW_STATE_STICKY' in:v id.
-      v open.
-    "
-!
-
-setWindowType:aSymbol in:aWindowId
-    "Tell the window type to the window manager.
-     See Extended Window Manager Hints 1.3,
-     chapter 'Application Window Properties'
-     http://standards.freedesktop.org/wm-spec/1.3/
-
-    JV@2012-05-15: There was some code prior 2012-05-15,
-    but that code does not work anymore and I wonder if it
-    ever worked correctly. I changed it to be
-    EWMH compatible, as this improve UX on modern Linxu
-    machines.
-
-    It also helps to fix super-annoying problem with window autoraiser
-    on X11 in a proper way - window manager should manage top-level
-    window stacking, that's why it is called a 'window manager' :-)
-
-    "
-
-    | nameAtom typeAtom valueAtom |
-
-    self assert:(#(_NET_WM_WINDOW_TYPE_DESKTOP
-		  _NET_WM_WINDOW_TYPE_DOCK
-		  _NET_WM_WINDOW_TYPE_TOOLBAR
-		  _NET_WM_WINDOW_TYPE_MENU
-		  _NET_WM_WINDOW_TYPE_UTILITY
-		  _NET_WM_WINDOW_TYPE_SPLASH
-		  _NET_WM_WINDOW_TYPE_DIALOG
-		  _NET_WM_WINDOW_TYPE_NORMAL) includes: aSymbol).
-
-    nameAtom := self atomIDOf:#'_NET_WM_WINDOW_TYPE' create:false.
-    nameAtom isNil ifTrue:[
-	"/Hmm, no such property, not running under EWMH compliant WM?
-	self breakPoint: #jv.
-	^self
-    ].
-    "/ Hmm, hmm, no access to XA_ATOM, XA_INTEGER and so on...
-    typeAtom := self atomIDOf:#'ATOM' create:false.
-    typeAtom isNil ifTrue:[
-	self error:'Oops, no ATOM atom'.
-    ].
-    valueAtom := self atomIDOf: aSymbol create:false.
-    valueAtom isNil ifTrue:[
-	"/Hmm, no such property, not running under EWMH compliant WM?
-	self breakPoint: #jv.
-	^self
-    ].
-
-    self setProperty: nameAtom type: typeAtom value: valueAtom for: aWindowId.
-
-
-"/   Original code that does not work (if ever worked)
-"/
-"/    |netWmWindowTypeAtom typeAtom|
-"/
-"/    netWmWindowTypeAtom := self atomIDOf:#'_NET_WM_WINDOW_TYPE' create:false.
-"/    typeAtom := self atomIDOf:aSymbol create:false.
-"/
-"/    (netWmWindowTypeAtom notNil and:[typeAtom notNil]) ifTrue:[
-"/        self
-"/            sendClientEvent:netWmWindowTypeAtom
-"/            format:32
-"/            to:(self rootWindowId)
-"/            propagate:true
-"/            eventMask:((self eventMaskFor:#substructureNotify) bitOr:(self eventMaskFor:#substructureRedirect))
-"/            window:aWindowId
-"/            data1:typeAtom
-"/            data2:nil
-"/            data3:nil
-"/            data4:nil
-"/            data5:nil.
-"/    ].
-
-    "
-      |v|
-
-      v := TopView new create.
-      Display setWindowType:#'_NET_WM_WINDOW_TYPE_DOCK' in:v id.
-      v open.
-
-      |v|
-
-      v := TopView new create.
-      Display setWindowType:#'_NET_WM_WINDOW_TYPE_UTILITY' in:v id.
-      v open.
-    "
-
-    "Modified (comment): / 15-05-2012 / 10:49:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-unmapWindow:aWindowId
-    "make a window invisible"
-
-    <context: #return>
-%{
-    /*
-     * ignore closed connection
-     */
-    if (! ISCONNECTED) {
-	RETURN ( self );
-    }
-
-    if (__isExternalAddress(aWindowId)) {
-	ENTER_XLIB();
-	XUnmapWindow(myDpy, __WindowVal(aWindowId));
-	LEAVE_XLIB();
-	RETURN ( self );
-    }
-%}.
-    self primitiveFailed
-!
-
-windowIsIconified:aWindowId
-    "return true, if some window is iconified.
-     The passed windowID may be an alien windows id."
-
-    <context: #return>
-%{
-
-    if (ISCONNECTED
-     && __isExternalAddress(aWindowId)) {
-	Atom JunkAtom;
-	int JunkInt;
-	unsigned long WinState,JunkLong;
-	unsigned char *Property;
-	Atom WM_STATE_Atom;
-
-	if (__INST(wmStateAtom) != nil) {
-	    WM_STATE_Atom = __AtomVal(__INST(wmStateAtom));
-
-	    ENTER_XLIB();
-	    XGetWindowProperty(myDpy, __WindowVal(aWindowId),
-			       WM_STATE_Atom,
-			       0L, 2L, False, AnyPropertyType,
-			       &JunkAtom,&JunkInt,&WinState,&JunkLong,
-			       &Property);
-	    LEAVE_XLIB();
-	    WinState=(unsigned long)(*((long*)Property));
-	    if (WinState==3) {
-		RETURN (true);
-	    }
-	}
-	RETURN (false);
-    }
-%}.
-    self primitiveFailedOrClosedConnection.
-    ^ false "/ or true or what ?
-! !
-
-!XWorkstation::SelectionFetcher class methodsFor:'documentation'!
-
-documentation
-"
-    This class is responsible for fetching the clipboard.
-    The X11 clipboard is implemented via asynchonous messages.
-
-    For each fetch operation an instance of this class is created.
-    The asynchronous messages are queued and executed in the
-    process that requests the clipboard.
-
-    [author:]
-	Stefan Vogel (stefan@zwerg)
-
-    [instance variables:]
-
-    [class variables:]
-
-    [see also:]
-
-"
-! !
-
-!XWorkstation::SelectionFetcher class methodsFor:'selections'!
-
-requestSelection:selectionId type:aTargetId onDevice:aDisplay for:aDrawableId
-    ^ self new requestSelection:selectionId type:aTargetId onDevice:aDisplay for:aDrawableId
-! !
-
-!XWorkstation::SelectionFetcher methodsFor:'accessing'!
-
-drawableID
-    ^ drawableID
-!
-
-getSelection
-    "convert the data in buffer to a selection"
-
-    |selection|
-
-    buffer isNil ifTrue:[
-	^ nil.
-    ].
-
-    targetID == (display atomIDOf:#STRING) ifTrue:[
-	display clipboardEncoding notNil ifTrue:[
-	    selection := buffer decodeFrom:display clipboardEncoding
-	].
-	selection := buffer.
-    ] ifFalse:[targetID == (display atomIDOf:#'UTF8_STRING') ifTrue:[
-"/ Transcript show:'UTF8: '; showCR:buffer storeString.
-	selection := CharacterArray fromUTF8Bytes:buffer
-    ] ifFalse:[targetID == (display atomIDOf:#TEXT) ifTrue:[
-"/ Transcript show:'TEXT: '; showCR:buffer storeString.
-	selection := buffer asString
-    ] ifFalse:[targetID == (display atomIDOf:#'COMPOUND_TEXT') ifTrue:[
-"/ Transcript show:'COMPOUND_TEXT: '; showCR:buffer storeString.
-	selection := buffer asString
-    ]]]].
-
-    selection notNil ifTrue:[
-	(selection endsWith:Character cr) ifTrue:[
-	    selection := selection asStringCollection copyWith:''
-	].
-	^ selection.
-    ].
-
-    targetID == (display atomIDOf:#'TARGETS') ifTrue:[
-	^ buffer
-    ].
-    targetID == (display atomIDOf:#'ST_OBJECT') ifTrue:[
-	"require libboss to be loaded"
-	(Smalltalk isClassLibraryLoaded:'libstx_libboss') ifFalse:[
-	    'SelectionFetch: cannot decode object (libboss library missing)' errorPrintCR.
-	    ^ nil
-	].
-	^ (Object
-	    readBinaryFrom:(ReadStream on:buffer)
-	    onError:[:ex |
-		('SelectionFetch: error while decoding binary object: ',ex description) errorPrintCR.
-		nil
-	    ])
-    ].
-
-    'XWorkstation: unimplemented property targetID: ' infoPrint. (display atomName:targetID) infoPrint.
-    ' buffer:' infoPrint. buffer infoPrintCR.
-    ^ nil
-
-    "Modified: / 23-08-2006 / 15:56:04 / cg"
-! !
-
-!XWorkstation::SelectionFetcher methodsFor:'event handling'!
-
-message:aMessage
-    "got an asynchronous event from the display.
-     Save and wake up waiters"
-
-    aMessage selector == #propertyChange:property:state:time: ifTrue:[
-	(aMessage arguments at:2) ~~ propertyID ifTrue:[
-	    "I am only interested in changes of the property used to
-	     store the selection"
-	    ^ self.
-	].
-	message notNil ifTrue:[
-	    "this should not happen - bad selection holder?"
-	    'XWorkstation(error): message overflow: ' errorPrint. display errorPrintCR.
-	    ^ self.
-	].
-    ].
-
-    "we get a propertyChange before the selectionNotify.
-     Since the propertyChange will be ignored anyway (because we are not in incremental mod,
-     a selectionNotify message may overwrite a propertyChange message"
-
-    message := aMessage.
-    sema signal.
-!
-
-propertyChange:aView property:aPropertyId state:stateSymbol time:time
-    "this is a forwarded propretyChange event from XWorkstation"
-
-    |property propertyValue|
-
-    incremental ifFalse:[
-	"ignore property changes until we are in incremental mode"
-	^ self.
-    ].
-
-    property := display getProperty:propertyID from:drawableID delete:true.
-    propertyValue := property value.
-
-    propertyValue size == 0 ifTrue:[
-	"property with size 0 signals end of transfer"
-	done := true.
-    ] ifFalse:[
-	buffer isNil ifTrue:[
-	    targetID := property key.
-	    buffer := propertyValue.
-	] ifFalse:[
-	    targetID ~= property key ifTrue:[
-		'XWorkstation(warning): targetID change in incremental select: ' errorPrint. display errorPrintCR.
-	    ].
-	    buffer := buffer, propertyValue.
-	].
-    ].
-!
-
-selectionClear:aView selection:selectionId time:time
-    "sent when another X-client has created a selection.
-     This is a very X-specific mechanism."
-!
-
-selectionNotify:aView selection:aSelectionID target:aTargetID property:aPropertyID requestor:requestorID time:time
-    "this is a forwarded selectionNotify event from XWorkstation"
-
-    |property propertyKey atomName|
-
-    aSelectionID ~~ selectionID ifTrue:[
-	"ignore notification that is not for our selection"
-	^ self.
-    ].
-
-    aPropertyID == 0 ifTrue:[
-	"the selection owner could not convert the selection to our target type"
-	done := true.
-	^ self.
-    ].
-
-    property := display getProperty:aPropertyID from:drawableID delete:true.
-    property isNil ifTrue:[
-	"the property does not exist in the specified window"
-	done := true.
-	^ self
-    ].
-
-    propertyKey := property key.
-    propertyKey == aTargetID ifTrue:[
-	"good, the property is consistent with our request.
-	 The whole selection is in the property"
-	buffer := property value.
-	done := true.
-    ] ifFalse:[propertyKey == (display atomIDOf:#INCR) ifTrue:[
-	"this is an incremental transfer. Wait for property change"
-	incremental := true.
-    ] ifFalse:[
-	atomName := (display atomName:propertyKey) ? propertyKey.
-	'XWorkstation(error): unexpected targetID (' errorPrint.
-	atomName errorPrint.
-	') in selectionNotify: ' errorPrint.
-	display errorPrintCR.
-	done := true.
-    ]].
-! !
-
-!XWorkstation::SelectionFetcher methodsFor:'selection actions'!
-
-requestSelection:aSelectionId type:aTargetId onDevice:aDisplay for:aDrawableId
-    "request the selection of type targetId.
-     Wait for next asynchronous message and process it,
-     until done"
-
-    display := aDisplay.
-    drawableID := aDrawableId.
-    selectionID := aSelectionId.
-    propertyID := display atomIDOf:#'VT_SELECTION'.
-    targetID := aTargetId.
-    sema := Semaphore new name:'X11SelectionFetcher'.
-    done := false.
-    incremental := false.
-
-    [
-	|timeout|
-
-	display registerSelectionFetcher:self.
-
-	display
-	    requestSelection:aSelectionId
-	    type:aTargetId
-	    for:drawableID
-	    intoProperty:propertyID.
-
-	timeout := display xlibTimeout.
-	[
-	    |currentMessage|
-
-	    (sema waitWithTimeout:timeout) isNil ifTrue:[
-		"the selection owner didn't respond within reasonable time"
-		'XWorkstation(error): selection owner does not respond:' infoPrint. display infoPrintCR.
-		^ nil.
-	    ].
-	    currentMessage := message.
-	    message := nil.
-	    currentMessage notNil ifTrue:[currentMessage sendTo:self].
-	] doUntil:[done].
-    ] ensure:[
-	display unregisterSelectionFetcher:self.
-    ].
-
-    ^ self getSelection
-! !
-
-!XWorkstation::SelectionFetcher methodsFor:'testing'!
-
-matchesDrawableId:aDrawableId
-    "return true, if this SelectionFetcher fetches for aDrawableId"
-
-    ^ drawableID = aDrawableId
-! !
-
-!XWorkstation::WindowGroupWindow class methodsFor:'documentation'!
-
-documentation
-"
-    A special window to serve as window group id. This window
-    is newer mapped.
-
-    [author:]
-	Jan Vrany <jan.vrany@fit.cvut.cz>
-
-    [instance variables:]
-
-    [class variables:]
-
-    [see also:]
-	Inter-Client Communication Conventions Manual [http://tronche.com/gui/x/icccm/]
-
-
-"
+#endif
+%}.
+    ^ super displayString:aString x:x y:y opaque:opaque
 ! !
 
 !XWorkstation class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.582 2014-02-04 15:34:49 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.592.2.1 2014-05-08 08:27:50 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.582 2014-02-04 15:34:49 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/XWorkstation.st,v 1.592.2.1 2014-05-08 08:27:50 stefan Exp $'
 !
 
 version_SVN
--- a/XftFontDescription.st	Thu Feb 06 12:50:14 2014 +0100
+++ b/XftFontDescription.st	Thu May 08 10:27:51 2014 +0200
@@ -1,7 +1,9 @@
+'From Smalltalk/X, Version:6.2.3.0 on 08-05-2014 at 10:08:24'                   !
+
 "{ Package: 'stx:libview' }"
 
 FontDescription subclass:#XftFontDescription
-	instanceVariableNames:'device fontId drawId closestFont'
+	instanceVariableNames:'device fontId sharedDrawId closestFont minCode maxCode'
 	classVariableNames:'FC_FAMILY FC_STYLE FC_SLANT FC_WEIGHT FC_SIZE FC_ASPECT
 		FC_PIXEL_SIZE FC_SPACING FC_FOUNDRY FC_ANTIALIAS FC_HINTING
 		FC_HINT_STYLE FC_VERTICAL_LAYOUT FC_AUTOHINT FC_WIDTH FC_FILE
@@ -25,11 +27,18 @@
 		FC_RGBA_VBGR FC_RGBA_NONE FC_HINT_NONE FC_HINT_SLIGHT
 		FC_HINT_MEDIUM FC_HINT_FULL FC_LCD_NONE FC_LCD_DEFAULT
 		FC_LCD_LIGHT FC_LCD_LEGACY StXFace2FCWeightMap
-		StXStyle2FCSlantMap'
+		StXStyle2FCSlantMap CachedFontList RecentlyUsedFonts'
 	poolDictionaries:''
 	category:'Graphics-Support'
 !
 
+Object subclass:#FCFontListParser
+	instanceVariableNames:'pipeStream lineStream currentDescription'
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:XftFontDescription
+!
+
 ExternalAddress subclass:#FCPatternHandle
 	instanceVariableNames:''
 	classVariableNames:''
@@ -148,6 +157,14 @@
 
 !XftFontDescription class methodsFor:'initialization'!
 
+flushListOfAvailableFonts
+    CachedFontList := nil.
+
+    "
+     XftFontDescription flushListOfAvailableFonts
+    "
+!
+
 initialize
     "Invoked at system start or when the class is dynamically loaded."
 
@@ -258,9 +275,23 @@
     FC_LCD_LEGACY           := 3.
 
     StXFace2FCWeightMap := Dictionary withKeysAndValues:{
-	'regular'.  FC_WEIGHT_REGULAR.
-	'medium'.   FC_WEIGHT_MEDIUM.
-	'bold'.     FC_WEIGHT_BOLD.
+	'thin'.       FC_WEIGHT_THIN.
+	'extralight'. FC_WEIGHT_EXTRALIGHT.
+	'ultralight'. FC_WEIGHT_ULTRALIGHT.
+	'light'.      FC_WEIGHT_LIGHT.
+	'book'.       FC_WEIGHT_BOOK.
+	'regular'.    FC_WEIGHT_REGULAR.
+	'normal'.     FC_WEIGHT_NORMAL.
+	'medium'.     FC_WEIGHT_MEDIUM.
+	'demibold'.   FC_WEIGHT_DEMIBOLD.
+	'semibold'.   FC_WEIGHT_SEMIBOLD.
+	'bold'.       FC_WEIGHT_BOLD.
+	'extrabold'.  FC_WEIGHT_EXTRABOLD.
+	'ultrabold'.  FC_WEIGHT_ULTRABOLD.
+	'black'.      FC_WEIGHT_BLACK.
+	'heavy'.      FC_WEIGHT_HEAVY.
+	'extrablack'. FC_WEIGHT_EXTRABLACK.
+	'ultrablack'. FC_WEIGHT_ULTRABLACK.
     }.
     StXStyle2FCSlantMap := Dictionary withKeysAndValues:{
 	'roman'.    FC_SLANT_ROMAN.
@@ -271,6 +302,38 @@
     "Modified: / 30-12-2013 / 19:48:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!XftFontDescription class methodsFor:'instance creation'!
+
+family:familyString face:faceString style:styleString size:size sizeUnit:sizeUnit encoding:encoding
+    "returns a font for given family, face, style, size and the specified encoding.
+     The returned font is not associated to a specific device"
+
+    |proto|
+
+    CachedFontList notNil ifTrue:[
+	proto := CachedFontList
+		detect:[:fn |
+		    fn family = familyString
+		    and:[ fn face = faceString
+		    and:[ (fn style = styleString
+			  or:[ (fn style = 'oblique' and:[styleString = 'italic'])
+			  or:[ (fn style = 'italic' and:[styleString = 'oblique']) ]]) ]]]
+		ifNone:nil.
+	proto notNil ifTrue:[
+	    ^ (proto shallowCopy)
+		setDevice: nil patternId: nil fontId: nil;
+		family:familyString face:faceString style:styleString size:size sizeUnit:sizeUnit encoding:encoding
+	].
+    ].
+    ^ super
+	family:familyString face:faceString style:styleString size:size sizeUnit:sizeUnit encoding:encoding
+!
+
+new
+"/    self halt.
+    ^ super new.
+! !
+
 !XftFontDescription class methodsFor:'examples'!
 
 example1
@@ -316,16 +379,151 @@
     top open.
 
     "Created: / 30-12-2013 / 19:49:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+example3
+    "
+    XftFontDescription example2
+    "
+    |top textView|
+
+    top := StandardSystemView new.
+    top extent:300@200.
+
+    textView := EditTextView new.
+    textView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
+    textView basicFont: (XftFontDescription family: 'Indie Flower' size: 30).
+
+    top addSubView:textView.
+
+    textView contents:('/etc/hosts' asFilename contentsOfEntireFile).
+
+    top open.
+
+    "Created: / 30-12-2013 / 19:49:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
-!XftFontDescription methodsFor:'accessing-private'!
+!XftFontDescription class methodsFor:'queries'!
+
+listOfAvailableFonts
+    "uses fc-list to get a list of available fontDescriptions"
+
+    CachedFontList isNil ifTrue:[
+	CachedFontList := FCFontListParser new listOfAvailableFonts
+    ].
+    ^ CachedFontList
+
+    "
+     XftFontDescription flushListOfAvailableFonts.
+     XftFontDescription listOfAvailableFonts
+    "
+! !
 
-getDevice
+!XftFontDescription methodsFor:'accessing'!
+
+encoding
+    ^ encoding ? #'iso10646-1'
+!
+
+face
+    ^ face ? ''
+!
+
+fullName
+    ^ name ? (self userFriendlyName)
+!
+
+graphicsDevice
     ^ device
 
     "Created: / 02-01-2014 / 23:22:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
+maxCode
+    ^ maxCode ? 16rFFFF
+!
+
+maxCode:something
+    maxCode := something.
+!
+
+minCode
+    ^ minCode ? 0
+!
+
+minCode:something
+    minCode := something.
+!
+
+size
+    ^ size ? 0
+!
+
+style
+    ^ style ? ''
+!
+
+weight:aNumber
+    "set the weight"
+
+    self assert:(self fontId isNil). "/ cannot change an instantiated font
+
+    aNumber == FC_WEIGHT_THIN ifTrue:[ face := 'thin'. ^ self].
+    aNumber == FC_WEIGHT_EXTRALIGHT ifTrue:[ face := 'extralight'. ^ self].
+    aNumber == FC_WEIGHT_LIGHT ifTrue:[ face := 'light'. ^ self].
+    aNumber == FC_WEIGHT_BOOK ifTrue:[ face := 'book'. ^ self].
+    aNumber == FC_WEIGHT_REGULAR ifTrue:[ face := 'regular'. ^ self].
+    aNumber == FC_WEIGHT_MEDIUM ifTrue:[ face := 'medium'. ^ self].
+    aNumber == FC_WEIGHT_DEMIBOLD ifTrue:[ face := 'demibold'. ^ self].
+    aNumber == FC_WEIGHT_BOLD ifTrue:[ face := 'bold'. ^ self].
+    aNumber == FC_WEIGHT_EXTRABOLD ifTrue:[ face := 'extrabold'. ^ self].
+    aNumber == FC_WEIGHT_BLACK ifTrue:[ face := 'black'. ^ self].
+    aNumber == FC_WEIGHT_EXTRABLACK ifTrue:[ face := 'extrablack'. ^ self].
+
+    aNumber <= (FC_WEIGHT_EXTRALIGHT + FC_WEIGHT_LIGHT // 2) ifTrue:[
+	face := 'extralight'.
+	^ self.
+    ].
+    aNumber <= (FC_WEIGHT_LIGHT + FC_WEIGHT_BOOK // 2) ifTrue:[
+	face := 'light'.
+	^ self.
+    ].
+    aNumber <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD // 2) ifTrue:[
+	face := 'medium'.
+	^ self.
+    ].
+    aNumber <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD // 2) ifTrue:[
+	face := 'demibold'.
+	^ self.
+    ].
+    aNumber <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK // 2) ifTrue:[
+	face := 'bold'.
+	^ self.
+    ].
+    face := 'extrabold'.
+    ^ self
+
+"/    FC_WEIGHT_THIN          := 0.
+"/    FC_WEIGHT_EXTRALIGHT    := 40.
+"/    FC_WEIGHT_ULTRALIGHT    := FC_WEIGHT_EXTRALIGHT.
+"/    FC_WEIGHT_LIGHT         := 50.
+"/    FC_WEIGHT_BOOK          := 75.
+"/    FC_WEIGHT_REGULAR       := 80.
+"/    FC_WEIGHT_NORMAL        := FC_WEIGHT_REGULAR.
+"/    FC_WEIGHT_MEDIUM        := 100.
+"/    FC_WEIGHT_DEMIBOLD      := 180.
+"/    FC_WEIGHT_SEMIBOLD      := FC_WEIGHT_DEMIBOLD.
+"/    FC_WEIGHT_BOLD          := 200.
+"/    FC_WEIGHT_EXTRABOLD     := 205.
+"/    FC_WEIGHT_ULTRABOLD     := FC_WEIGHT_EXTRABOLD.
+"/    FC_WEIGHT_BLACK         := 210.
+"/    FC_WEIGHT_HEAVY         := FC_WEIGHT_BLACK.
+"/    FC_WEIGHT_EXTRABLACK    := 215.
+"/    FC_WEIGHT_ULTRABLACK    := FC_WEIGHT_EXTRABLACK.
+! !
+
+!XftFontDescription methodsFor:'accessing-private'!
+
 getFontId
     ^ fontId
 
@@ -334,58 +532,79 @@
 
 !XftFontDescription methodsFor:'displaying'!
 
-displayString:aString from:index1 to:index2 x:xArg y:yArg in:aGC opaque:opaque
+displayString:aString from:index1 to:index2Arg x:xArg y:yArg in:aGC opaque:opaque
     "display a partial string at some position in aGC."
 
-    |bytesPerCharacter transformation clipR clipX clipY clipW clipH fg fgR fgG fgB fgA fgPixel bg bgR bgG bgB bgA bgPixel drawX drawY displayId screen drawableId error |
-
-    bytesPerCharacter := aString bitsPerCharacter // 8.
-    transformation := aGC transformation.
+    |index2 bytesPerCharacter transformation clipR clipX clipY clipW clipH fg fgR fgG fgB fgA fgPixel
+     bg bgR bgG bgB bgA bgPixel drawX drawY displayId screen drawableId error stringLen|
 
-    transformation isNil ifTrue:[
-	drawX := xArg.
-	drawY := yArg.
-    ] ifFalse:[
-	drawX := transformation applyToX: xArg.
-	drawY := transformation applyToY: yArg.
+    "limit the string len, otherwise bad output is generated"
+    stringLen := index2Arg - index1.
+    stringLen > 4000 ifTrue:[
+        index2 := index1 + 4000.
+    ]  ifFalse:[
+        index2 := index2Arg.
+    ].
+    bytesPerCharacter := aString bitsPerCharacter // 8.
+
+    clipR := aGC deviceClippingBoundsOrNil.
+    clipR notNil ifTrue:[
+        clipX := clipR left.
+        clipY := clipR top.
+        clipW := clipR width.
+        clipH := clipR height.
+clipW > 32767 ifTrue:['clipW > 32767 ' errorPrintCR. clipW errorPrintCR. self halt. clipW := 32767].
+(clipX > 16384 or:[clipX < -16384]) ifTrue:['clipX < 16384 ' errorPrintCR. clipX errorPrintCR.].
     ].
 
-    clipR := aGC clippingRectangleOrNil.
-    clipR notNil ifTrue:[
-	clipX := clipR left.
-	clipY := clipR top.
-	clipW := clipR width.
-	clipH := clipR height.
-	transformation notNil ifTrue:[
-	    clipX := transformation applyToX: clipX.
-	    clipY := transformation applyToY: clipY.
-	    clipW := transformation applyScaleX: clipW.
-	    clipH := transformation applyScaleY: clipH.
-	].
+    transformation := aGC transformation.
+    transformation isNil ifTrue:[
+        drawX := xArg.
+        drawY := yArg.
+    ] ifFalse:[
+        drawX := (transformation applyToX:xArg) ceiling.
+        drawY := (transformation applyToY:yArg) ceiling.
     ].
 
     fg  :=  aGC paint.
     fgPixel := fg colorId.
-    "/ fgPixel isNil ifTrue:[
-	fgR := fg scaledRed.
-	fgG := fg scaledGreen.
-	fgB := fg scaledBlue.
-	fgA := (fg alpha * 65535) rounded.
-    "/].
+    fgA := fg scaledAlpha.
+    fgR := fg scaledRed.
+    fgR notNil ifTrue:[
+        fgG := fg scaledGreen.
+        fgB := fg scaledBlue.
+    ] ifFalse:[
+        "/ when drawing into a pixmap...
+        fgPixel == 0 ifTrue:[
+            fgR := fgG := fgB := 0.
+        ] ifFalse:[
+            fgR := fgG := fgB := 16rFFFF.
+        ]
+    ].
 
     opaque ifTrue:[
-	bg  := aGC backgroundPaint.
-	bgPixel := bg colorId.
-	"/bgPixel notNil ifTrue:[
-	    bgR := bg scaledRed.
-	    bgG := bg scaledGreen.
-	    bgB := bg scaledBlue.
-	    bgA := (bg alpha * 65535) rounded.
-	"/].
+        bg  := aGC backgroundPaint.
+        bgPixel := bg colorId.
+        bgA := bg scaledAlpha.
+        bgR := bg scaledRed.
+        bgR notNil ifTrue:[
+            bgG := bg scaledGreen.
+            bgB := bg scaledBlue.
+        ] ifFalse:[
+            "/ when drawing into a pixmap...
+            bgPixel == 0 ifTrue:[
+                bgR := bgG := bgB := 0.
+            ] ifFalse:[
+                bgR := bgG := bgB := 16rFFFF.
+            ]
+        ].
     ].
-    displayId := device displayId.
+    displayId := device displayIdOrErrorIfBroken.
+    displayId isNil ifTrue:[
+        ^ self.
+    ].
     screen := device screen.
-    drawableId := aGC id.
+    drawableId := aGC drawableId.
 
 %{
 #ifdef XFT
@@ -399,102 +618,103 @@
     int __bytesPerCharacter;
 
     if (!(__bothSmallInteger(drawX, drawY)
-	  && __bothSmallInteger(index1, index2)
-	  && __isSmallInteger(bytesPerCharacter)
-	  && (__isSmallInteger(fgPixel) || (__bothSmallInteger(fgR, fgG) && __bothSmallInteger(fgB, fgA)))
-	  && (opaque == false || __isSmallInteger(bgPixel) || (__bothSmallInteger(bgR, bgG) && __bothSmallInteger(bgB, bgA)))
-	  && __isNonNilObject(aString)
+          && __bothSmallInteger(index1, index2)
+          && __isSmallInteger(bytesPerCharacter)
+          && (__isSmallInteger(fgPixel) || (__bothSmallInteger(fgR, fgG) && __bothSmallInteger(fgB, fgA)))
+          && (opaque == false || __isSmallInteger(bgPixel) || (__bothSmallInteger(bgR, bgG) && __bothSmallInteger(bgB, bgA)))
+          && __isNonNilObject(aString)
     )) {
-	goto err;
+        goto err;
     }
 
     __bytesPerCharacter = __intVal(bytesPerCharacter);
 
-    if ( __INST(drawId) == nil ) {
-	__INST(drawId) = XFT_DRAW_HANDLE_NEW ( XftDrawCreate ( DISPLAY( displayId ) ,
-					       DRAWABLE( drawableId ) ,
-					       DefaultVisual( DISPLAY( displayId), SCREEN (screen) ) ,
-					       DefaultColormap( DISPLAY( displayId), SCREEN (screen) ) ) );
-	__STORE(self, __INST(drawId));
+    if ( __INST(sharedDrawId) == nil ) {
+        __INST(sharedDrawId) = XFT_DRAW_HANDLE_NEW ( XftDrawCreate ( DISPLAY( displayId ) ,
+                                               DRAWABLE( drawableId ) ,
+                                               DefaultVisual( DISPLAY( displayId), SCREEN (screen) ) ,
+                                               DefaultColormap( DISPLAY( displayId), SCREEN (screen) ) ) );
+        __STORE(self, __INST(sharedDrawId));
     }
 
-    if ( XftDrawDrawable ( XFT_DRAW ( __INST(drawId) ) ) != DRAWABLE( drawableId ) ) {
-	XftDrawChange( XFT_DRAW( __INST(drawId) ) , DRAWABLE( drawableId ) );
+    if ( XftDrawDrawable ( XFT_DRAW ( __INST(sharedDrawId) ) ) != DRAWABLE( drawableId ) ) {
+        XftDrawChange( XFT_DRAW( __INST(sharedDrawId) ) , DRAWABLE( drawableId ) );
     }
 
     string = __stringVal( aString ) + (( __intVal(index1) - 1 ) * __bytesPerCharacter);
     len = __intVal(index2) - __intVal(index1) + 1;
 
     if (clipR != nil) {
-	clipRX.x = __intVal(clipX);
-	clipRX.y = __intVal(clipY);
-	clipRX.width = __intVal(clipW);
-	clipRX.height = __intVal(clipH);
-	XftDrawSetClipRectangles( XFT_DRAW( __INST( drawId ) ) , 0, 0, &clipRX, 1);
+        clipRX.x = __intVal(clipX);
+        clipRX.y = __intVal(clipY);
+        clipRX.width = __intVal(clipW);
+        clipRX.height = __intVal(clipH);
+        XftDrawSetClipRectangles( XFT_DRAW( __INST( sharedDrawId ) ) , 0, 0, &clipRX, 1);
     } else {
-	XftDrawSetClip( XFT_DRAW( __INST( drawId ) ) , 0);
+        XftDrawSetClip( XFT_DRAW( __INST( sharedDrawId ) ) , 0);
     }
 
     if (opaque == true) {
-	if (bgPixel != nil) {
-	    color.pixel = (unsigned long)__intVal(bgPixel);
-	} 
-	// else {
-	    color.color.red = __intVal(bgR);
-	    color.color.green = __intVal(bgG);
-	    color.color.blue = __intVal(bgB);
-	    color.color.alpha = __intVal(bgA);
-	// }
-	switch (__bytesPerCharacter) {
-	case 1:
-	    XftTextExtents8( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar8*)string, len, &extents);
-	    break;
-	case 2:
-	    XftTextExtents16( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar16*)string, len, &extents);
-	    break;
-	case 4:
-	    XftTextExtents32( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar32*)string, len, &extents);
-	    break;
-	}
-	XftDrawRect( XFT_DRAW ( __INST( drawId ) ), &color, __intVal(drawX) - extents.x, __intVal(drawY) - XFT_FONT( __INST( fontId ) )->ascent, extents.width, XFT_FONT(__INST (fontId ) )->height);
+        if (bgPixel != nil) {
+            color.pixel = (unsigned long)__intVal(bgPixel);
+        }
+        // else {
+            color.color.red = __intVal(bgR);
+            color.color.green = __intVal(bgG);
+            color.color.blue = __intVal(bgB);
+            color.color.alpha = __intVal(bgA);
+        // }
+        switch (__bytesPerCharacter) {
+        case 1:
+            XftTextExtents8( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar8*)string, len, &extents);
+            break;
+        case 2:
+            XftTextExtents16( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar16*)string, len, &extents);
+            break;
+        case 4:
+            XftTextExtents32( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar32*)string, len, &extents);
+            break;
+        }
+if (extents.width < 0) printf("width: %d  < 0\n", extents.width);
+        XftDrawRect( XFT_DRAW ( __INST( sharedDrawId ) ), &color, __intVal(drawX) - extents.x, __intVal(drawY) - XFT_FONT( __INST( fontId ) )->ascent, extents.width, XFT_FONT(__INST (fontId ) )->height);
     }
     if (fgPixel != nil) {
-	color.pixel = (unsigned long)__intVal(fgPixel);
+        color.pixel = (unsigned long)__intVal(fgPixel);
     }
     // else {
-	color.color.red = __intVal(fgR);
-	color.color.green = __intVal(fgG);
-	color.color.blue = __intVal(fgB);
-	color.color.alpha = __intVal(fgA);
+        color.color.red = __intVal(fgR);
+        color.color.green = __intVal(fgG);
+        color.color.blue = __intVal(fgB);
+        color.color.alpha = __intVal(fgA);
     // }
     switch (__bytesPerCharacter) {
     case 1:
-	XftDrawString8( XFT_DRAW ( __INST( drawId ) ), &color, XFT_FONT( __INST( fontId ) ),
-			__intVal(drawX),
-			__intVal(drawY),
-			(FcChar8*)string,
-			len);
-	RETURN ( self );
-	break;
+        XftDrawString8( XFT_DRAW ( __INST( sharedDrawId ) ), &color, XFT_FONT( __INST( fontId ) ),
+                        __intVal(drawX),
+                        __intVal(drawY),
+                        (FcChar8*)string,
+                        len);
+        RETURN ( self );
+        break;
     case 2:
-	XftDrawString16( XFT_DRAW ( __INST( drawId ) ), &color, XFT_FONT( __INST( fontId ) ),
-			__intVal(drawX),
-			__intVal(drawY),
-			(FcChar16*)string,
-			len);
-	RETURN ( self );
-	break;
+        XftDrawString16( XFT_DRAW ( __INST( sharedDrawId ) ), &color, XFT_FONT( __INST( fontId ) ),
+                        __intVal(drawX),
+                        __intVal(drawY),
+                        (FcChar16*)string,
+                        len);
+        RETURN ( self );
+        break;
     case 4:
-	XftDrawString32( XFT_DRAW ( __INST( drawId ) ), &color, XFT_FONT( __INST( fontId ) ),
-			__intVal(drawX),
-			__intVal(drawY),
-			(FcChar32*)string,
-			len);
-	RETURN ( self );
-	break;
+        XftDrawString32( XFT_DRAW ( __INST( sharedDrawId ) ), &color, XFT_FONT( __INST( fontId ) ),
+                        __intVal(drawX),
+                        __intVal(drawY),
+                        (FcChar32*)string,
+                        len);
+        RETURN ( self );
+        break;
     }
+#endif
     err:;
-#endif
 %}.
     self primitiveFailed: error.
 
@@ -543,12 +763,30 @@
 	^ self
     ].
 
-    (closestFont notNil and:[closestFont getDevice == aGraphicsDevice]) ifTrue:[
+    (closestFont notNil and:[closestFont graphicsDevice == aGraphicsDevice]) ifTrue:[
 	^ closestFont onDevice: aGraphicsDevice.
     ].
 
+    RecentlyUsedFonts isNil ifTrue:[
+	RecentlyUsedFonts := OrderedCollection new:10.
+    ].
+
+    RecentlyUsedFonts keysAndValuesDo:[:index :aFont |
+	((aFont class == self class) and:[self sameDeviceFontAs:aFont]) ifTrue:[
+	    "/ Transcript showCR:'hit'.
+	    RecentlyUsedFonts removeIndex:index.
+	    RecentlyUsedFonts addFirst:aFont.
+	    ^ aFont
+	]
+    ].
+
+    RecentlyUsedFonts size > 20 ifTrue:[
+	RecentlyUsedFonts removeLast.
+    ].
+
     aGraphicsDevice deviceFonts do:[:aFont |
-	(self sameDeviceFontAs:aFont) ifTrue:[
+	((aFont class == self class) and:[self sameDeviceFontAs:aFont]) ifTrue:[
+	    RecentlyUsedFonts addFirst:aFont.
 	    ^ aFont
 	].
     ].
@@ -561,15 +799,16 @@
 	] ifFalse:[
 	    self xftPatternAdd: myPatternId attribute: FC_SIZE value: size.
 	].
-	self xftPatternAdd: myPatternId attribute: FC_WEIGHT value: (StXFace2FCWeightMap at: face).
-	self xftPatternAdd: myPatternId attribute: FC_SLANT value: (StXStyle2FCSlantMap at: style).
+	self xftPatternAdd: myPatternId attribute: FC_WEIGHT value: (StXFace2FCWeightMap at: (face ? 'regular')).
+	self xftPatternAdd: myPatternId attribute: FC_SLANT value: (StXStyle2FCSlantMap at: (style ? 'roman') ifAbsent:[StXStyle2FCSlantMap at: (style ? 'roman') asLowercase]).
 
 	newFontId := self xftFontOpenPattern: aGraphicsDevice displayId pattern: myPatternId.
 	newFontId notNil ifTrue:[
-	    "/ Good, this font exist!!
+	    "/ Good, this font exists!!
 	    fontId := newFontId.
 	    device := aGraphicsDevice.
 	    aGraphicsDevice registerFont:self.
+	    RecentlyUsedFonts addFirst:self.
 	    ^ self.
 	] ifFalse:[
 	    closestPatternId1 := self xftFontMatch: aGraphicsDevice displayId screen: aGraphicsDevice screen pattern: myPatternId.
@@ -585,28 +824,30 @@
 	    "/ !!!!!!!! closestPatternId is no longer valid !!!!!!!!
 	    closestPatternId1 :=  nil.
 	    newFontId isNil ifTrue:[
-		self error: 'Pattern matched, but font could be open (should not happen)'.
+		self error: 'Pattern matched, but font could not be opened (should not happen)'.
 	    ].
+
 	    "/ Search for existing registered font. Note, that XftFont instances
 	    "/ are shared (and refcounted) so newFontId = aFont getFontId is enough
-	    "/ to check whether some other font instance  represents the same font...
+	    "/ to check whether some other font instance represents the same font...
 	    aGraphicsDevice deviceFonts do:[:aFont |
-		((self class == aFont class) and:[ newFontId = aFont getFontId ]) ifTrue:[
+		((self class == aFont class) and:[newFontId = aFont getFontId]) ifTrue:[
 		    closestFont := aFont.
 		    ^ closestFont
 		].
 	    ].
 
-	    closestFont := self class new
+	    closestFont := self shallowCopy
 				setDevice: aGraphicsDevice patternId: closestPatternId2 fontId: newFontId;
 				yourself.
 	    aGraphicsDevice registerFont: closestFont.
+	    RecentlyUsedFonts addFirst:closestFont.
 	    ^ closestFont
 	].
     ] ensure:[
-	self xftPatternDestroy: myPatternId.
-	self xftPatternDestroy: closestPatternId1.
-	self xftPatternDestroy: closestPatternId2.
+	myPatternId notNil ifTrue:[self xftPatternDestroy: myPatternId].
+	closestPatternId1 notNil ifTrue:[self xftPatternDestroy: closestPatternId1].
+	closestPatternId2 notNil ifTrue:[self xftPatternDestroy: closestPatternId2].
     ].
 
     "
@@ -622,8 +863,7 @@
      myself on aWorkstation. This does NOT try to look for existing
      or replacement fonts (i.e. can be used to get physical fonts)."
 
-    "/ Apparently, this is not needed.
-    self shouldImplement
+    ^ self onDevice:aWorkstation
 
     "Modified: / 02-01-2014 / 23:15:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified (comment): / 04-01-2014 / 02:06:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
@@ -634,15 +874,19 @@
 setDevice: deviceArg patternId: patternIdArg fontId: fontIdArg
     device := deviceArg.
     fontId := fontIdArg.
+    patternIdArg notNil ifTrue:[
+        family  := self xftPatternGet: patternIdArg attribute: FC_FAMILY index: 0.
+        size    := self xftPatternGet: patternIdArg attribute: FC_SIZE index: 0.
+        face    := self xftPatternGet: patternIdArg attribute: FC_WEIGHT index: 0.
+        face    := StXFace2FCWeightMap keyAtValue: face.
+        style   := self xftPatternGet: patternIdArg attribute: FC_SLANT index: 0.
+        style   := StXStyle2FCSlantMap keyAtValue: style.
 
-    family  := self xftPatternGet: patternIdArg attribute: FC_FAMILY index: 0.
-    size    := self xftPatternGet: patternIdArg attribute: FC_SIZE index: 0.
-    face    := self xftPatternGet: patternIdArg attribute: FC_WEIGHT index: 0.
-    face    := StXFace2FCWeightMap keyAtValue: face.
-    style   := self xftPatternGet: patternIdArg attribute: FC_SLANT index: 0.
-    style   := StXStyle2FCSlantMap keyAtValue: style.
+        name:= self xftPatternGet: patternIdArg attribute: 'fullname' index: 0.
 
-    encoding:= self xftPatternGet: patternIdArg attribute: 'encoding' index: 0.
+        encoding:= self xftPatternGet: patternIdArg attribute: 'encoding' index: 0.
+        encoding notNil ifTrue:[encoding := encoding asSymbol].
+    ].
 
     "Created: / 21-12-2013 / 00:46:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified: / 30-12-2013 / 12:49:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
@@ -724,6 +968,14 @@
     g := aColor scaledGreen.
     b := aColor scaledBlue.
     a := aColor alpha * 65535.
+    r isNil ifTrue:[
+	"/ when drawing into a pixmap...
+	aColor colorId == 0 ifTrue:[
+	    r := g := b := 0.
+	] ifFalse:[
+	    r := g := b := 16rFFFF.
+	]
+    ].
     pix := aColor colorId.
 %{
 #ifdef XFT
@@ -814,6 +1066,14 @@
     g := aColor scaledGreen.
     b := aColor scaledBlue.
     a := aColor alpha * 65535.
+    r isNil ifTrue:[
+	"/ when drawing into a pixmap...
+	aColor colorId == 0 ifTrue:[
+	    r := g := b := 0.
+	] ifFalse:[
+	    r := g := b := 16rFFFF.
+	]
+    ].
     pix := aColor colorId.
 %{
 #ifdef XFT
@@ -1339,6 +1599,24 @@
     "Created: / 21-12-2013 / 01:20:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
+getFontMetrics
+    |info|
+
+    info := DeviceWorkstation::DeviceFontMetrics new.
+    info
+      ascent:self ascent
+      descent:self descent
+      maxAscent:self maxAscent
+      maxDescent:self maxDescent
+      minWidth:self maxWidth
+      maxWidth:self maxWidth
+      avgWidth:self maxWidth
+      minCode:self minCode
+      maxCode:self maxCode
+      direction:#LeftToRight.
+    ^ info
+!
+
 height
     "return the height - the number of pixels above plus below the baseLine."
 
@@ -1386,10 +1664,26 @@
 widthOf:aString from:start to:stop
     "return the width of a sub string"
 
-    | extents |
+    |extents maxWidthOfSingleGlyph|
 
     (stop < start) ifTrue:[^ 0].
-    extents := self xftTextExtents: device displayId font: fontId string: aString from: start to: stop.
+    maxWidthOfSingleGlyph := self maxWidth.
+    "xOff from XFTTextExtents is a signed short.
+     Work arond for long strings"
+    (stop - start + 1) * maxWidthOfSingleGlyph > 32767 ifTrue:[
+        |total chunkSize|
+
+        chunkSize := (32767 // maxWidthOfSingleGlyph) - 1.
+        total := 0.
+        start to:stop by:chunkSize do:[:eachChunkStart|
+            extents := self xftTextExtents:device displayId font:fontId string:aString 
+                            from:eachChunkStart to:((eachChunkStart+chunkSize-1) min:stop).
+            "/ extents --> #(width height x y xOff yOff)
+            total := total + extents fifth.
+        ].
+        ^ total.
+    ].    
+    extents := self xftTextExtents: device displayId font:fontId string:aString from:start to:stop.
     "/ extents --> #(width height x y xOff yOff)
     ^ extents fifth.
 
@@ -1400,7 +1694,6 @@
 !XftFontDescription methodsFor:'release'!
 
 releaseDrawIfAssociatedWith: view
-
     | drawableId |
 
     view isNil ifTrue:[ ^ self ].
@@ -1408,30 +1701,360 @@
     drawableId isNil ifTrue: [ ^ self ].
 %{
 #ifdef XFT
-    XftDraw *draw;
-    if ( __INST(drawId) != nil ) {
-	if ( XftDrawDrawable ( XFT_DRAW ( __INST(drawId) ) ) == DRAWABLE( drawableId ) ) {
-	    XftDrawDestroy( XFT_DRAW( __INST(drawId) ) );
-	    __INST(drawId) = nil;
+    if ( __INST(sharedDrawId) != nil ) {
+	if (XftDrawDrawable(XFT_DRAW(__INST(sharedDrawId))) == DRAWABLE(drawableId)) {
+	    __INST(sharedDrawId) = nil;
+	    XftDrawDestroy(DRAWABLE(drawableId));
 	}
     }
-    RETURN ( self );
+    RETURN (self);
 #endif
 %}.
     self primitiveFailed
 
     "Created: / 12-01-2014 / 19:48:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
     "Modified: / 12-01-2014 / 22:09:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+releaseFromDevice
+    "I am no longer available on the device"
+
+    device := nil.
+    fontId := nil.
+    sharedDrawId := nil.
+    closestFont := nil
+! !
+
+!XftFontDescription methodsFor:'testing'!
+
+isUsed
+    ^ sharedDrawId notNil
+!
+
+isXftFont
+    ^ true
+! !
+
+!XftFontDescription::FCFontListParser class methodsFor:'documentation'!
+
+documentation
+"
+    parses fc-list output to get a list of XftFontDescriptions
+
+    [author:]
+	cg
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+
+"
+! !
+
+!XftFontDescription::FCFontListParser methodsFor:'api'!
+
+listOfAvailableFonts
+    |readEntry list l fcListProg|
+
+    list := OrderedCollection new.
+
+    readEntry :=
+	[
+	    |key|
+
+	    [l startsWith:'Pattern has'] whileFalse:[
+	      l := pipeStream nextLine. Transcript showCR:l.
+	    ].
+
+	    currentDescription := XftFontDescription new.
+	    [ l := pipeStream nextLine. l notEmptyOrNil ] whileTrue:[
+		"/ Transcript showCR:l.
+		lineStream := l readStream. lineStream skipSeparators.
+		key := lineStream upToSeparator.
+		(
+		    #('family:' 'style:' 'slant:' 'weight:' 'width:'
+		      'pixelsize:' 'spacing:' 'foundry:' 'antialias:'
+		      'file:' 'outline' 'scalable:' 'charset:' 'lang:'
+		      'fontversion:' 'fontformat:' 'decorative:' 'index:'
+		      'outline:' 'familylang:' 'stylelang:' 'fullname:'
+		      'fullnamelang:' 'capability:' 'hash:' 'postscriptname:'
+		    ) includes:key
+		) ifTrue:[
+		    self perform:('fc_',(key allButLast)) asSymbol
+		] ifFalse:[
+		    Transcript show:'Xft ignored line: '; showCR:l.
+		    self breakPoint:#cg.
+		].
+	    ].
+	    list add:currentDescription
+	].
+
+    fcListProg := #('/usr/bin/fc-list' '/usr/X11/bin/fc-list') detect:[:eachProg|
+			eachProg asFilename isExecutableProgram
+		    ] ifNone:[
+			'fc-list program not found - no XFT fonts' infoPrintCR.
+			^ list.
+		    ].
+
+    pipeStream := PipeStream readingFrom:fcListProg, ' -v'.
+    [
+	[pipeStream atEnd] whileFalse:[
+	    l := pipeStream nextLine.
+	    readEntry value.
+	]
+    ] ensure:[
+	pipeStream close
+    ].
+    ^ list
+
+    "
+     FCFontListParser new listOfAvailableFonts
+    "
+! !
+
+!XftFontDescription::FCFontListParser methodsFor:'font list keywords'!
+
+fc_antialias
+    "helper for font listing"
+
+    currentDescription isAntialiasedFont:(self getBoolean).
+!
+
+fc_capability
+    "helper for font listing"
+
+    "currentDescription capability:" (self getString).
+!
+
+fc_charset
+    "helper for font listing"
+
+    |page bits l min max minCode maxCode|
+
+    [ l := pipeStream nextLine. l notEmpty ] whileTrue:[
+	"/ Transcript show:'->'; showCR:l.
+	(l startsWith:Character tab) ifFalse:[
+	    (l startsWith:'(') ifFalse:[self halt].
+	    currentDescription minCode:minCode.
+	    currentDescription maxCode:maxCode.
+	    ^ self.
+	].
+
+	lineStream := l readStream.
+	lineStream skipSeparators.
+	page := Integer readFrom:(lineStream upTo:$:) radix:16.
+	lineStream next.
+	bits := 0 to:7 collect:[:i|
+	    lineStream skipSeparators.
+	    Integer readFrom:(lineStream upToSeparator) radix:16.
+	].
+	min := (page * 256 + 0).
+	max := (page * 256 + 255).
+	minCode isNil ifTrue:[
+	    minCode := min.
+	    maxCode := max.
+	] ifFalse:[
+	    minCode := minCode min:min.
+	    maxCode := maxCode max:max.
+	].
+    ].
+    "/ currentDescription characterSet:(self getString).
+    currentDescription minCode:minCode.
+    currentDescription maxCode:maxCode.
+!
+
+fc_decorative
+    "helper for font listing"
+
+    currentDescription isDecorativeFont:(self getBoolean).
+!
+
+fc_family
+    "helper for font listing"
+
+    currentDescription family:(self getString).
+!
+
+fc_familylang
+    "helper for font listing"
+
+    "currentDescription familylang:" (self getString).
+!
+
+fc_file
+    "helper for font listing"
+
+    currentDescription file:(self getString).
+!
+
+fc_fontformat
+    "helper for font listing"
+
+    currentDescription fontFormat:(self getString).
+!
+
+fc_fontversion
+    "helper for font listing"
+
+    currentDescription fontVersion:(self getInteger).
+!
+
+fc_foundry
+    "helper for font listing"
+
+    currentDescription foundry:(self getString).
+!
+
+fc_fullname
+    "helper for font listing"
+
+    "currentDescription fullname:" (self getString).
+!
+
+fc_fullnamelang
+    "helper for font listing"
+
+    "currentDescription fullnamelang:" (self getString).
+!
+
+fc_hash
+    "helper for font listing"
+
+    "currentDescription hash:" self getString.
+!
+
+fc_index
+    "helper for font listing"
+
+    "currentDescription index:" (self getInteger).
+!
+
+fc_lang
+    "helper for font listing"
+
+    "/ currentDescription characterSet:(self getString).
+!
+
+fc_outline
+    "helper for font listing"
+
+    currentDescription isOutlineFont:(self getBoolean).
+!
+
+fc_pixelsize
+    "helper for font listing"
+
+    currentDescription setPixelSize:(self getInteger).
+    currentDescription setSizeUnit:#px.
+    "/ currentDescription setSize:(self getInteger).
+    "/ currentDescription setSizeUnit:#pt.
+!
+
+fc_postscriptname
+    "helper for font listing"
+
+    "currentDescription postscriptname:" self getString.
+!
+
+fc_scalable
+    "helper for font listing"
+
+    currentDescription isScalableFont:(self getBoolean).
+!
+
+fc_slant
+    "helper for font listing"
+
+    currentDescription slant:(self getInteger).
+!
+
+fc_spacing
+    "helper for font listing"
+
+    currentDescription spacing:(self getInteger).
+!
+
+fc_style
+    "helper for font listing"
+
+    |xftStyle|
+
+    xftStyle := self getString.
+"/    ((xftStyle includesString:'Bold') or:[xftStyle includesString:'Fett']) ifTrue:[
+"/        currentDescription face:'bold'.
+"/        currentDescription style:'roman'.
+"/        ^ self.
+"/    ].
+    ((xftStyle includesString:'Italic') or:[xftStyle includesString:'Oblique']) ifTrue:[
+"/        currentDescription face:'medium'.
+	currentDescription style:'italic'.
+	^ self.
+    ].
+"/    (xftStyle includesString:'Regular') ifTrue:[
+"/        currentDescription face:'regular'.
+"/        currentDescription style:'roman'.
+"/        ^ self.
+"/    ].
+"/ self halt.
+"/    currentDescription face:'medium'.
+    currentDescription style:'roman'.
+!
+
+fc_stylelang
+    "helper for font listing"
+
+    "currentDescription stylelang:" (self getString).
+!
+
+fc_weight
+    "helper for font listing"
+
+    currentDescription weight:(self getInteger).
+!
+
+fc_width
+    "helper for font listing"
+
+    currentDescription width:(self getInteger).
+! !
+
+!XftFontDescription::FCFontListParser methodsFor:'helpers'!
+
+getBoolean
+    "helper for font listing"
+
+    |s|
+
+    lineStream skipSeparators.
+    s := lineStream nextAlphaNumericWord.
+    ^ s = 'FcTrue'.
+!
+
+getInteger
+    "helper for font listing"
+
+    lineStream skipSeparators.
+    ^ Integer readFrom:lineStream.
+!
+
+getString
+    "helper for font listing"
+
+    lineStream skipSeparators.
+    lineStream peekFor:$".
+    ^ (lineStream upTo:$").
 ! !
 
 !XftFontDescription class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.25 2014-02-04 10:22:47 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.51.2.1 2014-05-08 08:27:51 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.25 2014-02-04 10:22:47 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.51.2.1 2014-05-08 08:27:51 stefan Exp $'
 ! !