Merge branch 'unix' of https://github.com/CendioOssman/tigervnc
diff --git a/common/rdr/TLSException.cxx b/common/rdr/TLSException.cxx
index bf8e97a..0f75a4d 100644
--- a/common/rdr/TLSException.cxx
+++ b/common/rdr/TLSException.cxx
@@ -34,7 +34,7 @@
 
 #ifdef HAVE_GNUTLS
 TLSException::TLSException(const char* s, int err_)
-  : Exception("%s: %s (%d)", s, gnutls_strerror(err), err), err(err_)
+  : Exception("%s: %s (%d)", s, gnutls_strerror(err_), err_), err(err_)
 {
 }
 #endif /* HAVE_GNUTLS */
diff --git a/common/rfb/Congestion.cxx b/common/rfb/Congestion.cxx
index 4d36d9f..8162808 100644
--- a/common/rfb/Congestion.cxx
+++ b/common/rfb/Congestion.cxx
@@ -68,6 +68,11 @@
 // limit for now...
 static const unsigned MAXIMUM_WINDOW = 4194304;
 
+// Compare position even when wrapped around
+static inline bool isAfter(unsigned a, unsigned b) {
+  return (int)a - (int)b > 0;
+}
+
 static LogWriter vlog("Congestion");
 
 Congestion::Congestion() :
@@ -230,7 +235,7 @@
   targetAcked = lastPosition - congWindow;
 
   // Simple case?
-  if (lastPong.pos > targetAcked)
+  if (isAfter(lastPong.pos, targetAcked))
     return 0;
 
   // No measurements yet?
@@ -269,7 +274,7 @@
       etaNext -= delay;
 
     // Found it?
-    if (curPing.pos > targetAcked) {
+    if (isAfter(curPing.pos, targetAcked)) {
       eta += etaNext * (curPing.pos - targetAcked) / (curPing.pos - prevPing->pos);
       if (elapsed > eta)
         return 0;
diff --git a/common/rfb/DecodeManager.cxx b/common/rfb/DecodeManager.cxx
index ccf084f..c509db0 100644
--- a/common/rfb/DecodeManager.cxx
+++ b/common/rfb/DecodeManager.cxx
@@ -64,6 +64,12 @@
       vlog.info("Creating %d decoder thread(s)", (int)cpuCount);
   }
 
+  if (cpuCount == 1) {
+    // Threads are not used on single CPU machines
+    freeBuffers.push_back(new rdr::MemOutStream());
+    return;
+  }
+
   while (cpuCount--) {
     // Twice as many possible entries in the queue as there
     // are worker threads to make sure they don't stall
@@ -123,7 +129,7 @@
 
   // Fast path for single CPU machines to avoid the context
   // switching overhead
-  if (threads.size() == 1) {
+  if (threads.empty()) {
     bufferStream = freeBuffers.front();
     bufferStream->clear();
     decoder->readRect(r, conn->getInStream(), conn->cp, bufferStream);
@@ -271,7 +277,7 @@
       entry->decoder->decodeRect(entry->rect, entry->bufferStream->data(),
                                  entry->bufferStream->length(),
                                  *entry->cp, entry->pb);
-    } catch (rdr::Exception e) {
+    } catch (rdr::Exception& e) {
       manager->setThreadException(e);
     } catch(...) {
       assert(false);
diff --git a/common/rfb/HTTPServer.cxx b/common/rfb/HTTPServer.cxx
index 54becbb..2895a69 100644
--- a/common/rfb/HTTPServer.cxx
+++ b/common/rfb/HTTPServer.cxx
@@ -125,7 +125,7 @@
     while (1) {
       os.writeU8(is.readU8());
     }
-  } catch (rdr::EndOfStream) {
+  } catch (rdr::EndOfStream&) {
   }
 }
 
diff --git a/common/rfb/ScreenSet.h b/common/rfb/ScreenSet.h
index ad340c2..9680b6e 100644
--- a/common/rfb/ScreenSet.h
+++ b/common/rfb/ScreenSet.h
@@ -126,11 +126,23 @@
       }
     };
 
-    // FIXME: List order shouldn't matter
-    inline bool operator==(const ScreenSet& r) const { return screens == r.screens; }
-    inline bool operator!=(const ScreenSet& r) const { return screens != r.screens; }
+    inline bool operator==(const ScreenSet& r) const {
+      std::list<Screen> a = screens;
+      a.sort(compare_screen);
+      std::list<Screen> b = r.screens;
+      b.sort(compare_screen);
+      return a == b;
+    };
+    inline bool operator!=(const ScreenSet& r) const { return !operator==(r); }
 
     std::list<Screen> screens;
+
+  private:
+    static inline bool compare_screen(const Screen& first, const Screen& second)
+    {
+      return first.id < second.id;
+    }
+
   };
 
 };
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index 95870c9..8cc04f7 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -316,9 +316,11 @@
     return;
   }
 
+  // Assume the framebuffer contents wasn't saved and reset everything
+  // that tracks its contents
   comparer = new ComparingUpdateTracker(pb);
   renderedCursorInvalid = true;
-  startFrameClock();
+  add_changed(pb->getRect());
 
   // Make sure that we have at least one screen
   if (screenLayout.num_screens() == 0)
