diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,21 @@
 # Release history for fudgets
 
+## 0.18.4 --  2023-06-27
+
+* ``Cla`` (Lennart Augustsson's calculator) is now included.
+
+* Added support for binary I/O with lazy bytestrings to files and network
+  sockets.
+
+* Removed the last remnants of the ``PackedString`` type.
+
+* Tested with 14 different versions of GHC, from 7.4.1 to 9.6.2.
+
+* Fudgets turned 30 this month, can you believe it?
+  [The first paper on Fudgets](https://www.altocumulus.org/Fudgets/fpca93-abstract.html)
+  was presented at the *Conference on Functional Programming Languages and
+  Computer Architecture*, Copenhagen, June 1993.
+  
 ## 0.18.3.2 --  2022-08-04
 
 * Simplified the installation on macOS by adding a helper script
diff --git a/Demos/SpaceInvaders/GUI.hs b/Demos/SpaceInvaders/GUI.hs
--- a/Demos/SpaceInvaders/GUI.hs
+++ b/Demos/SpaceInvaders/GUI.hs
@@ -9,7 +9,7 @@
            bmScale,spaceSize,spaceWidth,spaceHeight
            ) where
 import Control.Applicative
-import AllFudgets hiding (draw,wDraw,size,state,rect,put)
+import AllFudgets hiding (draw,wDraw,state,rect,put)
 import ReactiveF
 import ReadPic
 import InvaderTypes
diff --git a/Examples/Cla.hs b/Examples/Cla.hs
new file mode 100644
--- /dev/null
+++ b/Examples/Cla.hs
@@ -0,0 +1,51 @@
+module Main(main) where
+import Fudgets
+
+font = if null args
+       then "-adobe-times-bold-r-normal--34-*-*-*-*-*-*-*"
+       else head args
+
+--font = "-adobe-times-bold-r-normal--34-*-*-*-*-*-*-*"
+
+myUntaggedListLF layout fs = snd >^=< listLF layout (number 0 (concat fs))
+
+startstate = ([0::Integer], 10, False)
+
+digit d = ["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"!!(fromInteger d)]
+bconv b x = if x < b then digit x else bconv b (x`div`b) ++ digit (x`mod`b)
+showstate (x:xs, b, _) = (if x < 0 then '-':bconv b (0-x) else bconv b x)++"    "++show b
+bop f ([x], b, c) = bop f ([x,x], b, True)
+bop f (x:y:xs, b, c) = (f y x:xs, b, True)
+uop f (x:xs, b, c) = (f x:xs, b, True)
+dig n (x:xs, b, c) = ((if c then n:x:xs else if n < b then x*b+n:xs else x:xs), b, False)
+
+accumulator =
+  let transform state op = let state' = op state
+			   in (state',state')
+  in putSP startstate $ mapAccumlSP transform startstate
+
+disp = displayF' (setAlign aRight.setFont font)  >=^< showstate
+
+buttons =
+  let b = buttonF
+  in let bf s f = (\x->f) >^=< b s
+  in let bq s = quitF>==<b s
+
+  in let buttons = [
+	   [bq "Off", bf "Enter" (\(x:xs, b, c)->(x : x : xs, b, True)), bf "Clear" (\(_:xs, b, c)->(0:xs, b, False)), bf "BS" (\(x:xs, b, c)->((if c then x else x`div`b):xs, b, c))],
+	   [bf "D" (dig 13),bf "E" (dig 14),bf "F" (dig 15),bf "mod" (bop (mod))],
+	   [bf "A" (dig 10),bf "B" (dig 11),bf "C" (dig 12),bf "/" (bop (div))],
+	   [bf "7" (dig 7), bf "8" (dig 8), bf "9" (dig 9), bf "*" (bop (*))],
+	   [bf "4" (dig 4), bf "5" (dig 5), bf "6" (dig 6), bf "-" (bop (-))],
+	   [bf "1" (dig 1), bf "2" (dig 2), bf "3" (dig 3), bf "+" (bop (+))],
+	   [bf "0" (dig 0), bf "Chs" (uop (0-)), bf "Base" (\(x:xs, b, c)->(x:xs, (if x <= 36 && x > 1 then x else b), True)), bf "Pop" (\(x:xs, b, c)->(if null xs then ([x],b,c) else (xs,b,c))) ]]
+
+  in let layout = matrixP 4
+  in myUntaggedListLF layout buttons
+
+counterF = (disp >=^^< accumulator, Above) >#==< buttons
+
+main = fudlogue $ shellF "Calculator" counterF
+
+--[] ++ ys = ys
+--(x:xs) ++ ys = x:(xs++ys)
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@
 - [Fudgets User's Guide](https://www.altocumulus.org/Fudgets/userguide.html).
   Naming conventions and some other practical things.
 - [Fudget Library Reference Manual](https://www.altocumulus.org/Fudgets/Manual/). (Haddock did not exist back when Fudgets were created.)
+- [Programming with Fudgets](https://www.altocumulus.org/Fudgets/springschool95-intro.html): Lecture Notes from the Spring School on Advanced Functional Programming in Båstad 1995. A comprehensive introduction.
 - [The FPCA-93 paper about Fudgets](https://www.altocumulus.org/Fudgets/fpca93-abstract.html),
   the first publication describing Fudgets.
 - See the [Fudgets home page](https://www.altocumulus.org/Fudgets/) for more info.
diff --git a/fudgets.cabal b/fudgets.cabal
--- a/fudgets.cabal
+++ b/fudgets.cabal
@@ -1,6 +1,6 @@
 Name: fudgets
 -- The version number also appears in hsrc/utils/FudVersion.hs
-Version: 0.18.3.2
+Version: 0.18.4
 Cabal-Version: >=1.10
 Synopsis: The Fudgets Library
 Homepage: https://www.altocumulus.org/Fudgets/
@@ -24,7 +24,7 @@
 Build-Type: Simple
 License: OtherLicense
 License-File: COPYRIGHT
-Tested-With: GHC==7.4.1, GHC==7.6.3, GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.3, GHC==8.8.2, GHC==8.10.2, GHC==8.10.7, GHC==9.0.2, GHC==9.2.4
+Tested-With: GHC==7.4.1, GHC==7.6.3, GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.4, GHC==8.10.2, GHC==8.10.7, GHC==9.0.2, GHC==9.2.7, GHC==9.4.4, GHC==9.6.2
 
 Extra-Source-Files: README.md
                     ChangeLog.md
@@ -47,6 +47,11 @@
   Manual:      True
   Default:     False
 
+Flag bytestring
+  Description: Use bytestring for binary IO with ReadBinFile and WriteBinFile
+  Manual:      True
+  Default:     True
+
 Flag old-time
   Description: Use the old-time package
   Default:     True
@@ -66,6 +71,9 @@
                  containers, array, time,
                  unix
 
+  if flag(bytestring)
+    Build-Depends: bytestring
+
   if flag(old-time)
     Build-Depends: old-time
 
@@ -88,6 +96,8 @@
 
   Include-dirs: hsrc hsrc/ghc-dialogue hsrc/defaults
 
+  if os(freebsd)
+    ghc-options: -pgmP hsrc/fudcpp
   if os(darwin)
     Extra-lib-dirs: /opt/X11/lib 
     Include-dirs: /opt/X11/include
@@ -296,7 +306,7 @@
     OpenSocket
     PQueue
     P_IO_data
-    PackedString
+  --PackedString
     ParF
     ParK
     ParSP
@@ -440,6 +450,16 @@
 Executable texteditor
   hs-source-dirs: Examples
   main-is: texteditor.hs
+  Default-language: Haskell98
+  build-depends: base, fudgets
+
+  ghc-options: -fno-warn-tabs
+  if impl(ghc>=7.0)
+    ghc-options: -rtsopts
+
+Executable Cla
+  hs-source-dirs: Examples
+  main-is: Cla.hs
   Default-language: Haskell98
   build-depends: base, fudgets
 
diff --git a/hsrc/combinators/ListF.hs b/hsrc/combinators/ListF.hs
--- a/hsrc/combinators/ListF.hs
+++ b/hsrc/combinators/ListF.hs
@@ -3,12 +3,12 @@
 import CompSP(prepostMapSP)
 import CompSP(preMapSP)
 import CompOps((>^=<),(>=^^<))
-import Direction
+--import Direction
 import Fudget
 --import ListMap(lookupWithDefault)
 --import Message(Message(..))
 --import NullF
---import Path(Path(..))
+import Path(turn,Direction(..))
 import Spops
 import TreeF
 import Utils(number,pair)
@@ -60,7 +60,7 @@
 
 pathtab (Leaf (t, _)) = [(t, [])]
 pathtab (Branch l r) =
-    map (apSnd (L :)) (pathtab l) ++ map (apSnd (R :)) (pathtab r)
+    map (apSnd (turn L)) (pathtab l) ++ map (apSnd (turn R)) (pathtab r)
 
 balancedTree xs =
     case xs of
diff --git a/hsrc/combinators/Route.hs b/hsrc/combinators/Route.hs
--- a/hsrc/combinators/Route.hs
+++ b/hsrc/combinators/Route.hs
@@ -1,12 +1,11 @@
 module Route(compTurnRight, compTurnLeft, compPath) where
-import Direction
 import Message(Message(..))
-import Path({-Path(..),-}path, turn)
+import Path(turn,Direction(..))
 
-compPath (tag, ev) wrongaddr c =
-    case path tag of
-      (L, tag') -> c $ Left (Low (tag', ev))
-      (R, tag') -> c $ Right (Low (tag', ev))
+compPath (path, ev) wrongaddr c =
+    case path of
+      L:tag' -> c $ Left (Low (tag', ev))
+      R:tag' -> c $ Right (Low (tag', ev))
       _ -> wrongaddr
 
 compTurnLeft  (tag, cmd) = Low (turn L tag, cmd)
