diff -urP --ignore-space-change orig/src/CH/ifa/draw/appframe/Application.java moin-utf8/src/CH/ifa/draw/appframe/Application.java
--- orig/src/CH/ifa/draw/appframe/Application.java	2005-03-08 17:48:42.000000000 +0000
+++ moin-utf8/src/CH/ifa/draw/appframe/Application.java	2005-11-27 23:42:26.000000000 +0000
@@ -24,6 +24,6 @@
                  String fileName,
                  String type,
                  String path,
-                 String content,
+                 byte[] content,
                  String comment) throws IOException;
 }
diff -urP --ignore-space-change orig/src/CH/ifa/draw/standard/CompositeFigure.java moin-utf8/src/CH/ifa/draw/standard/CompositeFigure.java
--- orig/src/CH/ifa/draw/standard/CompositeFigure.java	2003-02-02 10:16:46.000000000 +0000
+++ moin-utf8/src/CH/ifa/draw/standard/CompositeFigure.java	2005-11-27 18:33:04.000000000 +0000
@@ -395,7 +395,7 @@
 	String areas = "";
         Enumeration k = fFigures.elements();
         while (k.hasMoreElements())
-            areas += ((Storable) k.nextElement()).getMap();
+            areas = ((Storable) k.nextElement()).getMap() + areas;
 	return areas;
     }
 
diff -urP --ignore-space-change orig/src/CH/ifa/draw/twiki/TWikiDraw.java moin-utf8/src/CH/ifa/draw/twiki/TWikiDraw.java
--- orig/src/CH/ifa/draw/twiki/TWikiDraw.java	2005-03-08 18:00:56.000000000 +0000
+++ moin-utf8/src/CH/ifa/draw/twiki/TWikiDraw.java	2005-11-27 23:44:38.000000000 +0000
@@ -43,15 +43,23 @@
                         String fileName,
                         String type,
                         String path,
-                        String content,
+                        byte[] content,
                         String comment)
         throws IOException {
         
         String sep = "89692781418184";
-        while (content.indexOf(sep) != -1)
+        while (fileName.indexOf(sep) != -1)
+            sep += "x";
+        while (type.indexOf(sep) != -1)
+            sep += "x";
+        while (path.indexOf(sep) != -1)
+            sep += "x";
+        while (comment.indexOf(sep) != -1)
+            sep += "x";
+        while (indexOf(content, sep.getBytes()) != -1)
             sep += "x";
         
-        String message = makeMimeForm(fileName, type,
+        byte[] message = makeMimeForm(fileName, type,
                                       path, content, comment, sep);
         
         // for test
@@ -73,14 +81,14 @@
                                       "multipart/form-data; boundary=" + sep);
         connection.setRequestProperty(
                                       "Content-length",
-                                      Integer.toString(message.length()));
+                                      Integer.toString(message.length));
         
         //System.out.println(url);
         String replyString = null;
         try {
-            DataOutputStream out =
-                new DataOutputStream(connection.getOutputStream());
-            out.writeBytes(message);
+            OutputStream out =
+                connection.getOutputStream();
+            out.write(message);
             out.close();
             //System.out.println("Wrote " + message.length() +
             //		   " bytes to\n" + connection);
@@ -101,7 +109,7 @@
             }
         } catch (UnknownServiceException use) {
             replyString = use.getMessage();
-            System.out.println(message);
+            System.out.println(new String(message));
         }
         if (replyString != null) {
             //System.out.println("---- Reply " + replyString);
@@ -144,22 +152,19 @@
     static String NLNL = NL + NL;
     
     /** Post the given message */
-    private String makeMimeForm(
+    private byte[] makeMimeForm(
                                 String fileName,
                                 String type,
                                 String path,
-                                String content,
+                                byte[] content,
                                 String comment,
                                 String sep) {
         
-        String binary = "";
-        if (type.equals("image/gif")) {
-            binary = "Content-Transfer-Encoding: binary" + NL;
-        }
+        String binary = "Content-Transfer-Encoding: binary" + NL;
         
         String mime_sep = NL + "--" + sep + NL;
         
-        return
+        byte[] part1 = (
             "--" + sep + "\r\n" 
             + "Content-Disposition: form-data; name=\"filename\"" + NLNL
             + fileName
@@ -170,12 +175,17 @@
             + "Content-Disposition: form-data; name=\"filepath\"; "
             + "filename=\"" + path + "\"" + NL
             + "Content-Type: " + type + NL
-            + binary + NL
-            + content
-            + mime_sep
+            + binary + NL).getBytes();
+        byte[] part3 =
+             (mime_sep
             + "Content-Disposition: form-data; name=\"filecomment\"" + NLNL
             + comment
-            + NL + "--" + sep + "--" + NL;
+            + NL + "--" + sep + "--" + NL).getBytes();
+        byte[] res = new byte[part1.length + content.length + part3.length];
+        System.arraycopy(part1, 0, res, 0, part1.length);
+        System.arraycopy(content, 0, res, part1.length, content.length);
+        System.arraycopy(part3, 0, res, part1.length + content.length, part3.length);
+        return res;
     }
     
     /** Replace current app with a different URL */
@@ -191,5 +201,25 @@
         }
     }
     
