diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,26 @@
 ghci:	ghci-tmp
 
 ghci-tmp:
-	ghci -Wall -i:src:dist/build/autogen:execute/tmp src/Graphics/Gnuplot/Simple.hs
+	ghci -Wall -i:src:dist/build/autogen:os/generic:execute/tmp src/Graphics/Gnuplot/Simple.hs
 
 ghci-pipe:
-	ghci -Wall -i:src:dist/build/autogen:execute/pipe src/Graphics/Gnuplot/Simple.hs
+	ghci -Wall -i:src:dist/build/autogen:os/generic:execute/pipe src/Graphics/Gnuplot/Simple.hs
 
 ghci-shell:
-	ghci -Wall -i:src:dist/build/autogen:execute/shell src/Graphics/Gnuplot/Simple.hs
+	ghci -Wall -i:src:dist/build/autogen:os/generic:execute/shell src/Graphics/Gnuplot/Simple.hs
 
 ghci-demo:
-	ghci -Wall -i:src:dist/build/autogen:execute/tmp src/Demo.hs
+	ghci -Wall -i:src:dist/build/autogen:os/generic:execute/tmp src/Demo.hs
+
+testbuild:
+	runhaskell Setup configure --user -f buildExamples
+	runhaskell Setup build
+	runhaskell Setup haddock
+
+	runhaskell Setup clean
+	runhaskell Setup configure --user -f executePipe
+	runhaskell Setup build
+
+	runhaskell Setup clean
+	runhaskell Setup configure --user -f executeShell
+	runhaskell Setup build
diff --git a/execute/pipe/Graphics/Gnuplot/Execute.hs b/execute/pipe/Graphics/Gnuplot/Execute.hs
--- a/execute/pipe/Graphics/Gnuplot/Execute.hs
+++ b/execute/pipe/Graphics/Gnuplot/Execute.hs
@@ -1,5 +1,7 @@
 module Graphics.Gnuplot.Execute where
 
+import Graphics.Gnuplot.Private.OS (gnuplotName, )
+
 import System.Exit (ExitCode, )
 import System.IO (hPutStr, )
 import qualified System.Process as Proc
@@ -12,6 +14,6 @@
 simple program options =
    do -- putStrLn cmd
       (inp,_out,_err,pid) <-
-         Proc.runInteractiveProcess "gnuplot" options Nothing Nothing
+         Proc.runInteractiveProcess gnuplotName options Nothing Nothing
       hPutStr inp (unlines program)
       Proc.waitForProcess pid
diff --git a/execute/shell/Graphics/Gnuplot/Execute.hs b/execute/shell/Graphics/Gnuplot/Execute.hs
--- a/execute/shell/Graphics/Gnuplot/Execute.hs
+++ b/execute/shell/Graphics/Gnuplot/Execute.hs
@@ -1,9 +1,10 @@
 module Graphics.Gnuplot.Execute where
 
+import Graphics.Gnuplot.Private.OS (gnuplotName, )
+import Graphics.Gnuplot.Utility (quote, semiColonConcat, )
+
 import System.Exit (ExitCode, )
 import System.Cmd (system, )
-import Graphics.Gnuplot.Utility
-   (quote, semiColonConcat, )
 
 
 simple ::
@@ -13,7 +14,7 @@
 simple program options =
    let cmd =
           "sh -c 'echo " ++ quote (semiColonConcat program) ++
-                 " | gnuplot " ++ unwords options ++ "'"
+                 " | " ++ gnuplotName ++ " " ++ unwords options ++ "'"
    in  do --putStrLn cmd
           system cmd
 
diff --git a/execute/tmp/Graphics/Gnuplot/Execute.hs b/execute/tmp/Graphics/Gnuplot/Execute.hs
--- a/execute/tmp/Graphics/Gnuplot/Execute.hs
+++ b/execute/tmp/Graphics/Gnuplot/Execute.hs
@@ -1,7 +1,11 @@
 module Graphics.Gnuplot.Execute where
 
+import Graphics.Gnuplot.Private.OS (gnuplotName, )
+
+import qualified System.IO as IO
+import System.IO.Temp (withSystemTempFile, )
 import System.Exit (ExitCode, )
-import System.Cmd (rawSystem, )
+import System.Process (readProcessWithExitCode, )
 
 
 tmpScript :: FilePath
@@ -12,6 +16,12 @@
    -> [String] {-^ Options for gnuplot -}
    -> IO ExitCode
 simple program options =
-   do writeFile tmpScript (unlines program)
-      -- putStrLn cmd
-      rawSystem "gnuplot" $ options ++ [tmpScript]
+   withSystemTempFile tmpScript $ \path handle -> do
+      IO.hPutStr handle (unlines program)
+      IO.hClose handle
+      -- putStrLn $ showCommandForUser gnuplotName (options ++ [path])
+      (exitCode, _out, _err) <-
+         readProcessWithExitCode gnuplotName (options ++ [path]) []
+      -- putStr out
+      -- putStr err
+      return exitCode
diff --git a/gnuplot.cabal b/gnuplot.cabal
--- a/gnuplot.cabal
+++ b/gnuplot.cabal
@@ -1,5 +1,5 @@
 Name:             gnuplot
-Version:          0.5.1
+Version:          0.5.2
 License:          BSD3
 License-File:     LICENSE
 Author:           Henning Thielemann <haskell@henning-thielemann.de>
@@ -33,8 +33,10 @@
    you can switch to more convenient
    but probably less portable ways
    of feeding gnuplot with a script.
+   .
+   Alternative packages: @plot@, @HPlot@, @Chart@, @textPlot@, @easyplot@
 Tested-With:       GHC==6.8.2, GHC==6.12.3
-Tested-With:       GHC==7.0.2, GHC==7.4.2, GHC==7.6.1
+Tested-With:       GHC==7.0.2, GHC==7.4.2, GHC==7.6.3
 Cabal-Version:     >=1.6
 Build-Type:        Simple
 Extra-Source-Files:
@@ -42,11 +44,13 @@
   execute/tmp/Graphics/Gnuplot/Execute.hs
   execute/pipe/Graphics/Gnuplot/Execute.hs
   execute/shell/Graphics/Gnuplot/Execute.hs
+  os/windows/Graphics/Gnuplot/Private/OS.hs
+  os/generic/Graphics/Gnuplot/Private/OS.hs
 Data-Files:
   data/runtime.data
 
 Source-Repository this
-  Tag:         0.5.1
+  Tag:         0.5.2
   Type:        darcs
   Location:    http://code.haskell.org/gnuplot/
 
@@ -75,10 +79,15 @@
 
 Library
   Build-Depends:
+    filepath >=1.1 && <1.4,
+    temporary >=1.1 && <1.2,
     array >=0.1 && <0.5,
     containers >=0.1 && <0.6,