@@ -539,9 +541,13 @@
   if (!desktopStarted) {
     slog.debug("starting desktop");
     desktop->start(this);
-    desktopStarted = true;
     if (!pb)
       throw Exception("SDesktop::start() did not set a valid PixelBuffer");
+    desktopStarted = true;
+    // The tracker might have accumulated changes whilst we were
+    // stopped, so flush those out
+    if (!comparer->is_empty())
+      writeUpdate();
   }
 }
 
diff --git a/java/com/tigervnc/vncviewer/VncViewer.java b/java/com/tigervnc/vncviewer/VncViewer.java
index 566169b..93d3f3b 100644
--- a/java/com/tigervnc/vncviewer/VncViewer.java
+++ b/java/com/tigervnc/vncviewer/VncViewer.java
@@ -208,6 +208,8 @@
       vncServerName.put(argv[i].toCharArray()).flip();
     }
 
+    // Check if the server name in reality is a configuration file
+    potentiallyLoadConfigurationFile(vncServerName);
   }
 
   public static void usage() {
@@ -215,6 +217,7 @@
                     "[host:displayNum]\n"+
                     "       vncviewer [options/parameters] -listen [port] "+
                     "[options/parameters]\n"+
+                    "       vncviewer [options/parameters] [.tigervnc file]\n"+
                     "\n"+
                     "Options:\n"+
                     "  -log <level>    configure logging level\n"+
@@ -277,6 +280,27 @@
     System.exit(1);
   }
 
