Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

CAddScreen.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2002 Chris Schoeneman
00004  * 
00005  * This package is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * found in the file COPYING that should have accompanied this file.
00008  * 
00009  * This package is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #include "CConfig.h"
00016 #include "KeyTypes.h"
00017 #include "OptionTypes.h"
00018 #include "ProtocolTypes.h"
00019 #include "CStringUtil.h"
00020 #include "CArch.h"
00021 #include "CAddScreen.h"
00022 #include "LaunchUtil.h"
00023 #include "resource.h"
00024 
00025 struct CModifierInfo {
00026 public:
00027     int             m_ctrlID;
00028     const char*     m_name;
00029     KeyModifierID   m_modifierID;
00030     OptionID        m_optionID;
00031 };
00032 
00033 static const CModifierInfo s_modifiers[] = {
00034     { IDC_ADD_MOD_SHIFT, "Shift",
00035         kKeyModifierIDShift,    kOptionModifierMapForShift   },
00036     { IDC_ADD_MOD_CTRL,  "Ctrl",
00037         kKeyModifierIDControl,  kOptionModifierMapForControl },
00038     { IDC_ADD_MOD_ALT,   "Alt",
00039         kKeyModifierIDAlt,      kOptionModifierMapForAlt     },
00040     { IDC_ADD_MOD_META,  "Meta",
00041         kKeyModifierIDMeta,     kOptionModifierMapForMeta    },
00042     { IDC_ADD_MOD_SUPER, "Super",
00043         kKeyModifierIDSuper,    kOptionModifierMapForSuper   }
00044 };
00045 
00046 static const KeyModifierID baseModifier = kKeyModifierIDShift;
00047 
00048 //
00049 // CAddScreen
00050 //
00051 
00052 CAddScreen*         CAddScreen::s_singleton = NULL;
00053 
00054 CAddScreen::CAddScreen(HWND parent, CConfig* config, const CString& name) :
00055     m_parent(parent),
00056     m_config(config),
00057     m_name(name)
00058 {
00059     assert(s_singleton == NULL);
00060     s_singleton = this;
00061 }
00062 
00063 CAddScreen::~CAddScreen()
00064 {
00065     s_singleton = NULL;
00066 }
00067 
00068 bool
00069 CAddScreen::doModal()
00070 {
00071     // do dialog
00072     return (DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_ADD),
00073                                 m_parent, (DLGPROC)dlgProc, (LPARAM)this) != 0);
00074 }
00075 
00076 CString
00077 CAddScreen::getName() const
00078 {
00079     return m_name;
00080 }
00081 
00082 void
00083 CAddScreen::init(HWND hwnd)
00084 {
00085     // set title
00086     CString title;
00087     if (m_name.empty()) {
00088         title = getString(IDS_ADD_SCREEN);
00089     }
00090     else {
00091         title = CStringUtil::format(
00092                             getString(IDS_EDIT_SCREEN).c_str(),
00093                             m_name.c_str());
00094     }
00095     SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)title.c_str());
00096 
00097     // fill in screen name
00098     HWND child = getItem(hwnd, IDC_ADD_SCREEN_NAME_EDIT);
00099     SendMessage(child, WM_SETTEXT, 0, (LPARAM)m_name.c_str());
00100 
00101     // fill in aliases
00102     CString aliases;
00103     for (CConfig::all_const_iterator index = m_config->beginAll();
00104                                 index != m_config->endAll(); ++index) {
00105         if (CStringUtil::CaselessCmp::equal(index->second, m_name) &&
00106             !CStringUtil::CaselessCmp::equal(index->second, index->first)) {
00107             if (!aliases.empty()) {
00108                 aliases += "\r\n";
00109             }
00110             aliases += index->first;
00111         }
00112     }
00113     child = getItem(hwnd, IDC_ADD_ALIASES_EDIT);
00114     SendMessage(child, WM_SETTEXT, 0, (LPARAM)aliases.c_str());
00115 
00116     // set options
00117     CConfig::CScreenOptions options;
00118     getOptions(options);
00119     CConfig::CScreenOptions::const_iterator index;
00120     child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
00121     index = options.find(kOptionHalfDuplexCapsLock);
00122     setItemChecked(child, (index != options.end() && index->second != 0));
00123     child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK);
00124     index = options.find(kOptionHalfDuplexNumLock);
00125     setItemChecked(child, (index != options.end() && index->second != 0));
00126     child = getItem(hwnd, IDC_ADD_HD_SCROLL_CHECK);
00127     index = options.find(kOptionHalfDuplexScrollLock);
00128     setItemChecked(child, (index != options.end() && index->second != 0));
00129 
00130     // modifier options
00131     for (UInt32 i = 0; i < sizeof(s_modifiers) /
00132                                 sizeof(s_modifiers[0]); ++i) {
00133         child = getItem(hwnd, s_modifiers[i].m_ctrlID);
00134 
00135         // fill in options
00136         for (UInt32 j = 0; j < sizeof(s_modifiers) /
00137                                     sizeof(s_modifiers[0]); ++j) {
00138             SendMessage(child, CB_ADDSTRING, 0,
00139                                 (LPARAM)s_modifiers[j].m_name);
00140         }
00141 
00142         // choose current value
00143         index            = options.find(s_modifiers[i].m_optionID);
00144         KeyModifierID id = s_modifiers[i].m_modifierID;
00145         if (index != options.end()) {
00146             id = index->second;
00147         }
00148         SendMessage(child, CB_SETCURSEL, id - baseModifier, 0);
00149     }
00150 
00151     // dead corners
00152     UInt32 corners = 0;
00153     index = options.find(kOptionScreenSwitchCorners);
00154     if (index != options.end()) {
00155         corners = index->second;
00156     }
00157     child = getItem(hwnd, IDC_ADD_DC_TOP_LEFT);
00158     setItemChecked(child, (corners & kTopLeftMask) != 0);
00159     child = getItem(hwnd, IDC_ADD_DC_TOP_RIGHT);
00160     setItemChecked(child, (corners & kTopRightMask) != 0);
00161     child = getItem(hwnd, IDC_ADD_DC_BOTTOM_LEFT);
00162     setItemChecked(child, (corners & kBottomLeftMask) != 0);
00163     child = getItem(hwnd, IDC_ADD_DC_BOTTOM_RIGHT);
00164     setItemChecked(child, (corners & kBottomRightMask) != 0);
00165     index = options.find(kOptionScreenSwitchCornerSize);
00166     SInt32 size = 0;
00167     if (index != options.end()) {
00168         size = index->second;
00169     }
00170     char buffer[20];
00171     sprintf(buffer, "%d", size);
00172     child = getItem(hwnd, IDC_ADD_DC_SIZE);
00173     SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer);
00174 }
00175 
00176 bool
00177 CAddScreen::save(HWND hwnd)
00178 {
00179     // get the old aliases and options
00180     CStringList oldAliases;
00181     getAliases(oldAliases);
00182     CConfig::CScreenOptions options;
00183     getOptions(options);
00184 
00185     // extract name and aliases
00186     CString newName;
00187     HWND child = getItem(hwnd, IDC_ADD_SCREEN_NAME_EDIT);
00188     newName = getWindowText(child);
00189     CStringList newAliases;
00190     child = getItem(hwnd, IDC_ADD_ALIASES_EDIT);
00191     tokenize(newAliases, getWindowText(child));
00192 
00193     // name must be valid
00194     if (!m_config->isValidScreenName(newName)) {
00195         showError(hwnd, CStringUtil::format(
00196                         getString(IDS_INVALID_SCREEN_NAME).c_str(),
00197                         newName.c_str()));
00198         return false;
00199     }
00200 
00201     // aliases must be valid
00202     for (CStringList::const_iterator index = newAliases.begin();
00203                         index != newAliases.end(); ++index) {
00204         if (!m_config->isValidScreenName(*index)) {
00205             showError(hwnd, CStringUtil::format(
00206                         getString(IDS_INVALID_SCREEN_NAME).c_str(),
00207                         index->c_str()));
00208             return false;
00209         }
00210     }
00211 
00212     // new name may not be in the new alias list
00213     if (isNameInList(newAliases, newName)) {
00214         showError(hwnd, CStringUtil::format(
00215                         getString(IDS_SCREEN_NAME_IS_ALIAS).c_str(),
00216                         newName.c_str()));
00217         return false;
00218     }
00219 
00220     // name must not exist in config but allow same name.  also
00221     // allow name if it exists in the old alias list but not the
00222     // new one.
00223     if (m_config->isScreen(newName) &&
00224         !CStringUtil::CaselessCmp::equal(newName, m_name) &&
00225         !isNameInList(oldAliases, newName)) {
00226         showError(hwnd, CStringUtil::format(
00227                         getString(IDS_DUPLICATE_SCREEN_NAME).c_str(),
00228                         newName.c_str()));
00229         return false;
00230     }
00231 
00232     // aliases must not exist in config but allow same aliases and
00233     // allow an alias to be the old name.
00234     for (CStringList::const_iterator index = newAliases.begin();
00235                         index != newAliases.end(); ++index) {
00236         if (m_config->isScreen(*index) &&
00237             !CStringUtil::CaselessCmp::equal(*index, m_name) &&
00238             !isNameInList(oldAliases, *index)) {
00239             showError(hwnd, CStringUtil::format(
00240                         getString(IDS_DUPLICATE_SCREEN_NAME).c_str(),
00241                         index->c_str()));
00242             return false;
00243         }
00244     }
00245 
00246     // dead corner size must be non-negative
00247     child = getItem(hwnd, IDC_ADD_DC_SIZE);
00248     CString valueString = getWindowText(child);
00249     int cornerSize = atoi(valueString.c_str());
00250     if (cornerSize < 0) {
00251         showError(hwnd, CStringUtil::format(
00252                             getString(IDS_INVALID_CORNER_SIZE).c_str(),
00253                             valueString.c_str()));
00254         SetFocus(child);
00255         return false;
00256     }
00257 
00258     // collect options
00259     child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
00260     if (isItemChecked(child)) {
00261         options[kOptionHalfDuplexCapsLock] = 1;
00262     }
00263     else {
00264         options.erase(kOptionHalfDuplexCapsLock);
00265     }
00266     child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK);
00267     if (isItemChecked(child)) {
00268         options[kOptionHalfDuplexNumLock] = 1;
00269     }
00270     else {
00271         options.erase(kOptionHalfDuplexNumLock);
00272     }
00273     child = getItem(hwnd, IDC_ADD_HD_SCROLL_CHECK);
00274     if (isItemChecked(child)) {
00275         options[kOptionHalfDuplexScrollLock] = 1;
00276     }
00277     else {
00278         options.erase(kOptionHalfDuplexScrollLock);
00279     }
00280 
00281     // save modifier options
00282     for (UInt32 i = 0; i < sizeof(s_modifiers) /
00283                                 sizeof(s_modifiers[0]); ++i) {
00284         child            = getItem(hwnd, s_modifiers[i].m_ctrlID);
00285         KeyModifierID id = static_cast<KeyModifierID>(
00286                             SendMessage(child, CB_GETCURSEL, 0, 0) +
00287                                 baseModifier);
00288         if (id != s_modifiers[i].m_modifierID) {
00289             options[s_modifiers[i].m_optionID] = id;
00290         }
00291         else {
00292             options.erase(s_modifiers[i].m_optionID);
00293         }
00294     }
00295 
00296     // save dead corner options
00297     UInt32 corners = 0;
00298     if (isItemChecked(getItem(hwnd, IDC_ADD_DC_TOP_LEFT))) {
00299         corners |= kTopLeftMask;
00300     }
00301     if (isItemChecked(getItem(hwnd, IDC_ADD_DC_TOP_RIGHT))) {
00302         corners |= kTopRightMask;
00303     }
00304     if (isItemChecked(getItem(hwnd, IDC_ADD_DC_BOTTOM_LEFT))) {
00305         corners |= kBottomLeftMask;
00306     }
00307     if (isItemChecked(getItem(hwnd, IDC_ADD_DC_BOTTOM_RIGHT))) {
00308         corners |= kBottomRightMask;
00309     }
00310     options[kOptionScreenSwitchCorners]    = corners;
00311     options[kOptionScreenSwitchCornerSize] = cornerSize;
00312 
00313     // save new data to config
00314     if (m_name.empty()) {
00315         // added screen
00316         m_config->addScreen(newName);
00317     }
00318     else {
00319         // edited screen
00320         m_config->removeAliases(m_name);
00321         m_config->removeOptions(m_name);
00322         m_config->renameScreen(m_name, newName);
00323     }
00324     m_name = newName;
00325     for (CStringList::const_iterator index = newAliases.begin();
00326                             index != newAliases.end(); ++index) {
00327         m_config->addAlias(m_name, *index);
00328     }
00329     for (CConfig::CScreenOptions::const_iterator
00330                             index  = options.begin();
00331                             index != options.end(); ++index) {
00332         m_config->addOption(m_name, index->first, index->second);
00333     }
00334 
00335     return true;
00336 }
00337 
00338 BOOL
00339 CAddScreen::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
00340 {
00341     switch (message) {
00342     case WM_INITDIALOG:
00343         init(hwnd);
00344         return TRUE;
00345 
00346     case WM_COMMAND:
00347         switch (LOWORD(wParam)) {
00348         case IDOK:
00349             if (save(hwnd)) {
00350                 EndDialog(hwnd, 1);
00351             }
00352             return TRUE;
00353 
00354         case IDCANCEL:
00355             EndDialog(hwnd, 0);
00356             return TRUE;
00357         }
00358         break;
00359 
00360     default:
00361         break;
00362     }
00363 
00364     return FALSE;
00365 }
00366 
00367 BOOL CALLBACK
00368 CAddScreen::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
00369 {
00370     return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
00371 }
00372 
00373 void
00374 CAddScreen::getAliases(CStringList& aliases) const
00375 {
00376     for (CConfig::all_const_iterator index = m_config->beginAll();
00377                                 index != m_config->endAll(); ++index) {
00378         if (CStringUtil::CaselessCmp::equal(index->second, m_name) &&
00379             !CStringUtil::CaselessCmp::equal(index->second, index->first)) {
00380             aliases.push_back(index->first);
00381         }
00382     }
00383 }
00384 
00385 void
00386 CAddScreen::getOptions(CConfig::CScreenOptions& optionsOut) const
00387 {
00388     const CConfig::CScreenOptions* options = m_config->getOptions(m_name);
00389     if (options == NULL) {
00390         optionsOut = CConfig::CScreenOptions();
00391     }
00392     else {
00393         optionsOut = *options;
00394     }
00395 }
00396 
00397 void
00398 CAddScreen::tokenize(CStringList& tokens, const CString& src)
00399 {
00400     // find first non-whitespace
00401     CString::size_type x = src.find_first_not_of(" \t\r\n");
00402     if (x == CString::npos) {
00403         return;
00404     }
00405 
00406     // find next whitespace
00407     do {
00408         CString::size_type y = src.find_first_of(" \t\r\n", x);
00409         if (y == CString::npos) {
00410             y = src.size();
00411         }
00412         tokens.push_back(src.substr(x, y - x));
00413         x = src.find_first_not_of(" \t\r\n", y);
00414     } while (x != CString::npos);
00415 }
00416 
00417 bool
00418 CAddScreen::isNameInList(const CStringList& names, const CString& name)
00419 {
00420     for (CStringList::const_iterator index = names.begin();
00421                                 index != names.end(); ++index) {
00422         if (CStringUtil::CaselessCmp::equal(name, *index)) {
00423             return true;
00424         }
00425     }
00426     return false;
00427 }

Generated on Fri Nov 6 00:21:13 2009 for synergy-plus by  doxygen 1.3.9.1