-    utility-ht >=0.0.1 && <0.1,
-    monoid-transformer >=0.0.2 && <0.1
+    utility-ht >=0.0.8 && <0.1,
+    data-accessor-transformers >=0.2.1 && <0.3,
+    data-accessor >=0.2.2 && <0.3,
+    transformers >=0.3 && <0.4,
+    deepseq >=1.0 && <1.4
   If flag(splitBase)
     Build-Depends:
       process >=1.0 && <1.2,
@@ -99,13 +108,19 @@
       Hs-Source-Dirs: execute/shell
     Else
       Hs-Source-Dirs: execute/tmp
+  If os(windows)
+    Hs-Source-Dirs: os/windows
+  Else
+    Hs-Source-Dirs: os/generic
 
   Exposed-Modules:
     Graphics.Gnuplot.Simple
     Graphics.Gnuplot.Time
     Graphics.Gnuplot.Advanced
     Graphics.Gnuplot.Display
+    Graphics.Gnuplot.File
     Graphics.Gnuplot.Terminal
+    Graphics.Gnuplot.Terminal.Default
     Graphics.Gnuplot.Terminal.PostScript
     Graphics.Gnuplot.Terminal.PNG
     Graphics.Gnuplot.Terminal.SVG
@@ -116,6 +131,7 @@
     Graphics.Gnuplot.Frame.OptionSet
     Graphics.Gnuplot.Frame.OptionSet.Style
     Graphics.Gnuplot.Frame.OptionSet.Histogram
+    Graphics.Gnuplot.Plot
     Graphics.Gnuplot.Plot.TwoDimensional
     Graphics.Gnuplot.Plot.ThreeDimensional
     Graphics.Gnuplot.Graph
@@ -142,6 +158,9 @@
     Graphics.Gnuplot.Private.GraphEmpty
     Graphics.Gnuplot.Private.Terminal
     Graphics.Gnuplot.Private.Display
+    Graphics.Gnuplot.Private.File
+    Graphics.Gnuplot.Private.Command
+    Graphics.Gnuplot.Private.OS
     Graphics.Gnuplot.Utility
     Graphics.Gnuplot.Execute
 
@@ -151,5 +170,5 @@
   Else
     Buildable: False
   GHC-Options: -Wall
-  Hs-Source-Dirs: src, execute/tmp
+  Hs-Source-Dirs: src, execute/tmp, os/generic
   Main-Is: Demo.hs
diff --git a/os/generic/Graphics/Gnuplot/Private/OS.hs b/os/generic/Graphics/Gnuplot/Private/OS.hs
new file mode 100644
--- /dev/null
+++ b/os/generic/Graphics/Gnuplot/Private/OS.hs
@@ -0,0 +1,4 @@
+module Graphics.Gnuplot.Private.OS where
+
+gnuplotName :: String
+gnuplotName = "gnuplot"
diff --git a/os/windows/Graphics/Gnuplot/Private/OS.hs b/os/windows/Graphics/Gnuplot/Private/OS.hs
new file mode 100644
--- /dev/null
+++ b/os/windows/Graphics/Gnuplot/Private/OS.hs
@@ -0,0 +1,4 @@
+module Graphics.Gnuplot.Private.OS where
+
+gnuplotName :: String
+gnuplotName = "pgnuplot"
diff --git a/src/Demo.hs b/src/Demo.hs
--- a/src/Demo.hs
+++ b/src/Demo.hs
@@ -25,9 +25,10 @@
 import qualified Paths_gnuplot as Path
 import System.FilePath ((</>), )
 
+import Control.Monad (liftM2, )
 import Data.Array (listArray, )
 import Data.Foldable (foldMap, )
-import Data.Monoid (mappend, )
+import Data.Monoid (mappend, mconcat, )
 
 
 simple2d :: Plot2D.T Double Double
@@ -43,7 +44,7 @@
 
 list2d :: Plot2D.T Int Integer
 list2d =
-   Plot2D.list Graph2D.listPoints [0,1,1,2,3,5,8,13::Integer]
+   Plot2D.list Graph2D.listPoints [0,1,1,2,3,5,8,13]
 
 candle2d :: Plot2D.T Time.Day Double
 candle2d =
@@ -52,6 +53,13 @@
    flip map (linearScale 32 (0,2*pi)) $
    \t -> (-sin t, -2*sin t, 2*sin t, sin t)
 
+image2d :: Plot2D.T Double Double
+image2d =
+   case linearScale 300 (-20,20) of
+      xs ->
+         Plot2D.function Graph2D.image (liftM2 (,) xs xs) $
+            \(x,y) -> cos (sqrt (x*x+x*y+y*y))
+
 overlay2d :: Frame.T (Graph2D.T Double Double)
 overlay2d =
    Frame.cons (Opts.size 1 0.4 $ Opts.key False $ Opts.deflt) $
@@ -67,9 +75,9 @@
       Opts.boxwidthAbsolute 0.9 $
       OptsStyle.fillBorderLineType (-1) $
       OptsStyle.fillSolid $
+      Opts.keyOutside $
       Opts.xTicks2d
          [("220", 0), ("320", 1), ("420", 2), ("520", 3), ("620", 4), ("720", 5)] $