+  public static void potentiallyLoadConfigurationFile(CharBuffer vncServerName) {
+    String serverName = vncServerName.toString();
+    boolean hasPathSeparator = (serverName.indexOf('/') != -1 ||
+                                (serverName.indexOf('\\')) != -1);
+
+    if (hasPathSeparator) {
+      try {
+        serverName = loadViewerParameters(vncServerName.toString());
+        if (serverName == "") {
+          vlog.info("Unable to load the server name from given file");
+          System.exit(1);
+        }
+        vncServerName.clear();
+        vncServerName.put(serverName).flip();
+      } catch (com.tigervnc.rfb.Exception e) {
+        vlog.info(e.getMessage());
+        System.exit(1);
+      }
+    }
+  }
+
   public static void newViewer() {
     String cmd = "java -jar ";
     try {
diff --git a/po/eo.po b/po/eo.po
index 3ca4bf9..6d07526 100644
--- a/po/eo.po
+++ b/po/eo.po
@@ -1,21 +1,21 @@
 # Esperanto translation
-# Copyright (C) 2015, 2016 the TigerVNC Team (msgids)
+# Copyright (C) 2015, 2016, 2018 the TigerVNC Team (msgids)
 # This file is distributed under the same license as the tigervnc package.
-# Felipe Castro <fefcas@gmail.com>, 2015, 2016.
+# Felipe Castro <fefcas@gmail.com>, 2015, 2016, 2018.
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: tigervnc 1.6.90\n"
+"Project-Id-Version: tigervnc 1.7.90\n"
 "Report-Msgid-Bugs-To: tigervnc-devel@googlegroups.com\n"
-"POT-Creation-Date: 2016-07-01 10:15+0000\n"
-"PO-Revision-Date: 2016-10-15 21:00-0300\n"
+"POT-Creation-Date: 2017-04-19 13:05+0000\n"
+"PO-Revision-Date: 2018-05-14 21:23-0300\n"
 "Last-Translator: Felipe Castro <fefcas@gmail.com>\n"
 "Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
 "Language: eo\n"
-"X-Bugs: Report translation errors to the Language-Team address.\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
 "X-Generator: Poedit 1.5.4\n"
 
 #: vncviewer/CConn.cxx:110
@@ -73,81 +73,77 @@
 msgid "Security method: %s"
 msgstr "Sekureca metodo: %s"
 
-#: vncviewer/CConn.cxx:319
+#: vncviewer/CConn.cxx:343
 #, c-format
 msgid "SetDesktopSize failed: %d"
 msgstr "SetDesktopSize fiaskis: %d"
 
-#: vncviewer/CConn.cxx:411
+#: vncviewer/CConn.cxx:413
 msgid "Invalid SetColourMapEntries from server!"
 msgstr "Malvalida SetColourMapEntries el servilo!"
 
-#: vncviewer/CConn.cxx:485
+#: vncviewer/CConn.cxx:489
 msgid "Enabling continuous updates"
 msgstr "Ebligo de daŭrigaj ĝisdatigoj"
 
-#: vncviewer/CConn.cxx:555
+#: vncviewer/CConn.cxx:559
 #, c-format
 msgid "Throughput %d kbit/s - changing to quality %d"
 msgstr "Traigo %d kbit/s - ni ŝanĝas al kvalito %d"
 
-#: vncviewer/CConn.cxx:577
+#: vncviewer/CConn.cxx:581
 #, c-format
 msgid "Throughput %d kbit/s - full color is now %s"
 msgstr "Traigo %d kbit/s - plenkoloro nun estas %s"
 
-#: vncviewer/CConn.cxx:579
+#: vncviewer/CConn.cxx:583
 msgid "disabled"
 msgstr "malebligita"
 
-#: vncviewer/CConn.cxx:579
+#: vncviewer/CConn.cxx:583
 msgid "enabled"
 msgstr "ebligita"
 
-#: vncviewer/CConn.cxx:589
+#: vncviewer/CConn.cxx:593
 #, c-format
 msgid "Using %s encoding"
 msgstr "Ni uzas enkodigon %s"
 
-#: vncviewer/CConn.cxx:636
+#: vncviewer/CConn.cxx:640
 #, c-format
 msgid "Using pixel format %s"
 msgstr "Ni uzas bilderformon %s"
 
-#: vncviewer/DesktopWindow.cxx:106
+#: vncviewer/DesktopWindow.cxx:121
 msgid "Invalid geometry specified!"
 msgstr "Malvalida geometrio indikita!"
 
-#: vncviewer/DesktopWindow.cxx:303
+#: vncviewer/DesktopWindow.cxx:434
 msgid "Adjusting window size to avoid accidental full screen request"
 msgstr "Alĝustigo de fenestra grando por eviti akcidentan plenekranan peton"
 
-#: vncviewer/DesktopWindow.cxx:485 vncviewer/DesktopWindow.cxx:491
-#: vncviewer/DesktopWindow.cxx:504
+#: vncviewer/DesktopWindow.cxx:478
+#, c-format
+msgid "Press %s to open the context menu"
+msgstr "Premu %s por malfermi la kuntekstan menuon"
+
+#: vncviewer/DesktopWindow.cxx:741 vncviewer/DesktopWindow.cxx:747
+#: vncviewer/DesktopWindow.cxx:760
 msgid "Failure grabbing keyboard"
 msgstr "Fiasko dum elpreno de klavaro"
 
-#: vncviewer/DesktopWindow.cxx:516
+#: vncviewer/DesktopWindow.cxx:772
 msgid "Failure grabbing mouse"
 msgstr "Fiasko dum elpreno de muso"
 
-#: vncviewer/DesktopWindow.cxx:746
+#: vncviewer/DesktopWindow.cxx:1002
 msgid "Invalid screen layout computed for resize request!"
 msgstr "Malvalida ekrana aranĝo komputita por regrandiga peto!"
 
-#: vncviewer/FLTKPixelBuffer.cxx:33 vncviewer/OSXPixelBuffer.cxx:48
-#: vncviewer/X11PixelBuffer.cxx:117
+#: vncviewer/FLTKPixelBuffer.cxx:33
 msgid "Not enough memory for framebuffer"
 msgstr "Ne sufiĉe da memoro por frambufro"
 
-#: vncviewer/OSXPixelBuffer.cxx:52
-msgid "Could not create framebuffer device"
-msgstr "Ne eblis krei frambufran aparaton"
-
-#: vncviewer/OSXPixelBuffer.cxx:58
-msgid "Could not create framebuffer bitmap"
-msgstr "Ne eblis krei frambufran bitmapon"
-
 #: vncviewer/OptionsDialog.cxx:57
 msgid "VNC Viewer: Connection Options"
 msgstr "Rigardilo VNC: konektaj preferoj"
@@ -218,7 +214,7 @@
 msgstr "Ĉifrado"
 
 #: vncviewer/OptionsDialog.cxx:604 vncviewer/OptionsDialog.cxx:657
-#: vncviewer/OptionsDialog.cxx:735
+#: vncviewer/OptionsDialog.cxx:737
 msgid "None"
 msgstr "Nenio"
 
@@ -262,55 +258,55 @@
 msgid "Accept clipboard from server"
 msgstr "Akcepti tondaĵon el la servilo"
 
-#: vncviewer/OptionsDialog.cxx:709
+#: vncviewer/OptionsDialog.cxx:710
 msgid "Also set primary selection"
 msgstr "Difini ankaŭ la ĉefan elekton"
 
-#: vncviewer/OptionsDialog.cxx:716
+#: vncviewer/OptionsDialog.cxx:717
 msgid "Send clipboard to server"
 msgstr "Sendi tondaĵon al la servilo"
 
-#: vncviewer/OptionsDialog.cxx:723
+#: vncviewer/OptionsDialog.cxx:725
 msgid "Send primary selection as clipboard"
 msgstr "Sendi ĉefan elekton kiel tondajô"
 
-#: vncviewer/OptionsDialog.cxx:730
+#: vncviewer/OptionsDialog.cxx:732
 msgid "Pass system keys directly to server (full screen)"
 msgstr "Pasi sistemajn klavojn rekte al la servilo (plenekrane)"
 
-#: vncviewer/OptionsDialog.cxx:733
+#: vncviewer/OptionsDialog.cxx:735
 msgid "Menu key"
 msgstr "Menu-klavo"
 
-#: vncviewer/OptionsDialog.cxx:749
+#: vncviewer/OptionsDialog.cxx:751
 msgid "Screen"
 msgstr "Ekrano"
 
-#: vncviewer/OptionsDialog.cxx:757
+#: vncviewer/OptionsDialog.cxx:759
 msgid "Resize remote session on connect"
 msgstr "Regrandigi foran seancon dum konekto"
 
-#: vncviewer/OptionsDialog.cxx:770
+#: vncviewer/OptionsDialog.cxx:772
 msgid "Resize remote session to the local window"
 msgstr "Regrandigi foran seancon al la loka fenestro"
 
-#: vncviewer/OptionsDialog.cxx:776
+#: vncviewer/OptionsDialog.cxx:778
 msgid "Full-screen mode"
 msgstr "Plenekrana reĝimo"
 
-#: vncviewer/OptionsDialog.cxx:782
+#: vncviewer/OptionsDialog.cxx:784
 msgid "Enable full-screen mode over all monitors"
 msgstr "Ebligi plenekranan reĝimon en ĉiuj ekranoj"
 
-#: vncviewer/OptionsDialog.cxx:791
+#: vncviewer/OptionsDialog.cxx:793
 msgid "Misc."
 msgstr "Divers."
 
-#: vncviewer/OptionsDialog.cxx:799
+#: vncviewer/OptionsDialog.cxx:801
 msgid "Shared (don't disconnect other viewers)"
 msgstr "Kunhave (ne malkonekti aliajn rigardilojn)"
 
-#: vncviewer/OptionsDialog.cxx:805
+#: vncviewer/OptionsDialog.cxx:807
 msgid "Show dot when no cursor"
 msgstr "Montri punkton kiam sen kursoro"
 
@@ -362,156 +358,106 @@
 msgid "Username:"
 msgstr "Uzantnomo:"
 
-#: vncviewer/Viewport.cxx:391
-#, c-format
-msgid "Unable to create platform specific framebuffer: %s"
-msgstr "Ne eblas krei frambufron specifan de platformo: %s"
-
-#: vncviewer/Viewport.cxx:392
-msgid "Using platform independent framebuffer"
-msgstr "Ni uzas frambufron sendependan de platformo"
-
-#: vncviewer/Viewport.cxx:628
+#: vncviewer/Viewport.cxx:586
 #, c-format
 msgid "No scan code for extended virtual key 0x%02x"
 msgstr "Neniu skankodo por kroma virtuala klavo 0x%02x"
 
-#: vncviewer/Viewport.cxx:630
+#: vncviewer/Viewport.cxx:588
 #, c-format
 msgid "No scan code for virtual key 0x%02x"
 msgstr "Neniu skankodo por virtuala klavo 0x%02x"
 
-#: vncviewer/Viewport.cxx:647
+#: vncviewer/Viewport.cxx:605
 #, c-format
 msgid "No symbol for extended virtual key 0x%02x"
 msgstr "Neniu simbolo por kroma virtuala klavo 0x%02x"
 
-#: vncviewer/Viewport.cxx:649
+#: vncviewer/Viewport.cxx:607
 #, c-format
 msgid "No symbol for virtual key 0x%02x"
 msgstr "Neniu simbolo por virtuala klavo 0x%02x"
 
-#: vncviewer/Viewport.cxx:687
+#: vncviewer/Viewport.cxx:645
 #, c-format
 msgid "No symbol for key code 0x%02x (in the current state)"
 msgstr "Neniu simbolo por klavkodo 0x%02x (en la nuna stato)"
 
-#: vncviewer/Viewport.cxx:713
+#: vncviewer/Viewport.cxx:671
 #, c-format
 msgid "No symbol for key code %d (in the current state)"
 msgstr "Neniu simbolo por klavkodo %d (en la nuna stato)"
 
-#: vncviewer/Viewport.cxx:750
+#: vncviewer/Viewport.cxx:708
 msgctxt "ContextMenu|"
 msgid "E&xit viewer"
 msgstr "E&liri la rigardilon"
 
-#: vncviewer/Viewport.cxx:753
+#: vncviewer/Viewport.cxx:711
 msgctxt "ContextMenu|"
 msgid "&Full screen"
 msgstr "&Plena ekrano"
 
-#: vncviewer/Viewport.cxx:756
+#: vncviewer/Viewport.cxx:714
 msgctxt "ContextMenu|"
 msgid "Minimi&ze"
 msgstr "Mal&grandigi"
 
-#: vncviewer/Viewport.cxx:758
+#: vncviewer/Viewport.cxx:716
 msgctxt "ContextMenu|"
 msgid "Resize &window to session"
 msgstr "Regrandigi &fenestron al seanco"
 
-#: vncviewer/Viewport.cxx:763
+#: vncviewer/Viewport.cxx:721
 msgctxt "ContextMenu|"
 msgid "&Ctrl"
 msgstr "&Stirklavo"
 
-#: vncviewer/Viewport.cxx:766
+#: vncviewer/Viewport.cxx:724
 msgctxt "ContextMenu|"
 msgid "&Alt"
 msgstr "&Alt"
 
-#: vncviewer/Viewport.cxx:772
+#: vncviewer/Viewport.cxx:730
 #, c-format
 msgctxt "ContextMenu|"
 msgid "Send %s"
 msgstr "Sendi %s"
 
-#: vncviewer/Viewport.cxx:778
+#: vncviewer/Viewport.cxx:736
 msgctxt "ContextMenu|"
 msgid "Send Ctrl-Alt-&Del"
 msgstr "Sendi Ctrl-Alt-&Del"
 
-#: vncviewer/Viewport.cxx:781
+#: vncviewer/Viewport.cxx:739
 msgctxt "ContextMenu|"
 msgid "&Refresh screen"
 msgstr "A&ktualigi ekranon"
 
-#: vncviewer/Viewport.cxx:784
+#: vncviewer/Viewport.cxx:742
 msgctxt "ContextMenu|"
 msgid "&Options..."
 msgstr "&Modifiloj..."
 
-#: vncviewer/Viewport.cxx:786
+#: vncviewer/Viewport.cxx:744
 msgctxt "ContextMenu|"
 msgid "Connection &info..."
 msgstr "&Informo pri konekto..."
 
-#: vncviewer/Viewport.cxx:788
+#: vncviewer/Viewport.cxx:746
 msgctxt "ContextMenu|"
 msgid "About &TigerVNC viewer..."
 msgstr "Pri la rigardilo &TigerVNC..."
 
-#: vncviewer/Viewport.cxx:791
+#: vncviewer/Viewport.cxx:749
 msgctxt "ContextMenu|"
 msgid "Dismiss &menu"
 msgstr "Forlasi la me&nuon"
 
-#: vncviewer/Viewport.cxx:875
+#: vncviewer/Viewport.cxx:833
 msgid "VNC connection info"
 msgstr "Konekta informo de VNC"
 
-#: vncviewer/Win32PixelBuffer.cxx:62
-msgid "unable to create DIB section"
-msgstr "ne eblas krei sekcion DIB"
-
-#: vncviewer/Win32PixelBuffer.cxx:79
-msgid "CreateCompatibleDC failed"
-msgstr "CreateCompatibleDC malsukcesis"
-
-#: vncviewer/Win32PixelBuffer.cxx:82
-msgid "SelectObject failed"
-msgstr "SelectObject fiaskis"
-
-#: vncviewer/Win32PixelBuffer.cxx:91
-msgid "BitBlt failed"
-msgstr "BitBlt malsukcesis"
-
-#. TRANSLATORS: "pixmap" is an X11 concept and may not be suitable
-#. to translate.
-#: vncviewer/X11PixelBuffer.cxx:65
-msgid "Display lacks pixmap format for default depth"
-msgstr "Montri la bildermapan formon \"lacks\" por apriora profundo"
-
-#. TRANSLATORS: "pixmap" is an X11 concept and may not be suitable
-#. to translate.
-#: vncviewer/X11PixelBuffer.cxx:76
-msgid "Couldn't find suitable pixmap format"
-msgstr "Ne eblis trovi taŭgan bildermapan formon"
-
-#: vncviewer/X11PixelBuffer.cxx:85
-msgid "Only true colour displays supported"
-msgstr "Nur verŝajn-koloraj rigardiloj estas subtenataj"
-
-#: vncviewer/X11PixelBuffer.cxx:87
-#, c-format
-msgid "Using default colormap and visual, TrueColor, depth %d."
-msgstr "Ni uzas aprioran kolormapon kaj ŝajnon, 'TrueColor', profundo %d."
-
-#: vncviewer/X11PixelBuffer.cxx:113
-msgid "Could not create framebuffer image"
-msgstr "Ne eblis krei frambufran bildon"
-
 #: vncviewer/parameters.cxx:286 vncviewer/parameters.cxx:320
 #, c-format
 msgid "The name of the parameter %s was too large to write to the registry"
@@ -711,6 +657,45 @@
 msgid "Listening on port %d"
 msgstr "Ni aŭskultas pordon %d"
 
+#~ msgid "Could not create framebuffer device"
+#~ msgstr "Ne eblis krei frambufran aparaton"
+
+#~ msgid "Could not create framebuffer bitmap"
+#~ msgstr "Ne eblis krei frambufran bitmapon"
+
+#~ msgid "Unable to create platform specific framebuffer: %s"
+#~ msgstr "Ne eblas krei frambufron specifan de platformo: %s"
+
+#~ msgid "Using platform independent framebuffer"
+#~ msgstr "Ni uzas frambufron sendependan de platformo"
+
+#~ msgid "unable to create DIB section"
+#~ msgstr "ne eblas krei sekcion DIB"
+
+#~ msgid "CreateCompatibleDC failed"
+#~ msgstr "CreateCompatibleDC malsukcesis"
+
+#~ msgid "SelectObject failed"
+#~ msgstr "SelectObject fiaskis"
+
+#~ msgid "BitBlt failed"
+#~ msgstr "BitBlt malsukcesis"
+
+#~ msgid "Display lacks pixmap format for default depth"
+#~ msgstr "Montri la bildermapan formon \"lacks\" por apriora profundo"
+
+#~ msgid "Couldn't find suitable pixmap format"
+#~ msgstr "Ne eblis trovi taŭgan bildermapan formon"
+
+#~ msgid "Only true colour displays supported"
+#~ msgstr "Nur verŝajn-koloraj rigardiloj estas subtenataj"
+
+#~ msgid "Using default colormap and visual, TrueColor, depth %d."
+#~ msgstr "Ni uzas aprioran kolormapon kaj ŝajnon, 'TrueColor', profundo %d."
+
+#~ msgid "Could not create framebuffer image"
+#~ msgstr "Ne eblis krei frambufran bildon"
+
 #~ msgid "Alt"
 #~ msgstr "Alt-klavo"
 
diff --git a/tests/decperf.cxx b/tests/decperf.cxx
index 3b929a4..9061cb5 100644
--- a/tests/decperf.cxx
+++ b/tests/decperf.cxx
@@ -142,7 +142,7 @@
 
   try {
     cc = new CConn(fn);
-  } catch (rdr::Exception e) {
+  } catch (rdr::Exception& e) {
     fprintf(stderr, "Failed to open rfb file: %s\n", e.str());
     exit(1);
   }
@@ -150,8 +150,8 @@
   try {
     while (true)
       cc->processMsg();
-  } catch (rdr::EndOfStream e) {
-  } catch (rdr::Exception e) {
+  } catch (rdr::EndOfStream& e) {
+  } catch (rdr::Exception& e) {
     fprintf(stderr, "Failed to run rfb file: %s\n", e.str());
     exit(1);
   }
diff --git a/tests/encperf.cxx b/tests/encperf.cxx
index 7b9ff81..4e7038f 100644
--- a/tests/encperf.cxx
+++ b/tests/encperf.cxx
@@ -342,7 +342,7 @@
 
   try {
     cc = new CConn(fn);
-  } catch (rdr::Exception e) {
+  } catch (rdr::Exception& e) {
     fprintf(stderr, "Failed to open rfb file: %s\n", e.str());
     exit(1);
   }
@@ -350,8 +350,8 @@
   try {
     while (true)
       cc->processMsg();
-  } catch (rdr::EndOfStream e) {
-  } catch (rdr::Exception e) {
+  } catch (rdr::EndOfStream& e) {
+  } catch (rdr::Exception& e) {
     fprintf(stderr, "Failed to run rfb file: %s\n", e.str());
     exit(1);
   }
diff --git a/unix/vncpasswd/vncpasswd.cxx b/unix/vncpasswd/vncpasswd.cxx
index 16c925e..8bd4e48 100644
--- a/unix/vncpasswd/vncpasswd.cxx
+++ b/unix/vncpasswd/vncpasswd.cxx
@@ -67,18 +67,28 @@
   return 0;
 }
 
-// Reads password from stdin and prints encrypted password to stdout.
+// Reads passwords from stdin and prints encrypted passwords to stdout.
 static int encrypt_pipe() {
-  char *result = getpassword(NULL);
-  if (result) {
+  int i;
+
+  // We support a maximum of two passwords right now
+  for (i = 0;i < 2;i++) {
+    char *result = getpassword(NULL);
+    if (!result)
+      break;
+
     ObfuscatedPasswd obfuscated(result);
     if (fwrite(obfuscated.buf, obfuscated.length, 1, stdout) != 1) {
       fprintf(stderr,"Writing to stdout failed\n");
       return 1;
     }
-    return 0;
   }
-  else return 1;
+
+  // Did we fail to produce even one password?
+  if (i == 0)
+    return 1;
+
+  return 0;
 }
 
 static ObfuscatedPasswd* readpassword() {
diff --git a/unix/vncpasswd/vncpasswd.man b/unix/vncpasswd/vncpasswd.man
index e9250fd..a62c0ed 100644
--- a/unix/vncpasswd/vncpasswd.man
+++ b/unix/vncpasswd/vncpasswd.man
@@ -32,6 +32,9 @@
 version to stdout.  Note that in filter mode, short or even empty passwords
 will be silently accepted.
 
+A view-only password must be separated from the normal password by a newline
+character.
+
 
 .SH FILES
 .TP
diff --git a/unix/x0vncserver/RandrGlue.c b/unix/x0vncserver/RandrGlue.c
index 2e47763..ff12902 100644
--- a/unix/x0vncserver/RandrGlue.c
+++ b/unix/x0vncserver/RandrGlue.c
@@ -468,6 +468,7 @@
       }
 
       crtcid = output->crtcs[i];
+      crtc->rotation = RR_Rotate_0;
       break;
     }
   } else {
diff --git a/vncviewer/parameters.cxx b/vncviewer/parameters.cxx
index d24e5bc..51cce3d 100644
--- a/vncviewer/parameters.cxx
+++ b/vncviewer/parameters.cxx
@@ -190,44 +190,35 @@
   const char first;
   const char second;
 } replaceMap[] = { { '\n', 'n' },
-                   { '\r', 'r' } };
+                   { '\r', 'r' },
+                   { '\\', '\\' } };
 
 static bool encodeValue(const char* val, char* dest, size_t destSize) {
 
-  bool normalCharacter = true;
   size_t pos = 0;
 
   for (size_t i = 0; (val[i] != '\0') && (i < (destSize - 1)); i++) {
+    bool normalCharacter;
     
     // Check for sequences which will need encoding
-    if (val[i] == '\\') {
+    normalCharacter = true;
+    for (size_t j = 0; j < sizeof(replaceMap)/sizeof(replaceMap[0]); j++) {
 
-      strncpy(dest+pos, "\\\\", 2);
-      pos++;
-      if (pos >= destSize)
-        return false;
+      if (val[i] == replaceMap[j].first) {
+        dest[pos] = '\\';
+        pos++;
+        if (pos >= destSize)
+          return false;
 
-    } else {
+        dest[pos] = replaceMap[j].second;
+        normalCharacter = false;
+        break;
+      }
 
-      for (size_t j = 0; j < sizeof(replaceMap)/sizeof(replaceMap[0]); j++) {
-
-        if (val[i] == replaceMap[j].first) {
-          dest[pos] = '\\';
-          pos++;
-          if (pos >= destSize)
-            return false;
-
-          dest[pos] = replaceMap[j].second;
-          normalCharacter = false;
-          break;
-        }
-
-        if (normalCharacter) {
-          dest[pos] = val[i];
-        }
+      if (normalCharacter) {
+        dest[pos] = val[i];
       }
     }
-    normalCharacter = true; // Reset for next loop
 
     pos++;
     if (pos >= destSize)
@@ -242,36 +233,30 @@
 static bool decodeValue(const char* val, char* dest, size_t destSize) {
 
   size_t pos = 0;
-  bool escapedCharacter = false;
   
   for (size_t i = 0; (val[i] != '\0') && (i < (destSize - 1)); i++) {
     
     // Check for escape sequences
     if (val[i] == '\\') {
+      bool escapedCharacter;
       
+      escapedCharacter = false;
       for (size_t j = 0; j < sizeof(replaceMap)/sizeof(replaceMap[0]); j++) {
         if (val[i+1] == replaceMap[j].second) {
           dest[pos] = replaceMap[j].first;
           escapedCharacter = true;
-          pos--;
+          i++;
           break;
         }
       }
 
-      if (!escapedCharacter) {
-        if (val[i+1] == '\\') {
-          dest[pos] = val[i];
-          i++;
-        } else {
-          return false;
-        }
-      }
+      if (!escapedCharacter)
+        return false;
 
     } else {
       dest[pos] = val[i];
     }
 
-    escapedCharacter = false; // Reset for next loop
     pos++;
     if (pos >= destSize) {
       return false;
@@ -555,6 +540,8 @@
   char decodingBuffer[buffersize];
   static char servername[sizeof(line)];
 
+  memset(servername, '\0', sizeof(servername));
+
   // Load from the registry or a predefined file if no filename was specified.
   if(filename == NULL) {
 
diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx
index f22648d..6c0c738 100644
--- a/vncviewer/vncviewer.cxx
+++ b/vncviewer/vncviewer.cxx
@@ -349,8 +349,9 @@
 
   fprintf(stderr,
           "\nusage: %s [parameters] [host:displayNum] [parameters]\n"
-          "       %s [parameters] -listen [port] [parameters]\n",
-          programName, programName);
+          "       %s [parameters] -listen [port] [parameters]\n"
+          "       %s [parameters] [.tigervnc file]\n",
+          programName, programName, programName);
   fprintf(stderr,"\n"
           "Parameters can be turned on with -<param> or off with -<param>=0\n"
           "Parameters which take a value can be specified as "
@@ -368,6 +369,40 @@
   exit(1);
 }
 
+static void
+potentiallyLoadConfigurationFile(char *vncServerName)
+{
+  const bool hasPathSeparator = (strchr(vncServerName, '/') != NULL ||
+                                 (strchr(vncServerName, '\\')) != NULL);
+
+  if (hasPathSeparator) {
+#ifndef WIN32
+    struct stat sb;
+
+    // This might be a UNIX socket, we need to check
+    if (stat(vncServerName, &sb) == -1) {
+      // Some access problem; let loadViewerParameters() deal with it...
+    } else {
+      if ((sb.st_mode & S_IFMT) == S_IFSOCK)
+        return;
+    }
+#endif
+
+    try {
+      const char* newServerName;
+      newServerName = loadViewerParameters(vncServerName);
+      // This might be empty, but we still need to clear it so we
+      // don't try to connect to the filename
+      strncpy(vncServerName, newServerName, VNCSERVERNAMELEN);
+    } catch (rfb::Exception& e) {
+      vlog.error("%s", e.str());
+      if (alertOnFatalError)
+        fl_alert("%s", e.str());
+      exit(EXIT_FAILURE);
+    }
+  }
+}
+
 #ifndef WIN32
 static int
 interpretViaParam(char *remoteHost, int *remotePort, int localPort)
@@ -484,11 +519,11 @@
   Configuration::enableViewerParams();
 
   /* Load the default parameter settings */
-  const char* defaultServerName;
+  char defaultServerName[VNCSERVERNAMELEN];
   try {
-    defaultServerName = loadViewerParameters(NULL);
+    strncpy(defaultServerName, loadViewerParameters(NULL), VNCSERVERNAMELEN);
   } catch (rfb::Exception& e) {
-    defaultServerName = "";
+    strcpy(defaultServerName, "");
     vlog.error("%s", e.str());
     if (alertOnFatalError)
       fl_alert("%s", e.str());
@@ -516,6 +551,9 @@
     i++;
   }
 
+  // Check if the server name in reality is a configuration file
+  potentiallyLoadConfigurationFile(vncServerName);
+
   mkvnchomedir();
 
 #if !defined(WIN32) && !defined(__APPLE__)
diff --git a/vncviewer/vncviewer.man b/vncviewer/vncviewer.man
index 22b46cd..729c01d 100644
--- a/vncviewer/vncviewer.man
+++ b/vncviewer/vncviewer.man
@@ -14,6 +14,10 @@
 .RI [ options ] 
 .B \-listen
 .RI [ port ]
+.br
+.B vncviewer
+.RI [ options ]
+.RI [ .tigervnc file ]
 .SH DESCRIPTION
 .B vncviewer
 is a viewer (client) for Virtual Network Computing.  This manual page documents
@@ -31,6 +35,18 @@
 omitted.  So for example ":1" means display number 1 on the same machine, and
 "snoopy" means "snoopy:0" i.e. display 0 on machine "snoopy".
 
+As another quick way to start a connection to a VNC server, specify a .tigervnc
+configuration file as an argument to the viewer, e.g.:
+
+.RS
+vncviewer ./some.tigervnc
+.RE
+
+where './some.tigervnc' is an existing and valid TigerVNC configuration file.
+The file name needs to include a path separator.  Additional options may be
+given too, but the given configuration file will overwrite any conflicting
+parameters.
+
 If the VNC server is successfully contacted, you will be prompted for a
 password to authenticate you.  If the password is correct, a window will appear
 showing the desktop of the VNC server.
diff --git a/win/rfb_win32/Dialog.cxx b/win/rfb_win32/Dialog.cxx
index c6f303c..c9e333d 100644
--- a/win/rfb_win32/Dialog.cxx
+++ b/win/rfb_win32/Dialog.cxx
@@ -344,7 +344,7 @@
     delete [] hpages; hpages = 0;
 
     return true;
-  } catch (rdr::Exception) {
+  } catch (rdr::Exception&) {
     alreadyShowing = false;
 
     std::list<PropSheetPage*>::iterator pspi;
diff --git a/win/rfb_win32/Registry.cxx b/win/rfb_win32/Registry.cxx
index afbdd06..963a36a 100644
--- a/win/rfb_win32/Registry.cxx
+++ b/win/rfb_win32/Registry.cxx
@@ -164,7 +164,7 @@
 TCHAR* RegKey::getString(const TCHAR* valname, const TCHAR* def) const {
   try {
     return getString(valname);
-  } catch(rdr::Exception) {
+  } catch(rdr::Exception&) {
     return tstrDup(def);
   }
 }
@@ -177,7 +177,7 @@
 void RegKey::getBinary(const TCHAR* valname, void** data, int* length, void* def, int deflen) const {
   try {
     getBinary(valname, data, length);
-  } catch(rdr::Exception) {
+  } catch(rdr::Exception&) {
     if (deflen) {
       *data = new char[deflen];
       memcpy(*data, def, deflen);
@@ -194,7 +194,7 @@
 int RegKey::getInt(const TCHAR* valname, int def) const {
   try {
     return getInt(valname);
-  } catch(rdr::Exception) {
+  } catch(rdr::Exception&) {
     return def;
   }
 }
@@ -269,7 +269,7 @@
   try {
     TCharArray tmp(getRepresentation(valname));
     return true;
-  } catch(rdr::Exception) {
+  } catch(rdr::Exception&) {
     return false;
   }
 }
diff --git a/win/vncconfig/Connections.h b/win/vncconfig/Connections.h
index 3d3c06c..b3402ab 100644
--- a/win/vncconfig/Connections.h
+++ b/win/vncconfig/Connections.h
@@ -76,7 +76,7 @@
         try {
           network::TcpFilter::Pattern pat(network::TcpFilter::parsePattern(CStr(newPat.buf)));
           pattern.replaceBuf(TCharArray(network::TcpFilter::patternToStr(pat)).takeBuf());
-        } catch(rdr::Exception e) {
+        } catch(rdr::Exception& e) {
           MsgBox(NULL, TStr(e.str()), MB_ICONEXCLAMATION | MB_OK);
           return false;
         }
@@ -261,7 +261,7 @@
               (http_port != getItemInt(IDC_HTTP_PORT)) ||
               ((http_port!=0) != (isItemChecked(IDC_HTTP_ENABLE)!=0)) ||
               (rfb::Server::idleTimeout != getItemInt(IDC_IDLE_TIMEOUT));
-        } catch (rdr::Exception) {
+        } catch (rdr::Exception&) {
           return false;
         }
       }
diff --git a/win/vncconfig/Legacy.cxx b/win/vncconfig/Legacy.cxx
index 7d51de8..b56eb37 100644
--- a/win/vncconfig/Legacy.cxx
+++ b/win/vncconfig/Legacy.cxx
@@ -127,7 +127,7 @@
 
               // Finally, save the Hosts value
               regKey.setString(_T("Hosts"), TStr(newHosts.buf));
-            } catch (rdr::Exception) {
+            } catch (rdr::Exception&) {
               MsgBox(0, _T("Unable to convert AuthHosts setting to Hosts format."),
                      MB_ICONWARNING | MB_OK);
             }
@@ -148,7 +148,7 @@
           regKey.setBool(_T("AlwaysShared"), connectPriority == 1);
           regKey.setBool(_T("NeverShared"), connectPriority == 2);
 
-        } catch(rdr::Exception) {
+        } catch(rdr::Exception&) {
         }
 
         // Open the local, default-user settings
diff --git a/win/winvnc/winvnc.cxx b/win/winvnc/winvnc.cxx
index 5623421..43c852c 100644
--- a/win/winvnc/winvnc.cxx
+++ b/win/winvnc/winvnc.cxx
@@ -172,13 +172,13 @@
         // Try to clean up earlier services we've had
         try {
           rfb::win32::unregisterService("WinVNC4");
-        } catch (rdr::SystemException) {
+        } catch (rdr::SystemException&) {
           // Do nothing as we might fail simply because there was no
           // service to remove
         }
         try {
           rfb::win32::unregisterService("TigerVNC Server");
-        } catch (rdr::SystemException) {
+        } catch (rdr::SystemException&) {
         }
 
         if (rfb::win32::registerService(VNCServerService::Name,