+    private static int indexOf(byte[] searchin, byte[] searchfor){
+        if(searchfor.length==0)
+            return -1;
+        if(searchfor.length>searchin.length)
+            return -1;
+        if(searchfor.length==searchin.length)
+            return Arrays.equals(searchfor, searchin) ? 0 : -1;
+        for(int i=0; i<=searchin.length-searchfor.length; i++)
+            if((searchin[i]==searchfor[0]) && equals(searchin, i, searchfor))
+                return i;
+        return -1;
+    }
+
+    private static boolean equals(byte[] left, int leftOfs, byte[] right) {
+        for(int j=0; j<right.length; j++)
+            if(left[leftOfs+j]!=right[j])
+                return false;
+        return true;
+    }
+
     static private String VIEWPATH_PARAMETER   = "viewpath";
 }
diff -urP --ignore-space-change orig/src/CH/ifa/draw/twiki/TWikiFrame.java moin-utf8/src/CH/ifa/draw/twiki/TWikiFrame.java
--- orig/src/CH/ifa/draw/twiki/TWikiFrame.java	2005-03-08 17:59:34.000000000 +0000
+++ moin-utf8/src/CH/ifa/draw/twiki/TWikiFrame.java	2005-11-27 23:45:30.000000000 +0000
@@ -20,6 +20,7 @@
 import CH.ifa.draw.applet.*;
 import CH.ifa.draw.contrib.*;
 //import SVG.wiki.*;
+import com.keypoint.PngEncoderIndexed;
 
 import java.awt.*;
 import java.awt.event.*;
@@ -37,8 +38,10 @@
     static private String UNTITLED_PARAMETER   = "untitled";
     static private String DRAWPATH_PARAMETER   = "drawpath";
     static private String GIFPATH_PARAMETER    = "gifpath";
+    static private String PNGPATH_PARAMETER    = "pngpath";
     static private String SVGPATH_PARAMETER    = "svgpath";
     static private String SAVEPATH_PARAMETER   = "savepath";
+    static private String BASENAME_PARAMETER   = "basename";
     static private String HELPPATH_PARAMETER   = "helppath";
     static private String BORDERSIZE_PARAMETER = "bordersize";
     
@@ -361,8 +364,8 @@
     
     public boolean doSaveDrawing() {
         Application app = getApplication();
-        boolean savedDraw, savedSvg, savedGif, savedMap;
-        savedDraw = savedSvg = savedGif = savedMap = false;
+        boolean savedDraw, savedSvg, savedGif, savedPng, savedMap;
+        savedDraw = savedSvg = savedGif = savedPng = savedMap = false;
         
         // set wait cursor
         setCursor(new Cursor(Cursor.WAIT_CURSOR));
@@ -387,14 +390,19 @@
             if (savePath == null)
                 savePath = "";
             
+            // gets base filename
+            String baseName = app.getParameter(BASENAME_PARAMETER);
+            if (baseName == null)
+                baseName = "SET_BASENAME_PARAM";
+
             // submit POST command to the server three times:
-            // *.draw, *.map and *.gif
+            // *.draw, *.map, *.png and *.gif
             // first upload *.draw file
-            showStatus("Saving .draw file " + drawingPath);
+            showStatus("Saving " + baseName + ".draw");
             if (bPostEnabled)
                 savedDraw = app.post(
-                                     savePath, "", "text/plain", drawingPath,
-                                     out.toString(), "TWiki Draw draw file");
+                                     savePath, baseName + ".draw", "text/plain", drawingPath,
+                                     out.toByteArray(), "TWiki Draw draw file");
             
             // calculate the minimum size of the gif image
             Dimension d = new Dimension(0, 0); // not this.view().getSize();