-      Opts.yRange2d (0,3000) $
       Opts.deflt) $
    foldMap (\(title,dat) ->
       fmap (Graph2D.lineSpec (LineSpec.title title LineSpec.deflt)) $
@@ -88,17 +96,30 @@
           Opts.xRange2d domain $
           Opts.yRange2d (-1.5,1.5) $
           Opts.deflt
-   in Frame.cons frameOpts $
-      foldMap (\(name,f) ->
-         fmap (Graph2D.lineSpec
-                  (LineSpec.title name $
-                   LineSpec.deflt)) $
-         Plot2D.function Graph2D.lines (linearScale 100 domain) f) $
-      ("sin", sin) :
-      ("cos", cos) :
-      ("tan", tan) :
-      []
+   in  Frame.cons frameOpts $
+       foldMap (\(name,f) ->
+          fmap (Graph2D.lineSpec
+                   (LineSpec.title name $
+                    LineSpec.deflt)) $
+          Plot2D.function Graph2D.lines (linearScale 100 domain) f) $
+       ("sin", sin) :
+       ("cos", cos) :
+       ("tan", tan) :
+       []
 
+filled2d ::
+   Frame.T (Graph2D.T Double Double)
+filled2d =
+   let scale = linearScale 100 (-10,10)
+       wave style (lower,upper) =
+          Plot2D.function style scale $
+          (\y -> (lower*y, upper*y)) . sin
+   in  Frame.cons (Opts.key False Opts.deflt) $ mconcat $
+       wave Graph2D.filledStripeAbove (1.0, 1.3) :
+       wave Graph2D.filledStripeBelow (1.0, 1.3) :
+       wave Graph2D.filledStripe      (0.7, 1.0) :
+       []
+
 file2d :: FilePath -> FilePath -> Frame.T (Graph2D.T Int Double)
 file2d path file =
    let lineSpec =
@@ -157,6 +178,14 @@
           meshNodes meshNodes
           (\x y -> cos(x*x+y*y))
 
+lissajous3d :: Frame.T (Graph3D.T Double Double Double)
+lissajous3d =
+   let t = linearScale 300 (-pi, pi)
+       f n = map (sin . (*) n) t
+   in  Frame.cons defltOpts $
+       Plot3D.cloud Graph3D.lines $
+       zip3 (f 3) (f 4) (f 9)
+
 multiplot :: MultiPlot.T
 multiplot =
    let (prefix,suffix) =
@@ -185,13 +214,16 @@
    GP.plotDefault simple2d :
    GP.plotDefault list2d :
    GP.plotDefault candle2d :
+   GP.plotDefault image2d :
    GP.plotDefault histogram2d :
    GP.plotDefault names2d :
+   GP.plotDefault filled2d :
    GP.plotDefault overlay2d :
    (GP.plotDefault . flip file2d "runtime.data"
       =<< fmap (</> "data") Path.getDataDir) :
    GP.plotDefault mixed2d :
    GP.plotDefault size2d :
    GP.plotDefault wave3d :
+   GP.plotDefault lissajous3d :
    GP.plotDefault multiplot :
    []
diff --git a/src/Graphics/Gnuplot/Advanced.hs b/src/Graphics/Gnuplot/Advanced.hs
--- a/src/Graphics/Gnuplot/Advanced.hs
+++ b/src/Graphics/Gnuplot/Advanced.hs
@@ -34,7 +34,7 @@
 of learning gnuplot script syntax,
 it happens frequently that people ask,
 how to express a certain gnuplot script using this package.
-Thus let's annotate the gnuplot script generated by @Demo.multiplot2d@
+Thus let's annotate the gnuplot script generated by @Demo.multiplot@
 in order to show, what belongs to where:
 
 > # the terminal selection is part of the 'plot' command of this module
@@ -72,18 +72,26 @@
 module Graphics.Gnuplot.Advanced (
     plot,
     plotDefault,
+    plotSync,
+    plotAsync,
+    fileContents,
   ) where
 
 import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
 import qualified Graphics.Gnuplot.Private.Display as Display
-
 import qualified Graphics.Gnuplot.Private.Terminal as Terminal
-import qualified Graphics.Gnuplot.Execute as Exec
+import qualified Graphics.Gnuplot.Terminal.Default as DefaultTerm
+import qualified Graphics.Gnuplot.File as File
+
+import qualified Graphics.Gnuplot.Private.Command as Cmd
+import Control.Concurrent (ThreadId, forkIO, )
 import System.Exit (ExitCode, )
 
-import qualified Data.Monoid.State as State
+import qualified Control.Monad.Trans.Reader as MR
+import qualified Control.Monad.Trans.State as MS
 import Data.Monoid (Monoid, mempty, )
-import Graphics.Gnuplot.Utility (semiColonConcat, )
+import Control.Functor.HT (void, )
+import Data.Tuple.HT (mapFst, )
 
 
 -- * User front-end
@@ -96,43 +104,79 @@
 For interactive sessions,
 better use "Graphics.Gnuplot.Simple".
 @gfx@ must be one of the types @Plot@, @Frame@, @MultiPlot@.
+
+This function runs gnuplot asynchronously
+for interactive terminals (X11, WX)
+and synchronously for file terminals (PostScript, PNG, etc.).
+This emulates the behaviour of @gnuplot --persist@.
+However, when running asynchronous
+we cannot obtain a real 'ExitCode'.
+Thus, in this case we will always return 'ExitSuccess'.
 -}
 plot ::
    (Terminal.C terminal, Display.C gfx) =>
    terminal -> gfx -> IO ExitCode
-plot term =
-   plotCore (formatTerminal term :)
+plot term gfx =
+   case Terminal.canonical term of
+      cterm ->
+         Cmd.asyncIfInteractive
+            (Terminal.interactive cterm)
+            (plotCore cterm gfx)
 
-{- |
-Plot using the default gnuplot terminal.
--}
-plotDefault ::
-   (Display.C gfx) =>
-   gfx -> IO ExitCode
-plotDefault =
-   plotCore id
+plotAsync ::
+   (Terminal.C terminal, Display.C gfx) =>
+   terminal -> gfx -> IO ThreadId
+plotAsync term gfx = forkIO $ void $ plotSync term gfx
 
+plotSync ::
+   (Terminal.C terminal, Display.C gfx) =>
+   terminal -> gfx -> IO ExitCode
+plotSync = plotCore . Terminal.canonical
+
 plotCore ::
    (Display.C gfx) =>
-   ([String] -> [String]) -> gfx -> IO ExitCode
+   Terminal.T -> gfx -> IO ExitCode
 plotCore term gfx =
+   Cmd.run $ render term gfx
+
+{- |
+Return the gnuplot script and the curve files
+corresponding to your plot data.
+The first parameter is the directory where the curve files are located.
+This directory is baked into the gnuplot script
+and the paths of the curve files.
+
+Don't make any assumptions about the structure of the files.
+Feeding the files to gnuplot, archiving them or study them
+are the intended uses of them.
+-}
+fileContents ::
+   (Terminal.C terminal, Display.C gfx) =>
+   FilePath -> terminal -> gfx -> (String, [File.T])
+fileContents dir term gfx =
+   mapFst unlines $ render (Terminal.canonical term) gfx dir
+
+render ::
+   Display.C gfx =>
+   Terminal.T -> gfx -> FilePath -> ([String], [File.T])
+render term gfx dir =
    let body =
-          State.evaluate (0, OptionSet.initial) $
+          flip MR.runReader dir $
+          flip MS.evalStateT (0, OptionSet.initial) $
           Display.runScript $
           Display.toScript gfx
-   in  do mapM_ Display.writeData (Display.files body)
-          Exec.simple
-             (term $ Display.commands body)
-             ["--persist"]
+   in  (Terminal.format term ++ Display.commands body,
+        Display.files body)
 
-formatTerminal ::
-   (Terminal.C terminal) =>
-   terminal -> String
-formatTerminal term =
-   let (Terminal.Cons options commands) = Terminal.canonical term
-   in  semiColonConcat $
-          ("set terminal " ++ unwords options) : commands
 
