Merge branch 'mac_menu' of https://github.com/CendioOssman/tigervnc
diff --git a/vncviewer/fltk_layout.h b/vncviewer/fltk_layout.h
index 21fb00a..9e5c2d4 100644
--- a/vncviewer/fltk_layout.h
+++ b/vncviewer/fltk_layout.h
@@ -35,9 +35,9 @@
 }
 
 /* Escapes all @ in text as those have special meaning in labels */
-static inline int fltk_escape(const char *in, char *out, size_t maxlen)
+static inline size_t fltk_escape(const char *in, char *out, size_t maxlen)
 {
-    int len;
+    size_t len;
 
     len = 0;
 
@@ -69,9 +69,9 @@
 }
 
 /* Filter out unsafe characters for menu entries */
-static inline int fltk_menu_escape(const char *in, char *out, size_t maxlen)
+static inline size_t fltk_menu_escape(const char *in, char *out, size_t maxlen)
 {
-    int len;
+    size_t len;
 
     len = 0;
 
diff --git a/vncviewer/parameters.cxx b/vncviewer/parameters.cxx
index 712a257..7a868c7 100644
--- a/vncviewer/parameters.cxx
+++ b/vncviewer/parameters.cxx
@@ -580,15 +580,16 @@
     // Read the next line
     lineNr++;
     if (!fgets(line, sizeof(line), f)) {
-      if (line[sizeof(line) -1] != '\0')
-        throw Exception(_("Failed to read line %d in file %s: %s"),
-                        lineNr, filepath, _("Line too long"));
       if (feof(f))
         break;
 
       throw Exception(_("Failed to read line %d in file %s: %s"),
                       lineNr, filepath, strerror(errno));
     }
+
+    if (strlen(line) == (sizeof(line) - 1))
+      throw Exception(_("Failed to read line %d in file %s: %s"),
+                      lineNr, filepath, _("Line too long"));
     
     // Make sure that the first line of the file has the file identifier string
     if(lineNr == 1) {
diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx
index a60f000..3f51dd3 100644
--- a/vncviewer/vncviewer.cxx
+++ b/vncviewer/vncviewer.cxx
@@ -30,6 +30,7 @@
 #include <signal.h>
 #include <locale.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <sys/stat.h>
 
 #ifdef WIN32
@@ -58,6 +59,7 @@
 #include <FL/Fl.H>
 #include <FL/Fl_Widget.H>
 #include <FL/Fl_PNG_Image.H>
+#include <FL/Fl_Sys_Menu_Bar.H>
 #include <FL/fl_ask.H>
 #include <FL/x.H>
 
@@ -67,6 +69,7 @@
 #include "ServerDialog.h"
 #include "UserDialog.h"
 #include "vncviewer.h"
+#include "fltk_layout.h"
 
 #ifdef WIN32
 #include "resource.h"
@@ -83,6 +86,8 @@
 
 char vncServerName[VNCSERVERNAMELEN] = { '\0' };
 
+static const char *argv0 = NULL;
+
 static bool exitMainloop = false;
 static const char *exitError = NULL;
 
@@ -102,11 +107,36 @@
   fl_message("%s", aboutText);
 }
 
+#ifdef __APPLE__
 static void about_callback(Fl_Widget *widget, void *data)
 {
   about_vncviewer();
 }
 
+static void new_connection_cb(Fl_Widget *widget, void *data)
+{
+  const char *argv[2];
+  pid_t pid;
+
+  pid = fork();
+  if (pid == -1) {
+    vlog.error(_("Error starting new TigerVNC Viewer: %s"), strerror(errno));
+    return;
+  }
+
+  if (pid != 0)
+    return;
+
+  argv[0] = argv0;
+  argv[1] = NULL;
+
+  execvp(argv[0], (char * const *)argv);
+
+  vlog.error(_("Error starting new TigerVNC Viewer: %s"), strerror(errno));
+  _exit(1);
+}
+#endif
+
 static void CleanupSignalHandler(int sig)
 {
   // CleanupSignalHandler allows C++ object cleanup to happen because it calls
@@ -237,6 +267,16 @@
   Fl_Mac_App_Menu::show = _("Show All");
 
   fl_mac_set_about(about_callback, NULL);
+
+  Fl_Sys_Menu_Bar *menubar;
+  char buffer[1024];
+  menubar = new Fl_Sys_Menu_Bar(0, 0, 500, 25);
+  // Fl_Sys_Menu_Bar overrides methods without them being virtual,
+  // which means we cannot use our generic Fl_Menu_ helpers.
+  if (fltk_menu_escape(_("&File"), buffer, sizeof(buffer)) < sizeof(buffer))
+      menubar->add(buffer, 0, 0, 0, FL_SUBMENU);
+  if (fltk_menu_escape(_("&New Connection"), buffer, sizeof(buffer)) < sizeof(buffer))
+      menubar->insert(1, buffer, FL_COMMAND | 'n', new_connection_cb);
 #endif
 }
 
@@ -373,6 +413,8 @@
 {
   UserDialog dlg;
 
+  argv0 = argv[0];
+
   setlocale(LC_ALL, "");
   bindtextdomain(PACKAGE_NAME, LOCALE_DIR);
   textdomain(PACKAGE_NAME);