@@ -423,7 +431,7 @@
             String map = drawing().getMap();
             if (map.length() > 0) {
                 String mapPath = drawingPath.substring(0, drawingPath.length() - 5) + ".map";
-                showStatus("Saving .map file " + mapPath);
+                showStatus("Saving " + baseName + ".map");
                 // enclose the map and add editable border. Note that the
                 // edit border is added LAST so the earlier AREAs take
                 // precedence.
@@ -452,12 +460,12 @@
                     
                     "</map>";
                 savedMap = app.post(
-                                    savePath, "", "text/plain", mapPath,
-                                    map, "TWiki Draw map file");
+                                    savePath, baseName + ".map", "text/plain", mapPath + ".map",
+                                    map.getBytes(), "TWiki Draw map file");
             } else {
                 // erase any previous map file
                 String mapPath = drawingPath.substring(0, drawingPath.length() - 5);
-                savedMap = app.post( savePath, "", "text/plain", mapPath + ".map", "", "" );
+                savedMap = app.post( savePath, baseName + ".map", "text/plain", mapPath + ".map", new byte[0], "" );
             }
             
             // get pathname of the SVG file
@@ -477,24 +485,38 @@
             // gets pathname of the GIF image
             String gifPath = getApplication().getParameter(GIFPATH_PARAMETER);
             if (gifPath == null || gifPath.length() == 0)
-                gifPath = "untitled.gif";
-            
-            // then create *.gif image and upload file
-            showStatus("Saving .gif file " + gifPath);
+                gifPath = null;
             
-            // clear the selection so it doesn't appear
-            view().clearSelection();
-            
-            final Image oImgBuffer =
-                this.view().createImage(d.width + iBorder, d.height + iBorder);
-            final char[] aChar = convertToGif(oImgBuffer);
+            // gets pathname of the PNG image
+            String pngPath = getApplication().getParameter(PNGPATH_PARAMETER);
+            if (pngPath == null || pngPath.length() == 0) 
+                pngPath = null;
+
+            if (gifPath != null || pngPath != null) {
+                final Image oImgBuffer = createImage(d, iBorder);
+            
+                if (bPostEnabled && pngPath != null)
+                {
+                    // then create *.png image and upload file
+                    showStatus("Saving " + baseName + ".png");
+                    final byte[] aByte = convertToPng(oImgBuffer);
+                    // upload *.png file
+                    savedPng = app.post(savePath, baseName + ".png", "image/png",
+                                        pngPath, aByte, 
+                                        "TWiki Draw PNG file");
+                }
             
+                if (bPostEnabled && gifPath != null)
+                {
+                    // then create *.gif image and upload file
+                    showStatus("Saving " + baseName + ".gif");
+                    final byte[] aByte = convertToGif(oImgBuffer);
             // upload *.gif file
-            if (bPostEnabled)
-                savedGif = app.post(
-                                    savePath, "", "image/gif",
-                                    gifPath, String.valueOf(aChar, 0, aChar.length),
+                    savedGif = app.post(savePath, baseName + ".gif", "image/gif",
+                                        gifPath, aByte,
                                     "TWiki Draw GIF file");
+                }
+            }
         } catch (MalformedURLException e) {
             this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
             showStatus("Bad Wiki servlet URL: "+e.getMessage());
@@ -506,7 +528,8 @@
         this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
         showStatus("Saved .draw " + (savedDraw ? "OK" : "Failed") +
                    " .map " + (savedMap ? "OK" : "Failed") +
-                   " .gif " + (savedGif ? "OK" : "Failed"));
+                   " .gif " + (savedGif ? "OK" : "Failed") +
+                   " .png " + (savedPng ? "OK" : "Failed"));
         return savedDraw;
     }
     
@@ -523,12 +546,11 @@
     	System.err.println("TWikiDraw:" + msg);
     }
     
-    /**
-     * convert Image to GIF-encoded data, reducing the number of colors
-     * if needed. Added by Bertrand Delacretaz
-     */
-    private char [] convertToGif(Image oImgBuffer) throws IOException {
-        debug("converting data to GIF...");
+    private Image createImage(Dimension d, int iBorder) {
+        // clear the selection so it doesn't appear
+        view().clearSelection();
+        final Image oImgBuffer =
+           this.view().createImage(d.width + iBorder, d.height + iBorder);
         Graphics oGrf = oImgBuffer.getGraphics();
         this.view().enableGuides(false);
         this.view().drawAll(oGrf);
@@ -539,8 +561,16 @@
         //tf.setImage(oImgBuffer);
         //tf.show();
 		
-        ByteArrayOutputStream oOut = null;
+        return oImgBuffer;
+    }
 		
+    /**
+     * convert Image to GIF-encoded data, reducing the number of colors
+     * if needed. Added by Bertrand Delacretaz
+     */
+    private byte [] convertToGif(Image oImgBuffer) throws IOException {
+        debug("converting data to GIF...");
+        ByteArrayOutputStream oOut = null;
         try {
             oOut = new ByteArrayOutputStream();
             new GifEncoder(oImgBuffer,oOut).encode();
@@ -555,12 +585,19 @@
         }
         
         byte[] aByte = oOut.toByteArray();
-        int size = oOut.size();
-        char[] aChar = new char[size];
-        for (int i = 0; i < size; i++) {
-            aChar[i] = (char)aByte[i];
-        }
         debug("conversion to GIF successful.");
-        return aChar;
+        return aByte;
+    }
+
+    /**
+     * convert Image to PNG-encoded data
+     * Added by OliverGraf
+     */
+    private byte [] convertToPng(Image oImgBuffer) throws IOException {
+        debug("converting data to PNG...");
+        PngEncoderIndexed oEncode = new PngEncoderIndexed(oImgBuffer);
+        byte[] aByte = oEncode.pngEncode();
+        debug("conversion to PNG successful."); 
+        return aByte;
     }
 }