+{- |
+Plot using the default gnuplot terminal.
+-}
+plotDefault ::
+   (Display.C gfx) =>
+   gfx -> IO ExitCode
+plotDefault =
+   plot DefaultTerm.cons
 
 {-
 In the module introduction we refer to Monoid.
diff --git a/src/Graphics/Gnuplot/File.hs b/src/Graphics/Gnuplot/File.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/File.hs
@@ -0,0 +1,17 @@
+module Graphics.Gnuplot.File (T(Cons, name, content), write) where
+
+import qualified Graphics.Gnuplot.Private.File as File
+
+data T =
+   Cons {
+      name :: FilePath,
+      content :: String
+   }
+   deriving (Show, Eq)
+
+
+write :: T -> IO ()
+write (Cons fn cont) = writeFile fn cont
+
+instance File.C T where
+   write = write
diff --git a/src/Graphics/Gnuplot/Frame/Option.hs b/src/Graphics/Gnuplot/Frame/Option.hs
--- a/src/Graphics/Gnuplot/Frame/Option.hs
+++ b/src/Graphics/Gnuplot/Frame/Option.hs
@@ -24,6 +24,10 @@
    yTicks,
    zTicks,
 
+   xLogScale,
+   yLogScale,
+   zLogScale,
+
    xData,
    yData,
    zData,
diff --git a/src/Graphics/Gnuplot/Frame/OptionSet.hs b/src/Graphics/Gnuplot/Frame/OptionSet.hs
--- a/src/Graphics/Gnuplot/Frame/OptionSet.hs
+++ b/src/Graphics/Gnuplot/Frame/OptionSet.hs
@@ -4,10 +4,14 @@
 
    OptionSet.add,
    OptionSet.remove,
+   OptionSet.boolean,
+   OptionSet.addBool,
 
    size,
    title,
    key,
+   keyInside,
+   keyOutside,
    xRange2d,
    yRange2d,
    xRange3d,
@@ -21,6 +25,9 @@
    xTicks3d,
    yTicks3d,
    zTicks3d,
+   xLogScale,
+   yLogScale,
+   zLogScale,
    grid,
    gridXTicks,
    gridYTicks,
@@ -49,7 +56,7 @@
 
 import Graphics.Gnuplot.Private.FrameOptionSet (T, )
 
-import Graphics.Gnuplot.Utility (quote, formatBool, )
+import Graphics.Gnuplot.Utility (quote, )
 
 import qualified Data.List as List
 
@@ -69,6 +76,12 @@
 key :: Graph.C graph => Bool -> T graph -> T graph
 key = OptionSet.boolean Option.keyShow
 
+keyInside :: Graph.C graph => T graph -> T graph
+keyInside = OptionSet.add Option.keyPosition ["inside"]
+
+keyOutside :: Graph.C graph => T graph -> T graph
+keyOutside = OptionSet.add Option.keyPosition ["outside"]
+
 {-
 xRange :: Graph.C graph => (Double, Double) -> T graph -> T graph
 xRange = range Option.xRange
@@ -220,26 +233,34 @@
           labels]
 
 
+xLogScale :: Graph.C graph => T graph -> T graph
+xLogScale = OptionSet.add Option.xLogScale []
+
+yLogScale :: Graph.C graph => T graph -> T graph
+yLogScale = OptionSet.add Option.yLogScale []
+
+zLogScale ::
+   (Atom.C x, Atom.C y, Atom.C z) =>
+   T (Graph3D.T x y z) -> T (Graph3D.T x y z)
+zLogScale = OptionSet.add Option.zLogScale []
+
+
 grid :: Graph.C graph => Bool -> T graph -> T graph
 grid b =
-   gridTicks Option.gridXTicks b .
-   gridTicks Option.gridYTicks b .
-   gridTicks Option.gridZTicks b
+   OptionSet.addBool Option.gridXTicks b .
+   OptionSet.addBool Option.gridYTicks b .
+   OptionSet.addBool Option.gridZTicks b
 
 gridXTicks :: Graph.C graph => Bool -> T graph -> T graph
-gridXTicks = gridTicks Option.gridXTicks
+gridXTicks = OptionSet.addBool Option.gridXTicks
 
 gridYTicks :: Graph.C graph => Bool -> T graph -> T graph
-gridYTicks = gridTicks Option.gridYTicks
+gridYTicks = OptionSet.addBool Option.gridYTicks
 
 gridZTicks ::
    (Atom.C x, Atom.C y, Atom.C z) =>
    Bool -> T (Graph3D.T x y z) -> T (Graph3D.T x y z)
-gridZTicks = gridTicks Option.gridZTicks
-
-gridTicks :: Graph.C graph => Option.T -> Bool -> T graph -> T graph
-gridTicks opt@(Option.Cons _ name) b =
-   OptionSet.add opt [formatBool name b]
+gridZTicks = OptionSet.addBool Option.gridZTicks
 
 
 boxwidthRelative ::
diff --git a/src/Graphics/Gnuplot/Frame/OptionSet/Style.hs b/src/Graphics/Gnuplot/Frame/OptionSet/Style.hs
--- a/src/Graphics/Gnuplot/Frame/OptionSet/Style.hs
+++ b/src/Graphics/Gnuplot/Frame/OptionSet/Style.hs
@@ -15,13 +15,11 @@
 
 fillSolid :: Graph.C graph => T graph -> T graph
 fillSolid =
-   OptionSet.add Option.styleFillSolid ["solid"]
+   OptionSet.addBool Option.styleFillSolid True
 
 fillBorder :: Graph.C graph => Bool -> T graph -> T graph
-fillBorder on =
-   if on
-     then OptionSet.add Option.styleFillBorder ["border"]
-     else OptionSet.add Option.styleFillBorder ["noborder"]
+fillBorder =
+   OptionSet.addBool Option.styleFillBorder
 
 fillBorderLineType :: Graph.C graph => Int -> T graph -> T graph
 fillBorderLineType n =
diff --git a/src/Graphics/Gnuplot/Graph/ThreeDimensional.hs b/src/Graphics/Gnuplot/Graph/ThreeDimensional.hs
--- a/src/Graphics/Gnuplot/Graph/ThreeDimensional.hs
+++ b/src/Graphics/Gnuplot/Graph/ThreeDimensional.hs
@@ -8,8 +8,11 @@
 
    impulses,
    vectors,
-   pm3d,
+   Graph3DType.pm3d,
+
+   Graph3DType.lines,
+   points,
    ) where
 
 import Graphics.Gnuplot.Private.Graph3D
-import Graphics.Gnuplot.Private.Graph3DType hiding (T, )
+import Graphics.Gnuplot.Private.Graph3DType as Graph3DType hiding (T, )
diff --git a/src/Graphics/Gnuplot/Graph/TwoDimensional.hs b/src/Graphics/Gnuplot/Graph/TwoDimensional.hs
--- a/src/Graphics/Gnuplot/Graph/TwoDimensional.hs
+++ b/src/Graphics/Gnuplot/Graph/TwoDimensional.hs
@@ -46,6 +46,11 @@
    financeBars,
    candleSticks,
    vectors,