diff --git a/hsrc/drawing/FlexibleDrawing.hs b/hsrc/drawing/FlexibleDrawing.hs
--- a/hsrc/drawing/FlexibleDrawing.hs
+++ b/hsrc/drawing/FlexibleDrawing.hs
@@ -106,12 +106,12 @@
     h2 = (by-ty) `div` 2
     d = (h2 `div` 2) `min` (rx-lx)
 
-triangleUp = flex' size (drawpoly . trianglePoints')
-filledTriangleUp = flex' size (fillpoly . trianglePoints')
-triangleDown = flex' size (drawpoly . vMirror trianglePoints')
-filledTriangleDown = flex' size (fillpoly . vMirror trianglePoints')
+triangleUp = flex' defaultTriangleSize (drawpoly . trianglePoints')
+filledTriangleUp = flex' defaultTriangleSize (fillpoly . trianglePoints')
+triangleDown = flex' defaultTriangleSize (drawpoly . vMirror trianglePoints')
+filledTriangleDown= flex' defaultTriangleSize (fillpoly.vMirror trianglePoints')
 
-size = Point 18 14
+defaultTriangleSize = Point 18 14
 
 drawpoly ps = [DrawLines CoordModeOrigin ps]
 fillpoly ps = [FillPolygon Convex CoordModeOrigin ps]
diff --git a/hsrc/drawing/Font.hs b/hsrc/drawing/Font.hs
--- a/hsrc/drawing/Font.hs
+++ b/hsrc/drawing/Font.hs
@@ -18,7 +18,7 @@
 default(Int)
 
 data CharStruct = CharStruct {char_lbearing, char_rbearing,
-                              char_width, char_ascent, char_descent :: Int}
+                              char_width, char_ascent, char_descent :: !Int}
 		  deriving (Eq, Ord, Show, Read)
 
 data FontDirection = FontLeftToRight | FontRightToLeft 