diff -urP --ignore-space-change orig/src/CH/ifa/draw/util/StorableInput.java moin-utf8/src/CH/ifa/draw/util/StorableInput.java
--- orig/src/CH/ifa/draw/util/StorableInput.java	2004-11-22 16:00:00.000000000 +0000
+++ moin-utf8/src/CH/ifa/draw/util/StorableInput.java	2005-11-27 23:46:28.000000000 +0000
@@ -27,8 +27,12 @@
      * Initializes a Storable input with the given input stream.
      */
     public StorableInput(InputStream stream) {
-        Reader r = new BufferedReader(new InputStreamReader(stream));
+        try {
+            Reader r = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
         fTokenizer = new StreamTokenizer(r);
+        } catch(UnsupportedEncodingException ex) {
+            throw new RuntimeException(ex.getMessage());
+        }
         fMap = new Vector();
     }
 
@@ -68,7 +72,7 @@
     public String readString() throws IOException {
         int token = fTokenizer.nextToken();
         if (token == StreamTokenizer.TT_WORD || token == '"') {
-            return unescapeUnicode(fTokenizer.sval);
+            return fTokenizer.sval;
         }
 
         String msg = "String expected in line: " + fTokenizer.lineno();
diff -urP --ignore-space-change orig/src/CH/ifa/draw/util/StorableOutput.java moin-utf8/src/CH/ifa/draw/util/StorableOutput.java
--- orig/src/CH/ifa/draw/util/StorableOutput.java	2004-11-22 16:01:38.000000000 +0000
+++ moin-utf8/src/CH/ifa/draw/util/StorableOutput.java	2005-11-27 23:41:16.000000000 +0000
@@ -28,7 +28,12 @@
      * Initializes the StorableOutput with the given output stream.
      */
     public StorableOutput(OutputStream stream) {
-        fStream = new PrintWriter(stream);
+        try {
+            fStream = new PrintWriter(new OutputStreamWriter(stream, "UTF-8"));
+        } catch(UnsupportedEncodingException ex) {
+            throw new RuntimeException(ex.getMessage());
+        }
+
         fMap = new Vector();
         fIndent = 0;
     }
@@ -100,27 +105,14 @@
         for(int i = 0; i < s.length(); i++) {
             char c = s.charAt(i);
             switch(c) {
-                // RobWalker 17 Jul 2003 - suppress \r
-            case '\r': break;
+            case '\r': fStream.print('\\'); fStream.print('r'); break;
             case '\n': fStream.print('\\'); fStream.print('n'); break;
             case '"' : fStream.print('\\'); fStream.print('"'); break;
             case '\\': fStream.print('\\'); fStream.print('\\'); break;
-            case '\t': fStream.print('\\'); fStream.print('\t'); break;
-            default:
-                if ((c >= 0x0001) && (c <= 0x007F)) {
-                    fStream.print(c);
-                } else {
-                    String hex = Integer.toHexString(c);
-                    switch (hex.length()) {
-                    case 1:  fStream.print("\\\\u000" + hex); break;
-                    case 2:  fStream.print("\\\\u00" + hex); break;
-                    case 3:  fStream.print("\\\\u0" + hex); break;
-                    default: fStream.print("\\\\u" + hex); break;
-                    }
+            case '\t': fStream.print('\\'); fStream.print('t'); break;
+            default: fStream.print(c);
 	            }
             }
-
-        }
         fStream.print('"');
         space();
     }
--- orig/src/CH/ifa/draw/twiki/StandAlone.java	2005-03-08 18:10:00.000000000 +0000
+++ moin-utf8/src/CH/ifa/draw/twiki/StandAlone.java	2005-11-28 22:11:50.000000000 +0000
@@ -62,13 +62,13 @@
                         String fileName,
                         String type,
                         String path,
-                        String content,
+                        byte[] content,
                         String comment) {
         System.out.println("Post URL " + url +
                            " fileName " + fileName +
                            " type " + type +
                            " path " + path +
-                           " content " + content +
+                           " content " + new String(content) +
                            " comment " + comment);
         return false;
     }