+   image,
+
+   filledStripe,
+   filledStripeAbove,
+   filledStripeBelow,
    ) where
 
 import Graphics.Gnuplot.Private.Graph2D
diff --git a/src/Graphics/Gnuplot/Plot.hs b/src/Graphics/Gnuplot/Plot.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Plot.hs
@@ -0,0 +1,3 @@
+module Graphics.Gnuplot.Plot (T) where
+
+import Graphics.Gnuplot.Private.Plot (T)
diff --git a/src/Graphics/Gnuplot/Plot/ThreeDimensional.hs b/src/Graphics/Gnuplot/Plot/ThreeDimensional.hs
--- a/src/Graphics/Gnuplot/Plot/ThreeDimensional.hs
+++ b/src/Graphics/Gnuplot/Plot/ThreeDimensional.hs
@@ -55,11 +55,9 @@
     Tuple.C x, Tuple.C y, Tuple.C z) =>
    [[(x,y,z)]] -> T x y z
 mesh pss =
-   let typ :: [[a]] -> Type.T x y z a -> Type.T x y z a
-       typ _ = id
-   in  Plot.withUniqueFile
-          (assembleCells (concat (map (\ps -> map Tuple.text ps ++ [[]]) pss)))
-          [Graph.deflt (typ pss Type.pm3d) (1:2:3:[])]
+   Plot.withUniqueFile
+      (assembleCells (concatMap (\ps -> map Tuple.text ps ++ [[]]) pss))
+      [Graph.pm3d]
 
 surface ::
    (Atom.C x, Atom.C y, Atom.C z,
diff --git a/src/Graphics/Gnuplot/Private/Command.hs b/src/Graphics/Gnuplot/Private/Command.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Private/Command.hs
@@ -0,0 +1,28 @@
+module Graphics.Gnuplot.Private.Command where
+
+import qualified Graphics.Gnuplot.Private.File as File
+import qualified Graphics.Gnuplot.Execute as Exec
+import System.Exit (ExitCode(ExitSuccess), )
+import Control.Concurrent (forkIO, )
+
+import System.IO.Temp (withSystemTempDirectory, )
+
+import Control.DeepSeq (deepseq, )
+import Control.Functor.HT (void, )
+
+
+run ::
+   (File.C file) =>
+   (FilePath -> ([String], [file])) -> IO ExitCode
+run render =
+   withSystemTempDirectory "gnuplot" $ \dir ->
+   case render dir of
+      (cmds, files) -> deepseq cmds $ do
+         mapM_ File.write files
+         Exec.simple (cmds ++ ["pause mouse close"]) []
+
+asyncIfInteractive :: Bool -> IO ExitCode -> IO ExitCode
+asyncIfInteractive interactive act =
+   if interactive
+     then fmap (const ExitSuccess) $ forkIO $ void act
+     else act
diff --git a/src/Graphics/Gnuplot/Private/Display.hs b/src/Graphics/Gnuplot/Private/Display.hs
--- a/src/Graphics/Gnuplot/Private/Display.hs
+++ b/src/Graphics/Gnuplot/Private/Display.hs
@@ -1,47 +1,40 @@
 module Graphics.Gnuplot.Private.Display where
 
 import qualified Graphics.Gnuplot.Private.FrameOption as Option
+import qualified Graphics.Gnuplot.File as File
 
 import qualified Data.Map as Map
-import qualified Data.Monoid.State as State
+import qualified Control.Monad.Trans.Reader as MR
+import qualified Control.Monad.Trans.State as MS
+import Control.Monad (liftM2, )
 import Data.Monoid (Monoid, mempty, mappend, )
 
 
 newtype Script =
    Script {
-      runScript :: State.T (Int, OptionSet) Body
+      runScript :: MS.StateT (Int, OptionSet) (MR.Reader FilePath) Body
    }
 
 pure :: Body -> Script
-pure = Script . State.pure
+pure = Script . return
 
 data Body =
    Body {
-      files :: [File],
+      files :: [File.T],
       commands :: [String]
    }
 
 type OptionSet = Map.Map Option.T [String]
 
-data File =
-   File {
-      filename :: FilePath,
-      content :: String
-   }
 
-writeData :: File -> IO ()
-writeData (File fn cont) =
-   writeFile fn cont
-
-
 {-
 Could also be implemented with Control.Monad.Trans.State:
 mappend = liftA2 mappend
 -}
 instance Monoid Script where
-   mempty = Script mempty
+   mempty = Script $ return mempty
    mappend (Script b0) (Script b1) =
-      Script (mappend b0 b1)
+      Script (liftM2 mappend b0 b1)
 
 {-
 Could also be implemented with Control.Monad.Trans.State:
diff --git a/src/Graphics/Gnuplot/Private/File.hs b/src/Graphics/Gnuplot/Private/File.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Private/File.hs
@@ -0,0 +1,4 @@
+module Graphics.Gnuplot.Private.File where
+
+class C file where
+   write :: file -> IO ()
diff --git a/src/Graphics/Gnuplot/Private/FrameOption.hs b/src/Graphics/Gnuplot/Private/FrameOption.hs
--- a/src/Graphics/Gnuplot/Private/FrameOption.hs
+++ b/src/Graphics/Gnuplot/Private/FrameOption.hs
@@ -9,15 +9,35 @@
 It is altered with gnuplot's set command.
 The first field in 'T' is the name of the option
 and the name of the according internal state in gnuplot.
+
 Sometimes the addressed state is not explicitly mentioned
 but is expressed by the syntax of the values.
-For this case we manage an identifier in the second field.
-It is only used for distinguishing between these states,
-but it is never written to a gnuplot script.
+E.g. you can write @set grid xtics@ and @set grid noxtics@,
+but both commands refer to the same internal boolean variable,
+that we like to call @xtics@.
+It is important that the gnuplot Haskell bindings know
+that these two set commands refer to the same gnuplot state,
+since we want to simulate a stateless functional interface
+in front of a stateful imperative one.
+
+In case of a such a hidden state,
+we manage an identifier in the second field of 'T'.
+It is mainly used for distinguishing different hidden states,
+that are accessed by the same @set@ variable.
+This second field may not contain valid gnuplot identifiers,
+however you might use the field for formatting boolean options
+using 'Graphics.Gnuplot.Frame.OptionSet.addBool'.
 -}
 data T = Cons String String
    deriving (Eq, Ord, Show)
 
+{- |
+Constructs a generic option from Strings for the first and second field of 'T'.
+
+This is very flexible, but not very safe.
+Use it only as fall-back,
+if there is no specific setter function in "Graphics.Gnuplot.Frame.OptionSet".
+-}
 custom :: String -> String -> T
 custom = Cons
 
@@ -39,7 +59,11 @@
 yTicks :: String -> T; yTicks = Cons "ytics"
 zTicks :: String -> T; zTicks = Cons "ztics"
 
+xLogScale :: T; xLogScale = Cons "logscale x" ""
+yLogScale :: T; yLogScale = Cons "logscale y" ""
+zLogScale :: T; zLogScale = Cons "logscale z" ""
 
+
 title :: T; title = Cons "title" ""
 view  :: T; view  = Cons "view" ""
 
@@ -55,7 +79,8 @@
 
 
 sizeScale :: T; sizeScale = size "scale"
-keyShow   :: T; keyShow   = key "show"
+keyShow     :: T; keyShow     = key "show"
+keyPosition :: T; keyPosition = key "position"
 
 xRangeBounds :: T; xRangeBounds = xRange "bounds"
 yRangeBounds :: T; yRangeBounds = yRange "bounds"
diff --git a/src/Graphics/Gnuplot/Private/FrameOptionSet.hs b/src/Graphics/Gnuplot/Private/FrameOptionSet.hs
--- a/src/Graphics/Gnuplot/Private/FrameOptionSet.hs
+++ b/src/Graphics/Gnuplot/Private/FrameOptionSet.hs
@@ -11,7 +11,7 @@
 module Graphics.Gnuplot.Private.FrameOptionSet where
 
 import qualified Graphics.Gnuplot.Private.FrameOption as Option
--- import Graphics.Gnuplot.Utility (quote, )
+import Graphics.Gnuplot.Utility (formatBool, )
 
 import qualified Data.Map as Map
 
@@ -67,7 +67,8 @@
    []
 
 {- |
-Add an option with arguments as plain strings.
+Add (set) an option with arguments as plain strings.
+
 This is very flexible, but not very safe.
 Use it only as fall-back,
 if there is no specific setter function in "Graphics.Gnuplot.Frame.OptionSet".
@@ -77,7 +78,11 @@
    Cons (Map.insert opt args m)
 
 {- |
-Remove an option.
+Remove (unset) an option.
+
+This is very flexible, but not very safe.
+Use it only as fall-back,
+if there is no specific setter function in "Graphics.Gnuplot.Frame.OptionSet".
 -}
 remove :: Option.T -> T graph -> T graph
 remove opt (Cons m) =
@@ -102,8 +107,34 @@
       (fmap (\x -> (Just x, Nothing)) m0)
       (fmap (\x -> (Nothing, Just x)) m1)
 
+{- |
+Set or unset option according to a 'Bool'.
+This is for switches that can be disabled using @unset@.
+
+This is very flexible, but not very safe.
+Use it only as fall-back,
+if there is no specific setter function in "Graphics.Gnuplot.Frame.OptionSet".
+
+See also: 'addBool', 'add', 'remove'.
+-}
 boolean :: Option.T -> Bool -> T graph -> T graph
 boolean opt on =
    if on
      then add opt []
      else remove opt
+
+{- |
+Add an option with boolean value
+that is formatted like @set style fill border@ and @set style fill noborder@.
+The name of the internal state (i.e. @border@)
+must be stored in the second field of the option.
+
+This is very flexible, but not very safe.
+Use it only as fall-back,
+if there is no specific setter function in "Graphics.Gnuplot.Frame.OptionSet".
+
+See also 'boolean'.
+-}
+addBool :: Option.T -> Bool -> T graph -> T graph
+addBool opt@(Option.Cons _ state) arg =
+   add opt [formatBool state arg]
diff --git a/src/Graphics/Gnuplot/Private/Graph2DType.hs b/src/Graphics/Gnuplot/Private/Graph2DType.hs
--- a/src/Graphics/Gnuplot/Private/Graph2DType.hs
+++ b/src/Graphics/Gnuplot/Private/Graph2DType.hs
@@ -62,8 +62,13 @@
 financeBars    :: (Atom.C x, Atom.C y) => T x y (x,(y,y,y,y))
 candleSticks   :: (Atom.C x, Atom.C y) => T x y (x,(y,y,y,y))
 vectors        :: (Atom.C x, Atom.C y) => T x y ((x,y),(x,y))
+image          :: (Atom.C x, Atom.C y, Atom.C z) => T x y ((x, y), z)
 
+filledStripe      :: (Atom.C x, Atom.C y) => T x y (x,(y,y))
+filledStripeAbove :: (Atom.C x, Atom.C y) => T x y (x,(y,y))
+filledStripeBelow :: (Atom.C x, Atom.C y) => T x y (x,(y,y))
 
+
 listLines       = Cons "lines"
 listPoints      = Cons "points"
 listLinesPoints = Cons "linespoints"
@@ -104,6 +109,11 @@
 financeBars    = Cons "financebars"
 candleSticks   = Cons "candlesticks"
 vectors        = Cons "vectors"
+image          = Cons "image"
+
+filledStripe      = Cons "filledcurves"
+filledStripeAbove = Cons "filledcurves above"
+filledStripeBelow = Cons "filledcurves below"
 
 
 toString :: T x y a -> String
diff --git a/src/Graphics/Gnuplot/Private/Graph3D.hs b/src/Graphics/Gnuplot/Private/Graph3D.hs
--- a/src/Graphics/Gnuplot/Private/Graph3D.hs
+++ b/src/Graphics/Gnuplot/Private/Graph3D.hs
@@ -65,6 +65,9 @@
    defltOptions = defltOptions
 
 
+pm3d :: T x y z
+pm3d = Cons (1:2:3:[]) "pm3d" LineSpec.deflt
+
 deflt :: GraphType.T x y z a -> Columns -> T x y z
 deflt t c = Cons c (GraphType.toString t) LineSpec.deflt
 
diff --git a/src/Graphics/Gnuplot/Private/Graph3DType.hs b/src/Graphics/Gnuplot/Private/Graph3DType.hs
--- a/src/Graphics/Gnuplot/Private/Graph3DType.hs
+++ b/src/Graphics/Gnuplot/Private/Graph3DType.hs
@@ -12,6 +12,13 @@
 tupleSize _ = Tuple.columnCount
 
 
+lines          :: (Atom.C x, Atom.C y, Atom.C z) => T x y z (x,y,z)
+points         :: (Atom.C x, Atom.C y, Atom.C z) => T x y z (x,y,z)
+
+lines          = Cons "lines"
+points         = Cons "points"
+
+
 {-
 See info:/gnuplot/set_style_rectangle
 -}
@@ -23,6 +30,8 @@
 impulses       = Cons "impulses"
 vectors        = Cons "vectors"
 pm3d           = Cons "pm3d"
+
+{-# DEPRECATED pm3d "do not use this as graph type, use Graphics.Gnuplot.Plot.ThreeDimensional.surface instead" #-}
 
 
 toString :: T x y z a -> String
diff --git a/src/Graphics/Gnuplot/Private/Plot.hs b/src/Graphics/Gnuplot/Private/Plot.hs
--- a/src/Graphics/Gnuplot/Private/Plot.hs
+++ b/src/Graphics/Gnuplot/Private/Plot.hs
@@ -3,39 +3,53 @@
 import qualified Graphics.Gnuplot.Private.Display as Display
 import qualified Graphics.Gnuplot.Private.FrameOptionSet as OptionSet
 import qualified Graphics.Gnuplot.Private.Graph as Graph
+import qualified Graphics.Gnuplot.Private.File as FileClass
+import qualified Graphics.Gnuplot.File as File
 import Graphics.Gnuplot.Utility (quote, commaConcat, )
 
 import qualified Data.Foldable as Fold
-import qualified Data.Monoid.State as State
+import qualified Control.Monad.Trans.Reader as MR
+import qualified Control.Monad.Trans.State as MS
+import qualified Control.Monad.Trans.Class as MT
+import qualified Data.Accessor.Monad.Trans.State as AccState
+import qualified Data.Accessor.Tuple as AccTuple
+import Control.Monad (liftM2, )
 import Data.Monoid (Monoid, mempty, mappend, )
 
 import Data.Maybe (mapMaybe, )
 
+import qualified System.FilePath as Path
+import System.FilePath ((</>), )
 
+
 {- |
 Plots can be assembled using 'mappend' or 'mconcat'
 or several functions from "Data.Foldable".
 -}
-newtype T graph = Cons (State.T Int [File graph])
+newtype T graph = Cons (MS.StateT Int (MR.Reader FilePath) [File graph])
 
 pure :: [File graph] -> T graph
-pure = Cons . State.pure
+pure = Cons . return
 
 {-
 Could also be implemented with Control.Monad.Trans.State:
 mappend = liftA2 mappend
 -}
 instance Monoid (T graph) where
-   mempty = Cons mempty
+   mempty = Cons $ return mempty
    mappend (Cons s0) (Cons s1) =
-      Cons (mappend s0 s1)
+      Cons (liftM2 mappend s0 s1)
 
 
 withUniqueFile :: String -> [graph] -> T graph
-withUniqueFile content graphs =
-   Cons (State.Cons $ \n ->
-      ([File (tmpFileStem ++ show n ++ ".csv") (Just content) graphs],
-       succ n))
+withUniqueFile content graphs = Cons $ do
+   n <- MS.get
+   dir <- MT.lift MR.ask
+   MS.put $ succ n
+   return $
+      [File
+         (dir </> Path.addExtension (tmpFileStem ++ show n) "csv")
+         (Just content) graphs]
 
 fromGraphs :: FilePath -> [graph] -> T graph
 fromGraphs name gs =
@@ -49,9 +63,9 @@
       graphs_ :: [graph]
    }
 
-writeData :: File graph -> IO ()
-writeData (File fn cont _) =
-   Fold.mapM_ (writeFile fn) cont
+instance FileClass.C (File graph) where
+   write (File fn cont _) =
+      Fold.mapM_ (writeFile fn) cont
 
 
 tmpFileStem :: FilePath
@@ -76,31 +90,34 @@
 -}
 toScript :: Graph.C graph => T graph -> Display.Script
 toScript p@(Cons mp) =
-   Display.Script $ State.Cons $
-      \(n0, opts) ->
-         let (blocks, n1) = State.run mp n0
-             files =
-                mapMaybe
-                   (\blk -> fmap (Display.File (filename_ blk)) (content_ blk))
-                   blocks
-             graphs =
-                concatMap (\blk ->
-                   map (\gr ->
-                           quote (filename_ blk) ++ " " ++
-                           Graph.toString gr) $ graphs_ blk) $
-                   blocks
-         in  (Display.Body files
-                 [plotCmd p undefined ++ " " ++ commaConcat graphs],
-              (n1, opts))
+   Display.Script $ do
+      blocks <- AccState.liftT AccTuple.first mp
+      let files =
+             mapMaybe
+                (\blk -> fmap (File.Cons (filename_ blk)) (content_ blk))
+                blocks
+          graphs =
+             concatMap
+                (\blk ->
+                   map
+                      (\gr ->
+                         quote (filename_ blk) ++ " " ++
+                         Graph.toString gr) $ graphs_ blk) $
+             blocks
+      return $
+         Display.Body files
+            [plotCmd p undefined ++ " " ++ commaConcat graphs]
 
 optionsToScript :: Graph.C graph => OptionSet.T graph -> Display.Script
 optionsToScript opts =
    Display.Script $
-      State.Cons $ \(n, opts0) ->
-         let opts1 = OptionSet.decons opts
-         in  (Display.Body [] $
-              OptionSet.diffToString opts0 opts1,
-              (n, opts1))
+   AccState.liftT AccTuple.second $ do
+      opts0 <- MS.get
+      let opts1 = OptionSet.decons opts
+      MS.put opts1
+      return $
+         Display.Body [] $
+         OptionSet.diffToString opts0 opts1
 
 defltOpts :: Graph.C graph => T graph -> OptionSet.T graph
 defltOpts _ = Graph.defltOptions
diff --git a/src/Graphics/Gnuplot/Private/Terminal.hs b/src/Graphics/Gnuplot/Private/Terminal.hs
--- a/src/Graphics/Gnuplot/Private/Terminal.hs
+++ b/src/Graphics/Gnuplot/Private/Terminal.hs
@@ -3,11 +3,15 @@
 data T =
    Cons {
       options :: [String],
-      commands :: [String]
+      commands :: [String],
+      interactive :: Bool
    }
 
 class C terminal where
    canonical :: terminal -> T
 
-deflt :: T
-deflt = Cons ["x11"] []
+format :: T -> [String]
+format (Cons opts cmds _ia) =
+   if null opts
+     then cmds
+     else (unwords $ "set" : "terminal" : opts) : cmds
diff --git a/src/Graphics/Gnuplot/Simple.hs b/src/Graphics/Gnuplot/Simple.hs
--- a/src/Graphics/Gnuplot/Simple.hs
+++ b/src/Graphics/Gnuplot/Simple.hs
@@ -65,12 +65,16 @@
 -}
 
 import qualified Graphics.Gnuplot.Private.Terminal as Terminal
-import qualified Graphics.Gnuplot.Execute as Exec
 
-import System.Cmd (rawSystem, )
 import Graphics.Gnuplot.Utility
    (quote, commaConcat, semiColonConcat, showTriplet, linearScale, )
-import qualified Data.Monoid.State as State
+
+import qualified Control.Monad.Trans.Reader as MR
+import qualified Control.Monad.Trans.State as MS
+
+import qualified Graphics.Gnuplot.Private.Command as Cmd
+import System.Cmd (rawSystem, )
+import Control.Functor.HT (void, )
 import Data.Foldable (foldMap, )
 import Data.Maybe (listToMaybe, mapMaybe, isNothing, )
 import Data.List.HT (dropWhileRev, )
@@ -338,8 +342,7 @@
    -> IO ()
 epspdfPlot filename plot =
    do plot (EPS (filename++".eps") : Key Nothing : [])
-      _ <- rawSystem "epstopdf" [filename++".eps"]
-      return ()
+      void $ rawSystem "epstopdf" [filename++".eps"]
 
 {-| Creates an EPS and a PDF graphics
     and returns a string that can be inserted into a LaTeX document
@@ -365,9 +368,8 @@
 attrToProg (Custom attribute parameters) =
    "set " ++ attribute ++ " " ++ unwords parameters
 
-attrToProg (Terminal (Terminal.Cons options commands)) =
-   semiColonConcat $
-   ("set terminal " ++ unwords options) : commands
+attrToProg (Terminal term) =
+   semiColonConcat $ Terminal.format term
 
 attrToProg (EPS filename) =
    "set terminal postscript eps; " ++  -- latex
@@ -428,8 +430,17 @@
        showRng (l,r) = "[" ++ show l ++ ":" ++ show r ++ "]"
    in  unwords (map (maybe "[:]" showRng) (dropWhileRev isNothing ranges))
 
+interactiveTerm :: [Attribute] -> Bool
+interactiveTerm =
+   all $ \attr ->
+      case attr of
+         Terminal term -> Terminal.interactive term
+         PNG _ -> False
+         EPS _ -> False
+         _ -> True
 
 
+
 plotTypeToGraph :: PlotType -> Graph2D.Type -- GraphType.T
 plotTypeToGraph t =
    case t of
@@ -520,20 +531,17 @@
    Graph.C graph =>
    [Attribute] -> String -> Plot.T graph -> IO ()
 runGnuplot attrs cmd (Plot.Cons mp) =
-   let files = State.evaluate 0 mp
-   in  do mapM_ Plot.writeData files
-          callGnuplot attrs cmd $
-             concatMap (\(Plot.File filename _ grs) ->
-                map (\gr -> quote filename ++ " " ++ Graph.toString gr) grs) $
-             files
+   void $ Cmd.asyncIfInteractive (interactiveTerm attrs) $ Cmd.run $ \dir ->
+      let files = MR.runReader (MS.evalStateT mp 0) dir
+      in  (map attrToProg attrs ++
+           [cmd ++ " " ++
+            extractRanges attrs ++ " " ++
+            commaConcat (plotFileStatements files)],
+           files)
 
-callGnuplot :: [Attribute] -> String -> [String] -> IO ()
-callGnuplot attrs cmd params =
-   Exec.simple
-      (map attrToProg attrs ++
-       [cmd ++ " " ++
-        extractRanges attrs ++ " " ++
-        commaConcat params])
-      ["--persist"]
-   -- instead of the option, one can also use 'set terminal x11 persist'
-     >> return ()
+plotFileStatements ::
+   Graph.C graph => [Plot.File graph] -> [String]
+plotFileStatements =
+   concatMap
+      (\(Plot.File filename _ grs) ->
+         map (\gr -> quote filename ++ " " ++ Graph.toString gr) grs)
diff --git a/src/Graphics/Gnuplot/Terminal/Default.hs b/src/Graphics/Gnuplot/Terminal/Default.hs
new file mode 100644
--- /dev/null
+++ b/src/Graphics/Gnuplot/Terminal/Default.hs
@@ -0,0 +1,20 @@
+module Graphics.Gnuplot.Terminal.Default (
+   T, cons,
+   ) where
+
+import qualified Graphics.Gnuplot.Private.Terminal as Terminal
+
+
+data T = Cons
+
+cons :: T
+cons = Cons
+
+
+instance Terminal.C T where
+   canonical _term =
+      Terminal.Cons {
+         Terminal.options = [],
+         Terminal.commands = [],
+         Terminal.interactive = True  -- Always true? I don't know.
+      }
diff --git a/src/Graphics/Gnuplot/Terminal/PNG.hs b/src/Graphics/Gnuplot/Terminal/PNG.hs
--- a/src/Graphics/Gnuplot/Terminal/PNG.hs
+++ b/src/Graphics/Gnuplot/Terminal/PNG.hs
@@ -86,5 +86,6 @@
                (fmap formatFontSize $ fontSize_ term) :
                []),
          Terminal.commands =