@@ -31,13 +31,13 @@
 data FontStructF per_char =
     FontStruct {font_id :: FontId,
                 font_dir :: FontDirection,
-                first_char, last_char :: Char,
-                font_complete :: Bool, -- all chars exist
-                default_char :: Char,
+                first_char, last_char :: !Char,
+                font_complete :: !Bool, -- all chars exist
+                default_char :: !Char,
                 font_prop :: [FontProp],
-                max_bounds, min_bounds :: CharStruct,
+                max_bounds, min_bounds :: !CharStruct,
                 per_char :: Maybe per_char,
-                font_ascent, font_descent :: Int
+                font_ascent, font_descent :: !Int
                   -- ^ logical extent above/below baseline for spacing
                }
     deriving (Eq, Ord, Show, Read)
@@ -60,19 +60,23 @@
 
 linespace fs = font_ascent fs + font_descent fs
 
-char_struct default' fs c =
-    case per_char fs of
-      Nothing -> default' fs
-      Just ca -> --ca ! c
-                 ca ! (if inRange (font_range fs) c   -- or: bounds ca
-                       then -- debugging
-		            if inRange (bounds ca) c
-			    then c
-			    else ctrace "fontrange" (font_range fs,bounds ca,c) (default_char fs)
-		       else let c' = default_char fs
-		            in if inRange (bounds ca) c'
-			       then c'
-			       else ctrace "fontrange" (font_range fs,"default char",c') ' ')
+char_struct default' fs =
+  case per_char fs of
+    Nothing -> const (default' fs)
+    Just ca -> char_struct'
+      where
+        r = font_range fs
+        b = bounds ca
+        char_struct' c =
+          ca ! (if inRange r c   -- or: bounds ca
+                then -- debugging
+                     if inRange b c
+                     then c
+                     else ctrace "fontrange" (r,b,c) (default_char fs)
+                else let c' = default_char fs
+                     in if inRange b c'
+                        then c'
+                        else ctrace "fontrange" (r,"default char",c') ' ')
 
 lbearing fs = char_lbearing . char_struct min_bounds fs
 rbearing fs = char_rbearing . char_struct max_bounds fs
diff --git a/hsrc/drawing/Graphic.hs b/hsrc/drawing/Graphic.hs
--- a/hsrc/drawing/Graphic.hs
+++ b/hsrc/drawing/Graphic.hs
@@ -1,11 +1,11 @@
 module Graphic(module Graphic,MeasuredGraphics,emptyMG,emptyMG',GCtx,Cont(..)) where
-import Fudget
+--import Fudget
 import FudgetIO
 import EitherUtils(Cont(..))
 import Cont(conts)
-import MeasuredGraphics(MeasuredGraphics(..),measureString,measurePackedString,emptyMG,emptyMG')
+import MeasuredGraphics(MeasuredGraphics(..),measureString,emptyMG,emptyMG') --,measurePackedString
 import GCtx(GCtx)
-import PackedString(PackedString)
+--import PackedString(PackedString)
 import Geometry() -- instance Num Point
 
 class Graphic a where
@@ -40,7 +40,7 @@
 instance Graphic Bool         where measureGraphicK = measureText
 instance Graphic Float        where measureGraphicK = measureText
 instance Graphic Double       where measureGraphicK = measureText
-instance Graphic PackedString where measureGraphicK = measurePackedString
+--instance Graphic PackedString where measureGraphicK = measurePackedString
 
 instance (Graphic a,Graphic b) => Graphic (Either a b) where
   measureGraphicK = either measureGraphicK measureGraphicK
diff --git a/hsrc/fudcpp b/hsrc/fudcpp
--- a/hsrc/fudcpp
+++ b/hsrc/fudcpp
@@ -1,4 +1,4 @@
-#! /bin/bash
+#! /usr/bin/env bash
 
 # This script is used on macOS to workaround two problems:
 #
@@ -12,6 +12,7 @@
 
 cpp=cpp
 case `uname` in
+    FreeBSD) cpp=cpp12 ;;
     Darwin)
 	# Since gcc is an alias for clang on macOS, gcc proper is only
 	# available in the path with a version suffix, so we need to
diff --git a/hsrc/ghc-dialogue/AsyncInput.hs b/hsrc/ghc-dialogue/AsyncInput.hs
--- a/hsrc/ghc-dialogue/AsyncInput.hs
+++ b/hsrc/ghc-dialogue/AsyncInput.hs
@@ -32,7 +32,7 @@
 import Data.IORef(newIORef,readIORef,writeIORef,IORef)
 import System.Posix.DynamicLinker as DL
 
-import PackedString(unpackPS,lengthPS{-,packCBytesST,psToByteArray-})
+--import PackedString(unpackPS,lengthPS{-,packCBytesST,psToByteArray-})
 
 default (Int)
 
@@ -105,6 +105,14 @@
 			 do got <- tryP "read" (>=0) $ cread fd buf (fromIntegral bufsize)
 			    str <- unmarshallString' (CString buf) (fromIntegral got)
 			    return (d,SocketRead str)
+#ifdef VERSION_bytestring
+		       BinSocketDe _ ->
+		         let bufsize = 2000
+			 in alloca bufsize $ \ buf ->
+			 do got <- tryP "read" (>=0) $ cread fd buf (fromIntegral bufsize)
+			    bs <- unmarshallByteString' (CString buf) (fromIntegral got)
+			    return (d,SocketReadBin bs)
+#endif
 		       LSocketDe _ ->
 		         allocaInt $ \ addrlen ->
 			 do addr <- newsockAddr
@@ -211,8 +219,8 @@
       SocketResponse . LSocket . LSo <$> getfilep s "r+"
    WriteSocket s str -> writeSocket s str
    WriteSocketPS s str ->
-      do writeSocket s (unpackPS str) -- grr!
-         returnS (Wrote (lengthPS str)) -- grr!
+      do writeSocket s str -- grr!
+         returnS (Wrote (length str)) -- grr!
 {-
      do
       fd <- fileno s
@@ -331,6 +339,7 @@
  where descriptor d = case d of
 	   LSocketDe (LSo s) -> withd $ get_fileno s
 	   SocketDe (So s) ->  withd $ get_fileno s
+	   BinSocketDe (So s) ->  withd $ get_fileno s
 	   OutputSocketDe (So s) ->  withd $ get_fileno s
 	   DisplayDe ({-Display-} d) -> withd $ 
 --	         _casm_ ``%r=((Display*)%0)->fd;'' d
diff --git a/hsrc/ghc-dialogue/DialogueIO.hs b/hsrc/ghc-dialogue/DialogueIO.hs
--- a/hsrc/ghc-dialogue/DialogueIO.hs
+++ b/hsrc/ghc-dialogue/DialogueIO.hs
@@ -1,4 +1,5 @@
--- | Haskell 1.2 Dialogue I/O
+-- | Haskell 1.2 Dialogue I/O,
+-- extended for Fudgets with Xlib calls, network sockets, etc
 module DialogueIO(Request(..), Response(..), IOError(..)
        , Dialogue(..), SigAct(..) , dialogueToIO
        --, module _LibDialogue
@@ -11,7 +12,8 @@
 -- | Included just to illustrate that it is possible to convert a Dialogue
 -- IO function to a monadic IO function. The implementation relies on
 -- 'getChanContents' to construct the lazy list of responses needed by
--- the dialogue IO function.
+-- the dialogue IO function. (See also the functions 'doRequest' and
+-- 'Fudgets.fudlogue'.)
 dialogueToIO :: Dialogue -> IO ()
 dialogueToIO f =
   do st <- initXCall
diff --git a/hsrc/ghc-dialogue/DoRequest.hs b/hsrc/ghc-dialogue/DoRequest.hs
--- a/hsrc/ghc-dialogue/DoRequest.hs
+++ b/hsrc/ghc-dialogue/DoRequest.hs
@@ -11,6 +11,9 @@
 import qualified IOUtil as IO
 import System.IO(openBinaryFile,withBinaryFile,IOMode(..),hPutStr,hGetContents)
 import System.Directory
+#ifdef VERSION_bytestring
+import qualified Data.ByteString.Lazy as BS
+#endif
 #ifdef VERSION_old_time
 import System.Time(getClockTime,toCalendarTime)
 #endif
@@ -49,6 +52,13 @@
     ReadBinaryFile filename      -> rdCatch (readBinaryFile filename)
     WriteBinaryFile filename contents ->
                                     wrCatch (writeBinaryFile filename contents)
+#ifdef VERSION_bytestring
+    ReadBinFile filename         -> rdCatch' Bn (BS.readFile filename)
+    WriteBinFile filename contents ->
+                                    wrCatch (BS.writeFile filename contents)
+    AppendBinFile filename contents ->
+                                    wrCatch (BS.appendFile filename contents)
+#endif
     AppendFile filename contents -> wrCatch (appendFile filename contents)
     StatusFile filename          -> catchIo SearchError (statusFile filename)
       where
diff --git a/hsrc/ghc-dialogue/DoXCommand.hs b/hsrc/ghc-dialogue/DoXCommand.hs
--- a/hsrc/ghc-dialogue/DoXCommand.hs
+++ b/hsrc/ghc-dialogue/DoXCommand.hs
@@ -23,7 +23,7 @@
 
 import System.IO(hPutStr,hPutStrLn,stderr) -- for error reporting
 
-import PackedString(lengthPS,unpackPS)
+--import PackedString(lengthPS,unpackPS)
 --import Word(Word32)
 import Data.Bits
 
@@ -188,10 +188,10 @@
             where f = fromIntegral
 	  DrawPoint (Point x y) -> xDrawPoint d drw gc x y
 	  CreatePutImage rect format pixels -> createPutImage drw gc rect format pixels
-	  DrawImageStringPS (Point x y) s ->
-	    xDrawImageString d drw gc x y (unpackPS s) (lengthPS s) -- !!
-	  DrawStringPS (Point x y) s ->
-	    xDrawString d drw gc x y (unpackPS s) (lengthPS s) -- !!
+--	  DrawImageStringPS (Point x y) s ->
+--	    xDrawImageString d drw gc x y (unpackPS s) (lengthPS s) -- !!
+--	  DrawStringPS (Point x y) s ->
+--	    xDrawString d drw gc x y (unpackPS s) (lengthPS s) -- !!
           _ -> hPutStr stderr (notImplemented cmd)
 
        createPutImage drw gc rect@(Rect (Point x y) (Point w h)) (ImageFormat format) pixels =
diff --git a/hsrc/ghc-dialogue/DoXRequest.hs b/hsrc/ghc-dialogue/DoXRequest.hs
--- a/hsrc/ghc-dialogue/DoXRequest.hs
+++ b/hsrc/ghc-dialogue/DoXRequest.hs
@@ -218,14 +218,14 @@
    QueryTextExtents16 fid s ->
      do let n = length s
 	cs <- marshallString16' s n
-        ints@[dir,ascent,descent,overall] <- newLongs 4
+        ints@[dir,ascent,descent] <- newInt32s 3
         overall <- newPtr
 	xQueryTextExtents16 display fid cs n dir ascent descent overall
-        [asc,desc] <- mapM readLong [ascent,descent]
+        [asc,desc] <- mapM readInt32 [ascent,descent]
         ov <- mkCharStruct overall
         freePtrs ints
 	freePtr overall
-        return $ TextExtents16Queried asc desc ov
+        return $ TextExtents16Queried (fromIntegral asc) (fromIntegral desc) ov
    ListFontsWithInfo pattern maxnames ->
      GotFontListWithInfo <$> listFontsWithInfo d pattern maxnames
    DbeQueryExtension ->
diff --git a/hsrc/ghc-dialogue/Marshall.hs b/hsrc/ghc-dialogue/Marshall.hs
--- a/hsrc/ghc-dialogue/Marshall.hs
+++ b/hsrc/ghc-dialogue/Marshall.hs
@@ -1,6 +1,11 @@
+{-# LANGUAGE CPP #-}
 module Marshall where
 import MyForeign
 import Control.Monad(zipWithM_)
+#ifdef VERSION_bytestring
+import qualified Foreign as F
+import qualified Data.ByteString as BS
+#endif
 --import Ap
 
 class HasAddr a where
@@ -151,7 +156,11 @@
       if i<n
       then (:) <$> peekElemOff addr i <*> get (i+1)
       else return []
-     
+
+#ifdef VERSION_bytestring
+unmarshallByteString' (CString (Addr addr)) n =
+    BS.packCStringLen (F.castPtr addr,n)
+#endif
 
 ---
 
diff --git a/hsrc/ghc-dialogue/P_IO_data.hs b/hsrc/ghc-dialogue/P_IO_data.hs
--- a/hsrc/ghc-dialogue/P_IO_data.hs
+++ b/hsrc/ghc-dialogue/P_IO_data.hs
@@ -5,6 +5,9 @@
 import ShowFun()
 import Prelude hiding (IOError)
 import System.Directory(XdgDirectory)
+#ifdef VERSION_bytestring
+import qualified Data.ByteString.Lazy as BS
+#endif
 #ifdef VERSION_old_time
 import System.Time(ClockTime,CalendarTime)
 #endif
@@ -160,7 +163,11 @@
 		deriving (Show,Read)
 
 
+#ifdef VERSION_bytestring
+type Bin = BS.ByteString
+#else
 type Bin = Unused
+#endif
 type Dialogue = [Response] -> [Request] -- not useful anymore
 --type _CUnion = Unused
 type File = Unused
diff --git a/hsrc/ghc-dialogue/Xlib.hs b/hsrc/ghc-dialogue/Xlib.hs
--- a/hsrc/ghc-dialogue/Xlib.hs
+++ b/hsrc/ghc-dialogue/Xlib.hs
@@ -93,7 +93,7 @@
 Xlib(FreeFontNames,CStringArray->IO())
 PReq(ListFontsWithInfo,CString->Int->CInt32->CCXFontStruct,CStringArray,String->Int->CInt32->CCXFontStruct,CStringArray)
 Xlib(FreeFontInfo,CStringArray->CXFontStructArray->Int32->IO ())
-Cmd(QueryTextExtents16,FontId->CString16->Int->CLong->CLong->CLong->CXCharStruct)
+Cmd(QueryTextExtents16,FontId->CString16->Int->CInt32->CInt32->CInt32->CXCharStruct)
 
 Req(CreateFontCursor,Int,CursorId)
 Req(CreatePixmap,DrawableId->Unsigned->Unsigned->Unsigned,PixmapId)
diff --git a/hsrc/ghc/PackedString.hs b/hsrc/ghc/PackedString.hs
deleted file mode 100644
--- a/hsrc/ghc/PackedString.hs
+++ /dev/null
@@ -1,22 +0,0 @@
--- | Fake PackedString type
-module PackedString{-(module PS)-} where
---import Data.PackedString as PS
-
-newtype PackedString = PS String deriving (Eq,Ord)
-
-instance Show PackedString where
-  showsPrec n (PS s) r = s++r
-
-instance Read PackedString where
-  readsPrec n s0 = [(PS s,r)|(s,r)<-readsPrec n s0]
-
-packString = PS
-unpackPS (PS s) = s
-
-nullPS (PS s) = null s
-lengthPS (PS s) = length s
-
-appendPS (PS s1) (PS s2) = PS (s1++s2)
-mapPS f (PS s) = PS (map f s)
-nilPS = PS ""
-reversePS (PS s) = PS (reverse s)
diff --git a/hsrc/internals/MeasuredGraphics.hs b/hsrc/internals/MeasuredGraphics.hs
--- a/hsrc/internals/MeasuredGraphics.hs
+++ b/hsrc/internals/MeasuredGraphics.hs
@@ -1,4 +1,4 @@
-module MeasuredGraphics(DPath,up,MeasuredGraphics(..),compileMG,emptyMG,emptyMG',measureString,measureImageString,measurePackedString) where
+module MeasuredGraphics(DPath,up,MeasuredGraphics(..),compileMG,emptyMG,emptyMG',measureString,measureImageString{-,measurePackedString-}) where
 import Geometry
 import LayoutRequest
 --import Placers2(overlayP)
@@ -10,8 +10,8 @@
 import Rects(boundingRect)
 import CompiledGraphics
 import GCtx(GCtx(..))
-import GCAttrs(FontData(..))
-import PackedString(unpackPS)
+import GCAttrs(FontData(..),fontdata2struct)
+--import PackedString(unpackPS)
 import Utils(lunconcat)
 --import CmdLineEnv(argFlag)
 import Debug.Trace(trace)
@@ -98,10 +98,8 @@
 measureString' draw8 draw16 s gctx@(GC _ fd) k =
     measureString'' id draw s gctx k
   where
-    draw =
-      case fd of
-        FS fs | snd (font_range fs) <= '\xff' -> draw8
-	_ -> draw16
+    fs = fontdata2struct fd id
+    draw = if snd (font_range fs) <= '\xff' then draw8 else draw16
 
 measureString s = measureString' DrawString DrawString16 s
 measureImageString s = measureString' DrawImageString DrawImageString16 s
@@ -113,7 +111,7 @@
   else measureString' id DrawString
 -}
 
-measurePackedString ps = measureString'' unpackPS DrawStringPS ps
+--measurePackedString ps = measureString'' unpackPS DrawStringPS ps
 
 
 -- map2' is a lazier version of map2 (aka zipWith)
diff --git a/hsrc/internals/Table.hs b/hsrc/internals/Table.hs
--- a/hsrc/internals/Table.hs
+++ b/hsrc/internals/Table.hs
@@ -1,18 +1,19 @@
 module Table(table, mapTable, listTable, tableUpdate, tableLookup, emptyTable,
              Table) where
 import Tree234
+import HbcUtils(apSnd)
 
-newtype Table a = T (Tree234 a) deriving (Eq, Ord,Show)
+newtype Table k v = T (Tree234 (k,v)) deriving (Eq, Ord,Show)
 
 emptyTable = T initTree234
 
-tableLookup n j x (T t) = treeSearch n j (keyCmp x) t
+tableLookup n j x (T t) = treeSearch n j (keyCmp (x,())) t
 
 tableUpdate x (T t) = T (update' x t)
 
 update' x = treeAdd const keyCmp x
 
-mapTable f (T t) = T (treeMap f t)
+mapTable f (T t) = T (fmap (apSnd f) t)
 
 listTable (T t) = treeList t
 
diff --git a/hsrc/internals/Tables.hs b/hsrc/internals/Tables.hs
--- a/hsrc/internals/Tables.hs
+++ b/hsrc/internals/Tables.hs
@@ -1,7 +1,7 @@
 module Tables(PathTable(..), WidTable(..), updatePath, lookupPath, wid2path0,
               pruneWid, updateWid, subWids, lookupWid, path2wid0, PathTree,
 	      moveWids,movePaths, prunePath) where
-import Direction
+--import Direction
 --import Fudget
 import Path
 import Table
@@ -76,24 +76,25 @@
 nowid = noWindow
 
 -------
-type PathTable = Table (WindowId, Path)
+type PathTable = Table WindowId Path
 
 nopath = here -- error "window not associated with a path"
 
 wid2path0 = emptyTable
 
 -- This part should be replaced with something more efficient!!
-lookupPath wid2path wid =
-    tableLookup nopath snd (wid, nopath) wid2path
+lookupPath wid2path wid = tableLookup nopath snd wid wid2path
 
 -- normal code
 updatePath wid2path wid path' = tableUpdate (wid, path') wid2path
 
-movePaths wid2path opath npath = mapTable move wid2path where
-  move (wid,path) = (wid,repath opath path) where
-     repath [] rest = absPath npath rest
-     repath (x:xs) (y:ys) | x == y = repath xs ys
-     repath _ _ = path
+movePaths wid2path opath npath = mapTable move wid2path
+  where
+    move path = repath opath path
+      where
+        repath [] rest = absPath npath rest
+        repath (x:xs) (y:ys) | x == y = repath xs ys
+        repath _ _ = path
 
 -- should be implemented in Tree234
 prunePath wid2path w = table $ filter ((/=w).fst) $ listTable wid2path
diff --git a/hsrc/internals/Tables2.hs b/hsrc/internals/Tables2.hs
--- a/hsrc/internals/Tables2.hs
+++ b/hsrc/internals/Tables2.hs
@@ -1,11 +1,11 @@
 module Tables2(DTable(..), dtable0, lookupDe, listDe, updateDe) where
 import Utils(pair)
-import Direction() -- instances
-import Path(here,Path(..))
+--import Direction() -- instances, for hbc
+import Path(Path(..))
 import Sockets(Descriptor)
 import Table
 
-type DTable = Table (Descriptor, Path)
+type DTable = Table Descriptor Path
 
 updateDe :: Path -> [Descriptor] -> DTable -> DTable
 updateDe path' ds dtable =
@@ -17,7 +17,7 @@
 
 lookupDe :: DTable -> Descriptor -> Path
 lookupDe dtable de =
-    tableLookup (error ("Descriptor without path: "++show de)) snd (de, here) dtable
+    tableLookup (error ("Descriptor without path: "++show de)) snd de dtable
 
 dtable0 :: DTable
 dtable0 = table []
diff --git a/hsrc/internals/Tree234.hs b/hsrc/internals/Tree234.hs
--- a/hsrc/internals/Tree234.hs
+++ b/hsrc/internals/Tree234.hs
@@ -1,5 +1,6 @@
-module Tree234(treeMap, treeCombine, treeRebuild, treeFromList, treeMapList,
-               treeList, treeUpdate, treeSearch, treeAdd, initTree234, Tree234) where
+{-# LANGUAGE DeriveFunctor #-}
+module Tree234(treeFromList, --treeMap,
+               treeList, treeSearch, treeAdd, initTree234, Tree234) where
 
 data Tree234 a = Leaf |
                  Leaf2 a |
@@ -8,7 +9,7 @@
                  Node2 a (Tree234 a) (Tree234 a) |
                  Node3 a a (Tree234 a) (Tree234 a) (Tree234 a) |
                  Node4 a a a (Tree234 a) (Tree234 a) (Tree234 a) (Tree234 a) 
-                 deriving (Eq, Ord,Show)
+                 deriving (Eq, Ord,Show, Functor)
 
 initTree234 = Leaf
 
@@ -41,7 +42,7 @@
          (treeSearch fail cont p t3)
          (cont a3)
          (treeSearch fail cont p t4))
-
+{-
 treeUpdateFailed = error "treeUpdate couldn't find the node"
 
 treeUpdate update p Leaf = Leaf
@@ -81,7 +82,7 @@
          (Node4 a1 a2 a3 t1 t2 (treeUpdate update p t3) t4)
          (Node4 a1 a2 (update a3) t1 t2 t3 t4)
          (Node4 a1 a2 a3 t1 t2 t3 (treeUpdate update p t4)))
-
+-}
 treeMapList f Leaf = []
 treeMapList f (Leaf2 a1) = f a1
 treeMapList f (Leaf3 a1 a2) = f a1 ++ f a2
@@ -96,7 +97,7 @@
     f a1 ++
     treeMapList f t2 ++
     f a2 ++ treeMapList f t3 ++ f a3 ++ treeMapList f t4
-
+{-
 treeMap f Leaf = Leaf
 treeMap f (Leaf2 a1) = Leaf2 (f a1)
 treeMap f (Leaf3 a1 a2) = Leaf3 (f a1) (f a2)
@@ -113,18 +114,18 @@
           (treeMap f t2)
           (treeMap f t3)
           (treeMap f t4)
-
+-}
 treeFromList comb cmp l = treeAddList comb cmp l Leaf
 
 treeAddList comb cmp [] t = t
 treeAddList comb cmp (x : xs) t =
     treeAddList comb cmp xs (treeAdd comb cmp x t)
-
+{-
 treeRebuild comb cmp t = treeFromList comb cmp (treeMapList (: []) t)
 
 treeCombine comb cmp t1 t2 =
     treeAddList comb cmp (treeMapList (: []) t2) t1
-
+-}
 treeAdd' comb cmp a keep split Leaf = keep (Leaf2 a)
 treeAdd' comb cmp a keep split (Leaf2 a1) =
     keep (cmp a a1 (Leaf3 a a1) (Leaf2 (comb a a1)) (Leaf3 a1 a))
diff --git a/hsrc/io/AsyncTransmitter.hs b/hsrc/io/AsyncTransmitter.hs
--- a/hsrc/io/AsyncTransmitter.hs
+++ b/hsrc/io/AsyncTransmitter.hs
@@ -1,4 +1,3 @@
-{-# LANGUAGE CPP #-}
 module AsyncTransmitter(asyncTransmitterF,asyncTransmitterF',closerF) where
 import Sockets
 import Srequest
@@ -10,7 +9,7 @@
 import CompOps((>==<))
 import IoF(ioF)
 import DialogueIO hiding (IOError)
-import qualified PackedString as PS
+--import qualified PackedString as PS
 import Queue(QUEUE,empty,enter,qremove)
 
 {- asyncTransmitterF has two states:
@@ -84,7 +83,7 @@
 getMsg l h = getK $ message l h
 
 data Buffer = Buf String (QUEUE String)
-data GetBuf = More PS.PackedString Buffer | Empty | EoS
+data GetBuf = More String Buffer | Empty | EoS
 
 --buf0 = Buf "" empty
 buf1 str = Buf str empty -- pre: str/=""
@@ -105,13 +104,7 @@
 
     getbuf'' s q =
       case splitAt n s of
-        (s1,s2) -> More (PS.packString s1) (Buf s2 q)
+        (s1,s2) -> More s1 (Buf s2 q)
 
 
 initblocksize = 512 :: Int
-
-#if defined(__GLASGOW_HASKELL__) || defined(__PFE__)
-nullPS = PS.nullPS
-#else
-nullPS = PS.null
-#endif
diff --git a/hsrc/types/Direction.hs b/hsrc/types/Direction.hs
--- a/hsrc/types/Direction.hs
+++ b/hsrc/types/Direction.hs
@@ -1,3 +1,3 @@
-module Direction(Direction(..)) where
+module Direction where
 
 data Direction = L | R | Dno Int  deriving (Eq, Ord, Read, Show)
diff --git a/hsrc/types/Drawcmd.hs b/hsrc/types/Drawcmd.hs
--- a/hsrc/types/Drawcmd.hs
+++ b/hsrc/types/Drawcmd.hs
@@ -21,8 +21,8 @@
       CopyPlane d r p n -> CopyPlane d r (move v p) n
       DrawPoint p -> DrawPoint (move v p)
       CreatePutImage r fmt pxls -> CreatePutImage (move v r) fmt pxls
-      DrawImageStringPS p s -> DrawImageStringPS (move v p) s
-      DrawStringPS p s -> DrawStringPS (move v p) s
+--    DrawImageStringPS p s -> DrawImageStringPS (move v p) s
+--    DrawStringPS p s -> DrawStringPS (move v p) s
       DrawImageString16 p s -> DrawImageString16 (move v p) s
       DrawString16 p s -> DrawString16 (move v p) s
 
diff --git a/hsrc/types/Fudget.hs b/hsrc/types/Fudget.hs
--- a/hsrc/types/Fudget.hs
+++ b/hsrc/types/Fudget.hs
@@ -7,8 +7,7 @@
 --import Event(XEvent)
 import FRequest(FRequest,FResponse)
 import Message(Message(..))
-import Direction(Direction)
-import Path(Path(..))
+import Path(Path(..),Direction)
 import SP(SP)
 
 type TEvent   = (Path, FResponse)
diff --git a/hsrc/types/Path.hs b/hsrc/types/Path.hs
--- a/hsrc/types/Path.hs
+++ b/hsrc/types/Path.hs
@@ -1,4 +1,5 @@
-module Path(showPath, subPath, absPath, path, turn, here, Path(..)) where
+module Path(showPath, subPath, absPath, path, turn, here,
+            Path(..), Direction(..)) where
 import Direction
 import Utils(lhead)
 
diff --git a/hsrc/utils/FudVersion.hs b/hsrc/utils/FudVersion.hs
--- a/hsrc/utils/FudVersion.hs
+++ b/hsrc/utils/FudVersion.hs
@@ -1,7 +1,8 @@
 module FudVersion where
 
-version = version_0_18_3_2
+version = version_0_18_4
 
-version_0_18_3_2 = "version 0.18.3.2" -- only for documentation, use "version" instead
+version_0_18_4 = "version 0.18.4"
+-- ^ only for documentation, use 'version' instead
 
 -- The version number should be increased immediately after a public release.
diff --git a/hsrc/xtypes/Command.hs b/hsrc/xtypes/Command.hs
--- a/hsrc/xtypes/Command.hs
+++ b/hsrc/xtypes/Command.hs
@@ -1,6 +1,6 @@
 module Command(module Command,DrawCommand,Drawable(..)) where
 import Event(XEvent)
-import Direction() -- for hbc
+--import Direction() -- for hbc
 import Path(Path(..))
 import Geometry
 --import LayoutRequest(LayoutMessage(..))
diff --git a/hsrc/xtypes/DrawInPixmap.hs b/hsrc/xtypes/DrawInPixmap.hs
--- a/hsrc/xtypes/DrawInPixmap.hs
+++ b/hsrc/xtypes/DrawInPixmap.hs
@@ -9,8 +9,8 @@
 pmDrawString pm gc p s = draw (Pixmap pm) gc (DrawString p s)
 pmDrawImageString16 pm gc p s = draw (Pixmap pm) gc (DrawImageString16 p s)
 pmDrawString16 pm gc p s = draw (Pixmap pm) gc (DrawString16 p s)
-pmDrawImageStringPS pm gc p s = draw (Pixmap pm) gc (DrawImageStringPS p s)
-pmDrawStringPS pm gc p s = draw (Pixmap pm) gc (DrawStringPS p s)
+--pmDrawImageStringPS pm gc p s = draw (Pixmap pm) gc (DrawImageStringPS p s)
+--pmDrawStringPS pm gc p s = draw (Pixmap pm) gc (DrawStringPS p s)
 pmDrawRectangle pm gc r = draw (Pixmap pm) gc (DrawRectangle r)
 pmFillRectangle pm gc r = draw (Pixmap pm) gc (FillRectangle r)
 pmFillPolygon pm gc shape mode ps =
diff --git a/hsrc/xtypes/DrawInWindow.hs b/hsrc/xtypes/DrawInWindow.hs
--- a/hsrc/xtypes/DrawInWindow.hs
+++ b/hsrc/xtypes/DrawInWindow.hs
@@ -9,8 +9,8 @@
 wDrawString gc p s = draw MyWindow gc (DrawString p s)
 wDrawImageString16 gc p s = draw MyWindow gc (DrawImageString16 p s)
 wDrawString16 gc p s = draw MyWindow gc (DrawString16 p s)
-wDrawImageStringPS gc p s = draw MyWindow gc (DrawImageStringPS p s)
-wDrawStringPS gc p s = draw MyWindow gc (DrawStringPS p s)
+--wDrawImageStringPS gc p s = draw MyWindow gc (DrawImageStringPS p s)
+--wDrawStringPS gc p s = draw MyWindow gc (DrawStringPS p s)
 wDrawRectangle gc r = draw MyWindow gc (DrawRectangle r)
 wFillRectangle gc r = draw MyWindow gc (FillRectangle r)
 wFillPolygon gc shape mode ps = draw MyWindow gc (FillPolygon shape mode ps)
diff --git a/hsrc/xtypes/DrawTypes.hs b/hsrc/xtypes/DrawTypes.hs
--- a/hsrc/xtypes/DrawTypes.hs
+++ b/hsrc/xtypes/DrawTypes.hs
@@ -1,6 +1,6 @@
 module DrawTypes where
 import Geometry(Point,Rect,Line)
-import PackedString(PackedString)
+--import PackedString(PackedString)
 import Xtypes(Pixel,PixmapId,ImageFormat,DbeBackBufferId)
 
 data DrawCommand
@@ -18,8 +18,8 @@
   | DrawPoint Point
   | CreatePutImage Rect ImageFormat [Pixel]
   --
-  | DrawImageStringPS Point PackedString
-  | DrawStringPS Point PackedString
+---  | DrawImageStringPS Point PackedString
+---  | DrawStringPS Point PackedString
   --
   | DrawLines CoordMode [Point]
   | DrawImageString16 Point String
diff --git a/hsrc/xtypes/Sockets.hs b/hsrc/xtypes/Sockets.hs
--- a/hsrc/xtypes/Sockets.hs
+++ b/hsrc/xtypes/Sockets.hs
@@ -1,9 +1,13 @@
+{-# LANGUAGE CPP #-}
 module Sockets(DLValue,module Sockets) where
 import Event(XEvent)
 import Xtypes(WindowId,Display)
-import PackedString(PackedString)
+--import PackedString(PackedString)
 import DLValue
 import System.Posix.DynamicLinker(DL)
+#ifdef VERSION_bytestring
+import Data.ByteString(ByteString)
+#endif
 
 -- NOTE: Matching definitions for the C world appear in xlib/sockets.h --------
 
@@ -23,7 +27,7 @@
                    | DLSym DLHandle String           -- -> SR DLValue
 		   | OpenFileAsSocket String String  -- -> SR Socket
 		                   -- name,  mode  (as in fopen(name,mode))
-		   | WriteSocketPS Socket PackedString -- -> SR Wrote
+		   | WriteSocketPS Socket String     -- -> SR Wrote
                    | GetStdoutSocket                 -- -> SR Socket
                       deriving (Show,Read)
 
@@ -50,6 +54,7 @@
 data Descriptor
   = LSocketDe LSocket
   | SocketDe Socket
+  | BinSocketDe Socket
   | OutputSocketDe Socket
   | TimerDe Timer
   | DisplayDe Display 
@@ -58,6 +63,9 @@
 data AEvent
   = SocketAccepted Socket Peer
   | SocketRead String
+#ifdef VERSION_bytestring
+  | SocketReadBin ByteString
+#endif
   | SocketWritable
   | TimerAlarm
   | XEvent (WindowId, XEvent) 
