#include <FL/Fl.H>
#include <FL/Fl_Input.H>
+#include <FL/Fl_Input_Choice.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Return_Button.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_File_Chooser.H>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+
+#include <os/os.h>
+#include <rfb/Exception.h>
+
#include "ServerDialog.h"
#include "OptionsDialog.h"
#include "fltk_layout.h"
#include "i18n.h"
#include "vncviewer.h"
#include "parameters.h"
-#include "rfb/Exception.h"
+
+
+using namespace std;
+using namespace rfb;
+
+const char* SERVER_HISTORY="tigervnc.history";
ServerDialog::ServerDialog()
: Fl_Window(450, 160, _("VNC Viewer: Connection Details"))
x = margin + server_label_width;
y = margin;
- serverName = new Fl_Input(x, y, w() - margin*2 - server_label_width, INPUT_HEIGHT, _("VNC server:"));
+ serverName = new Fl_Input_Choice(x, y, w() - margin*2 - server_label_width, INPUT_HEIGHT, _("VNC server:"));
+ loadServerHistory();
+ for(size_t i=0;i<serverHistory.size();++i) {
+ serverName->add(serverHistory[i].c_str());
+ }
int adjust = (w() - 20) / 4;
int button_width = adjust - margin/2;
ServerDialog dialog;
dialog.serverName->value(servername);
-
+
dialog.show();
while (dialog.shown()) Fl::wait();
try {
dialog->serverName->value(loadViewerParameters(filename));
- } catch (rfb::Exception& e) {
+ } catch (Exception& e) {
fl_alert("%s", e.str());
}
try {
saveViewerParameters(filename, servername);
- } catch (rfb::Exception& e) {
+ } catch (Exception& e) {
fl_alert("%s", e.str());
}
{
ServerDialog *dialog = (ServerDialog*)data;
- dialog->serverName->value(NULL);
+ dialog->serverName->value("");
dialog->hide();
}
const char* servername = dialog->serverName->value();
dialog->hide();
-
+
try {
saveViewerParameters(NULL, servername);
- } catch (rfb::Exception& e) {
+
+ vector<string>::iterator elem = std::find(dialog->serverHistory.begin(), dialog->serverHistory.end(), servername);
+ // avoid duplicates in the history
+ if(dialog->serverHistory.end() == elem) {
+ dialog->serverHistory.insert(dialog->serverHistory.begin(), servername);
+ dialog->saveServerHistory();
+ }
+ } catch (Exception& e) {
fl_alert("%s", e.str());
}
}
+
+
+void ServerDialog::loadServerHistory()
+{
+#ifdef _WIN32
+ loadHistoryFromRegKey(serverHistory);
+ return;
+#endif
+
+ char* homeDir = NULL;
+ if (getvnchomedir(&homeDir) == -1) {
+ throw Exception(_("Failed to read server history file, "
+ "can't obtain home directory path."));
+ }
+
+ char filepath[PATH_MAX];
+ snprintf(filepath, sizeof(filepath), "%s%s", homeDir, SERVER_HISTORY);
+ delete[] homeDir;
+
+ /* Read server history from file */
+ ifstream f (filepath);
+ if (!f.is_open()) {
+ // no history file
+ return;
+ }
+
+ string line;
+ while(getline(f, line)) {
+ serverHistory.push_back(line);
+ }
+
+ if (f.bad()) {
+ throw Exception(_("Failed to read server history file, "
+ "error while reading file."));
+ }
+ f.close();
+}
+
+void ServerDialog::saveServerHistory()
+{
+#ifdef _WIN32
+ saveHistoryToRegKey(serverHistory);
+ return;
+#endif
+
+ char* homeDir = NULL;
+ if (getvnchomedir(&homeDir) == -1) {
+ throw Exception(_("Failed to write server history file, "
+ "can't obtain home directory path."));
+ }
+
+ char filepath[PATH_MAX];
+ snprintf(filepath, sizeof(filepath), "%s%s", homeDir, SERVER_HISTORY);
+ delete[] homeDir;
+
+ /* Write server history to file */
+ ofstream f (filepath);
+ if (!f.is_open()) {
+ throw Exception(_("Failed to write server history file, "
+ "can't open file."));
+ }
+
+ // Save the last X elements to the config file.
+ for(size_t i=0; i < serverHistory.size() && i <= SERVER_HISTORY_SIZE; i++) {
+ f << serverHistory[i] << endl;
+ }
+
+ if (f.bad()) {
+ throw Exception(_("Failed to write server history file, "
+ "error while writing file."));
+ }
+ f.close();
+}
#include <string.h>
#include <limits.h>
#include <errno.h>
+#include <assert.h>
#include "i18n.h"
using namespace rfb;
+using namespace std;
static LogWriter vlog("Parameters");
}
+void saveHistoryToRegKey(const vector<string>& serverHistory) {
+ HKEY hKey;
+ LONG res = RegCreateKeyExW(HKEY_CURRENT_USER,
+ L"Software\\TigerVNC\\vncviewer\\history", 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
+ &hKey, NULL);
+
+ if (res != ERROR_SUCCESS) {
+ vlog.error(_("Failed to create registry key: %ld"), res);
+ return;
+ }
+
+ size_t index = 0;
+ assert(SERVER_HISTORY_SIZE < 100);
+ char indexString[3];
+
+ while(index < serverHistory.size() && index <= SERVER_HISTORY_SIZE) {
+ snprintf(indexString, 3, "%d", index);
+ setKeyString(indexString, serverHistory[index].c_str(), &hKey);
+ index++;
+ }
+
+ res = RegCloseKey(hKey);
+ if (res != ERROR_SUCCESS) {
+ vlog.error(_("Failed to close registry key: %ld"), res);
+ }
+}
+
static void saveToReg(const char* servername) {
HKEY hKey;
}
}
+void loadHistoryFromRegKey(vector<string>& serverHistory) {
+ HKEY hKey;
+
+ LONG res = RegOpenKeyExW(HKEY_CURRENT_USER,
+ L"Software\\TigerVNC\\vncviewer\\history", 0,
+ KEY_READ, &hKey);
+ if (res != ERROR_SUCCESS) {
+ if (res == ERROR_FILE_NOT_FOUND) {
+ // The key does not exist, defaults will be used.
+ } else {
+ vlog.error(_("Failed to open registry key: %ld"), res);
+ }
+ return;
+ }
+
+ bool stop = false;
+ size_t index = 0;
+ const DWORD buffersize = 256;
+ char indexString[3];
+
+ while(!stop) {
+ snprintf(indexString, 3, "%d", index);
+ char servernameBuffer[buffersize];
+ if (getKeyString(indexString, servernameBuffer, buffersize, &hKey)) {
+ serverHistory.push_back(servernameBuffer);
+ index++;
+ }
+ else {
+ stop = true;
+ }
+ }
+
+ res = RegCloseKey(hKey);
+ if (res != ERROR_SUCCESS){
+ vlog.error(_("Failed to close registry key: %ld"), res);
+ }
+}
static char* loadFromReg() {
fprintf(f, "%s\r\n", IDENTIFIER_STRING);
fprintf(f, "\r\n");
- if (encodeValue(servername, encodingBuffer, buffersize))
+ if (encodeValue(servername, encodingBuffer, buffersize))
fprintf(f, "ServerName=%s\n", encodingBuffer);
-
+
for (size_t i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
if (encodeValue(*(StringParameter*)parameterArray[i], encodingBuffer, buffersize))
invalidParameterName = false;
} else {
-
+
// Find and set the correct parameter
for (size_t i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {