From eefe28d485238e6e19dbdc2cd71ed23a0fa6b001 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 11 Jan 2021 22:46:26 +0100 Subject: [PATCH] Have a history of used vnc servers to select from in the vncviewer --- vncviewer/ServerDialog.cxx | 113 ++++++++++++++++++++++++++++++++++--- vncviewer/ServerDialog.h | 11 +++- vncviewer/parameters.cxx | 73 +++++++++++++++++++++++- vncviewer/parameters.h | 13 +++++ 4 files changed, 197 insertions(+), 13 deletions(-) diff --git a/vncviewer/ServerDialog.cxx b/vncviewer/ServerDialog.cxx index fec17896..9ed5c408 100644 --- a/vncviewer/ServerDialog.cxx +++ b/vncviewer/ServerDialog.cxx @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -30,13 +31,25 @@ #include #include +#include +#include +#include + +#include +#include + #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")) @@ -51,7 +64,11 @@ ServerDialog::ServerDialog() 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;iadd(serverHistory[i].c_str()); + } int adjust = (w() - 20) / 4; int button_width = adjust - margin/2; @@ -112,7 +129,7 @@ void ServerDialog::run(const char* servername, char *newservername) ServerDialog dialog; dialog.serverName->value(servername); - + dialog.show(); while (dialog.shown()) Fl::wait(); @@ -154,7 +171,7 @@ void ServerDialog::handleLoad(Fl_Widget *widget, void *data) try { dialog->serverName->value(loadViewerParameters(filename)); - } catch (rfb::Exception& e) { + } catch (Exception& e) { fl_alert("%s", e.str()); } @@ -209,7 +226,7 @@ void ServerDialog::handleSaveAs(Fl_Widget *widget, void *data) try { saveViewerParameters(filename, servername); - } catch (rfb::Exception& e) { + } catch (Exception& e) { fl_alert("%s", e.str()); } @@ -227,7 +244,7 @@ void ServerDialog::handleCancel(Fl_Widget *widget, void *data) { ServerDialog *dialog = (ServerDialog*)data; - dialog->serverName->value(NULL); + dialog->serverName->value(""); dialog->hide(); } @@ -238,10 +255,90 @@ void ServerDialog::handleConnect(Fl_Widget *widget, void *data) const char* servername = dialog->serverName->value(); dialog->hide(); - + try { saveViewerParameters(NULL, servername); - } catch (rfb::Exception& e) { + + vector::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(); +} diff --git a/vncviewer/ServerDialog.h b/vncviewer/ServerDialog.h index 7926849a..83639777 100644 --- a/vncviewer/ServerDialog.h +++ b/vncviewer/ServerDialog.h @@ -20,9 +20,11 @@ #define __SERVERDIALOG_H__ #include +#include +#include class Fl_Widget; -class Fl_Input; +class Fl_Input_Choice; class ServerDialog : public Fl_Window { protected: @@ -40,8 +42,13 @@ protected: static void handleCancel(Fl_Widget *widget, void *data); static void handleConnect(Fl_Widget *widget, void *data); +private: + void loadServerHistory(); + void saveServerHistory(); + protected: - Fl_Input *serverName; + Fl_Input_Choice *serverName; + std::vector serverHistory; }; #endif diff --git a/vncviewer/parameters.cxx b/vncviewer/parameters.cxx index bb8e47fa..b28a1112 100644 --- a/vncviewer/parameters.cxx +++ b/vncviewer/parameters.cxx @@ -44,10 +44,12 @@ #include #include #include +#include #include "i18n.h" using namespace rfb; +using namespace std; static LogWriter vlog("Parameters"); @@ -398,6 +400,34 @@ static bool getKeyInt(const char* _name, int* dest, HKEY* hKey) { } +void saveHistoryToRegKey(const vector& 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; @@ -432,6 +462,43 @@ static void saveToReg(const char* servername) { } } +void loadHistoryFromRegKey(vector& 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() { @@ -521,9 +588,9 @@ void saveViewerParameters(const char *filename, const char *servername) { 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(parameterArray[i]) != NULL) { if (encodeValue(*(StringParameter*)parameterArray[i], encodingBuffer, buffersize)) @@ -638,7 +705,7 @@ char* loadViewerParameters(const char *filename) { invalidParameterName = false; } else { - + // Find and set the correct parameter for (size_t i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) { diff --git a/vncviewer/parameters.h b/vncviewer/parameters.h index 94aec9fa..3d8ac24f 100644 --- a/vncviewer/parameters.h +++ b/vncviewer/parameters.h @@ -22,6 +22,14 @@ #include +#ifdef _WIN32 +#include +#include +#endif + +#define SERVER_HISTORY_SIZE 20 + + extern rfb::IntParameter pointerEventInterval; extern rfb::BoolParameter emulateMiddleButton; extern rfb::BoolParameter dotWhenNoCursor; @@ -71,4 +79,9 @@ extern rfb::StringParameter via; void saveViewerParameters(const char *filename, const char *servername=NULL); char* loadViewerParameters(const char *filename); +#ifdef _WIN32 +void loadHistoryFromRegKey(std::vector& serverHistory); +void saveHistoryToRegKey(const std::vector& serverHistory); +#endif + #endif -- 2.39.5