-            ["set output " ++ (quote $ filename_ term)]
+            ["set output " ++ (quote $ filename_ term)],
+         Terminal.interactive = False
       }
diff --git a/src/Graphics/Gnuplot/Terminal/PostScript.hs b/src/Graphics/Gnuplot/Terminal/PostScript.hs
--- a/src/Graphics/Gnuplot/Terminal/PostScript.hs
+++ b/src/Graphics/Gnuplot/Terminal/PostScript.hs
@@ -91,5 +91,6 @@
             (maybe [] (\(name,size) -> "font" : quote name : show size : []) $ font_ term) ++
             [],
          Terminal.commands =
-            ["set output " ++ (quote $ filename_ term)]
+            ["set output " ++ (quote $ filename_ term)],
+         Terminal.interactive = False
       }
diff --git a/src/Graphics/Gnuplot/Terminal/SVG.hs b/src/Graphics/Gnuplot/Terminal/SVG.hs
--- a/src/Graphics/Gnuplot/Terminal/SVG.hs
+++ b/src/Graphics/Gnuplot/Terminal/SVG.hs
@@ -28,5 +28,6 @@
             "svg" :
             [],
          Terminal.commands =
-            ["set output " ++ (quote $ filename_ term)]
+            ["set output " ++ (quote $ filename_ term)],
+         Terminal.interactive = False
       }
diff --git a/src/Graphics/Gnuplot/Terminal/WXT.hs b/src/Graphics/Gnuplot/Terminal/WXT.hs
--- a/src/Graphics/Gnuplot/Terminal/WXT.hs
+++ b/src/Graphics/Gnuplot/Terminal/WXT.hs
@@ -47,6 +47,6 @@
                (fmap quote $ title_ term) :
                (fmap (formatBool "persist") $ persist_ term) :
                []),
-         Terminal.commands =
-            []
+         Terminal.commands = [],
+         Terminal.interactive = True
       }
diff --git a/src/Graphics/Gnuplot/Terminal/X11.hs b/src/Graphics/Gnuplot/Terminal/X11.hs
--- a/src/Graphics/Gnuplot/Terminal/X11.hs
+++ b/src/Graphics/Gnuplot/Terminal/X11.hs
@@ -43,6 +43,6 @@
                (fmap quote $ title_ term) :
                (fmap (formatBool "persist") $ persist_ term) :
                []),
-         Terminal.commands =
-            []
+         Terminal.commands = [],
+         Terminal.interactive = True
       }
