source: trunk/synergy/cmd/launcher/CAddScreen.cpp@ 3232

Last change on this file since 3232 was 2749, checked in by bird, 19 years ago

synergy v1.3.1 sources (zip).

File size: 11.1 KB
Line 
1/*
2 * synergy -- mouse and keyboard sharing utility
3 * Copyright (C) 2002 Chris Schoeneman
4 *
5 * This package is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * found in the file COPYING that should have accompanied this file.
8 *
9 * This package is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "CConfig.h"
16#include "KeyTypes.h"
17#include "OptionTypes.h"
18#include "ProtocolTypes.h"
19#include "CStringUtil.h"
20#include "CArch.h"
21#include "CAddScreen.h"
22#include "LaunchUtil.h"
23#include "resource.h"
24
25struct CModifierInfo {
26public:
27 int m_ctrlID;
28 const char* m_name;
29 KeyModifierID m_modifierID;
30 OptionID m_optionID;
31};
32
33static const CModifierInfo s_modifiers[] = {
34 { IDC_ADD_MOD_SHIFT, "Shift",
35 kKeyModifierIDShift, kOptionModifierMapForShift },
36 { IDC_ADD_MOD_CTRL, "Ctrl",
37 kKeyModifierIDControl, kOptionModifierMapForControl },
38 { IDC_ADD_MOD_ALT, "Alt",
39 kKeyModifierIDAlt, kOptionModifierMapForAlt },
40 { IDC_ADD_MOD_META, "Meta",
41 kKeyModifierIDMeta, kOptionModifierMapForMeta },
42 { IDC_ADD_MOD_SUPER, "Super",
43 kKeyModifierIDSuper, kOptionModifierMapForSuper }
44};
45
46static const KeyModifierID baseModifier = kKeyModifierIDShift;
47
48//
49// CAddScreen
50//
51
52CAddScreen* CAddScreen::s_singleton = NULL;
53
54CAddScreen::CAddScreen(HWND parent, CConfig* config, const CString& name) :
55 m_parent(parent),
56 m_config(config),
57 m_name(name)
58{
59 assert(s_singleton == NULL);
60 s_singleton = this;
61}
62
63CAddScreen::~CAddScreen()
64{
65 s_singleton = NULL;
66}
67
68bool
69CAddScreen::doModal()
70{
71 // do dialog
72 return (DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_ADD),
73 m_parent, dlgProc, (LPARAM)this) != 0);
74}
75
76CString
77CAddScreen::getName() const
78{
79 return m_name;
80}
81
82void
83CAddScreen::init(HWND hwnd)
84{
85 // set title
86 CString title;
87 if (m_name.empty()) {
88 title = getString(IDS_ADD_SCREEN);
89 }
90 else {
91 title = CStringUtil::format(
92 getString(IDS_EDIT_SCREEN).c_str(),
93 m_name.c_str());
94 }
95 SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)title.c_str());
96
97 // fill in screen name
98 HWND child = getItem(hwnd, IDC_ADD_SCREEN_NAME_EDIT);
99 SendMessage(child, WM_SETTEXT, 0, (LPARAM)m_name.c_str());
100
101 // fill in aliases
102 CString aliases;
103 for (CConfig::all_const_iterator index = m_config->beginAll();
104 index != m_config->endAll(); ++index) {
105 if (CStringUtil::CaselessCmp::equal(index->second, m_name) &&
106 !CStringUtil::CaselessCmp::equal(index->second, index->first)) {
107 if (!aliases.empty()) {
108 aliases += "\r\n";
109 }
110 aliases += index->first;
111 }
112 }
113 child = getItem(hwnd, IDC_ADD_ALIASES_EDIT);
114 SendMessage(child, WM_SETTEXT, 0, (LPARAM)aliases.c_str());
115
116 // set options
117 CConfig::CScreenOptions options;
118 getOptions(options);
119 CConfig::CScreenOptions::const_iterator index;
120 child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
121 index = options.find(kOptionHalfDuplexCapsLock);
122 setItemChecked(child, (index != options.end() && index->second != 0));
123 child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK);
124 index = options.find(kOptionHalfDuplexNumLock);
125 setItemChecked(child, (index != options.end() && index->second != 0));
126 child = getItem(hwnd, IDC_ADD_HD_SCROLL_CHECK);
127 index = options.find(kOptionHalfDuplexScrollLock);
128 setItemChecked(child, (index != options.end() && index->second != 0));
129
130 // modifier options
131 for (UInt32 i = 0; i < sizeof(s_modifiers) /
132 sizeof(s_modifiers[0]); ++i) {
133 child = getItem(hwnd, s_modifiers[i].m_ctrlID);
134
135 // fill in options
136 for (UInt32 j = 0; j < sizeof(s_modifiers) /
137 sizeof(s_modifiers[0]); ++j) {
138 SendMessage(child, CB_ADDSTRING, 0,
139 (LPARAM)s_modifiers[j].m_name);
140 }
141
142 // choose current value
143 index = options.find(s_modifiers[i].m_optionID);
144 KeyModifierID id = s_modifiers[i].m_modifierID;
145 if (index != options.end()) {
146 id = index->second;
147 }
148 SendMessage(child, CB_SETCURSEL, id - baseModifier, 0);
149 }
150
151 // dead corners
152 UInt32 corners = 0;
153 index = options.find(kOptionScreenSwitchCorners);
154 if (index != options.end()) {
155 corners = index->second;
156 }
157 child = getItem(hwnd, IDC_ADD_DC_TOP_LEFT);
158 setItemChecked(child, (corners & kTopLeftMask) != 0);
159 child = getItem(hwnd, IDC_ADD_DC_TOP_RIGHT);
160 setItemChecked(child, (corners & kTopRightMask) != 0);
161 child = getItem(hwnd, IDC_ADD_DC_BOTTOM_LEFT);
162 setItemChecked(child, (corners & kBottomLeftMask) != 0);
163 child = getItem(hwnd, IDC_ADD_DC_BOTTOM_RIGHT);
164 setItemChecked(child, (corners & kBottomRightMask) != 0);
165 index = options.find(kOptionScreenSwitchCornerSize);
166 SInt32 size = 0;
167 if (index != options.end()) {
168 size = index->second;
169 }
170 char buffer[20];
171 sprintf(buffer, "%d", size);
172 child = getItem(hwnd, IDC_ADD_DC_SIZE);
173 SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer);
174}
175
176bool
177CAddScreen::save(HWND hwnd)
178{
179 // get the old aliases and options
180 CStringList oldAliases;
181 getAliases(oldAliases);
182 CConfig::CScreenOptions options;
183 getOptions(options);
184
185 // extract name and aliases
186 CString newName;
187 HWND child = getItem(hwnd, IDC_ADD_SCREEN_NAME_EDIT);
188 newName = getWindowText(child);
189 CStringList newAliases;
190 child = getItem(hwnd, IDC_ADD_ALIASES_EDIT);
191 tokenize(newAliases, getWindowText(child));
192
193 // name must be valid
194 if (!m_config->isValidScreenName(newName)) {
195 showError(hwnd, CStringUtil::format(
196 getString(IDS_INVALID_SCREEN_NAME).c_str(),
197 newName.c_str()));
198 return false;
199 }
200
201 // aliases must be valid
202 for (CStringList::const_iterator index = newAliases.begin();
203 index != newAliases.end(); ++index) {
204 if (!m_config->isValidScreenName(*index)) {
205 showError(hwnd, CStringUtil::format(
206 getString(IDS_INVALID_SCREEN_NAME).c_str(),
207 index->c_str()));
208 return false;
209 }
210 }
211
212 // new name may not be in the new alias list
213 if (isNameInList(newAliases, newName)) {
214 showError(hwnd, CStringUtil::format(
215 getString(IDS_SCREEN_NAME_IS_ALIAS).c_str(),
216 newName.c_str()));
217 return false;
218 }
219
220 // name must not exist in config but allow same name. also
221 // allow name if it exists in the old alias list but not the
222 // new one.
223 if (m_config->isScreen(newName) &&
224 !CStringUtil::CaselessCmp::equal(newName, m_name) &&
225 !isNameInList(oldAliases, newName)) {
226 showError(hwnd, CStringUtil::format(
227 getString(IDS_DUPLICATE_SCREEN_NAME).c_str(),
228 newName.c_str()));
229 return false;
230 }
231
232 // aliases must not exist in config but allow same aliases and
233 // allow an alias to be the old name.
234 for (CStringList::const_iterator index = newAliases.begin();
235 index != newAliases.end(); ++index) {
236 if (m_config->isScreen(*index) &&
237 !CStringUtil::CaselessCmp::equal(*index, m_name) &&
238 !isNameInList(oldAliases, *index)) {
239 showError(hwnd, CStringUtil::format(
240 getString(IDS_DUPLICATE_SCREEN_NAME).c_str(),
241 index->c_str()));
242 return false;
243 }
244 }
245
246 // dead corner size must be non-negative
247 child = getItem(hwnd, IDC_ADD_DC_SIZE);
248 CString valueString = getWindowText(child);
249 int cornerSize = atoi(valueString.c_str());
250 if (cornerSize < 0) {
251 showError(hwnd, CStringUtil::format(
252 getString(IDS_INVALID_CORNER_SIZE).c_str(),
253 valueString.c_str()));
254 SetFocus(child);
255 return false;
256 }
257
258 // collect options
259 child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK);
260 if (isItemChecked(child)) {
261 options[kOptionHalfDuplexCapsLock] = 1;
262 }
263 else {
264 options.erase(kOptionHalfDuplexCapsLock);
265 }
266 child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK);
267 if (isItemChecked(child)) {
268 options[kOptionHalfDuplexNumLock] = 1;
269 }
270 else {
271 options.erase(kOptionHalfDuplexNumLock);
272 }
273 child = getItem(hwnd, IDC_ADD_HD_SCROLL_CHECK);
274 if (isItemChecked(child)) {
275 options[kOptionHalfDuplexScrollLock] = 1;
276 }
277 else {
278 options.erase(kOptionHalfDuplexScrollLock);
279 }
280
281 // save modifier options
282 for (UInt32 i = 0; i < sizeof(s_modifiers) /
283 sizeof(s_modifiers[0]); ++i) {
284 child = getItem(hwnd, s_modifiers[i].m_ctrlID);
285 KeyModifierID id = static_cast<KeyModifierID>(
286 SendMessage(child, CB_GETCURSEL, 0, 0) +
287 baseModifier);
288 if (id != s_modifiers[i].m_modifierID) {
289 options[s_modifiers[i].m_optionID] = id;
290 }
291 else {
292 options.erase(s_modifiers[i].m_optionID);
293 }
294 }
295
296 // save dead corner options
297 UInt32 corners = 0;
298 if (isItemChecked(getItem(hwnd, IDC_ADD_DC_TOP_LEFT))) {
299 corners |= kTopLeftMask;
300 }
301 if (isItemChecked(getItem(hwnd, IDC_ADD_DC_TOP_RIGHT))) {
302 corners |= kTopRightMask;
303 }
304 if (isItemChecked(getItem(hwnd, IDC_ADD_DC_BOTTOM_LEFT))) {
305 corners |= kBottomLeftMask;
306 }
307 if (isItemChecked(getItem(hwnd, IDC_ADD_DC_BOTTOM_RIGHT))) {
308 corners |= kBottomRightMask;
309 }
310 options[kOptionScreenSwitchCorners] = corners;
311 options[kOptionScreenSwitchCornerSize] = cornerSize;
312
313 // save new data to config
314 if (m_name.empty()) {
315 // added screen
316 m_config->addScreen(newName);
317 }
318 else {
319 // edited screen
320 m_config->removeAliases(m_name);
321 m_config->removeOptions(m_name);
322 m_config->renameScreen(m_name, newName);
323 }
324 m_name = newName;
325 for (CStringList::const_iterator index = newAliases.begin();
326 index != newAliases.end(); ++index) {
327 m_config->addAlias(m_name, *index);
328 }
329 for (CConfig::CScreenOptions::const_iterator
330 index = options.begin();
331 index != options.end(); ++index) {
332 m_config->addOption(m_name, index->first, index->second);
333 }
334
335 return true;
336}
337
338BOOL
339CAddScreen::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
340{
341 switch (message) {
342 case WM_INITDIALOG:
343 init(hwnd);
344 return TRUE;
345
346 case WM_COMMAND:
347 switch (LOWORD(wParam)) {
348 case IDOK:
349 if (save(hwnd)) {
350 EndDialog(hwnd, 1);
351 }
352 return TRUE;
353
354 case IDCANCEL:
355 EndDialog(hwnd, 0);
356 return TRUE;
357 }
358 break;
359
360 default:
361 break;
362 }
363
364 return FALSE;
365}
366
367BOOL CALLBACK
368CAddScreen::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
369{
370 return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
371}
372
373void
374CAddScreen::getAliases(CStringList& aliases) const
375{
376 for (CConfig::all_const_iterator index = m_config->beginAll();
377 index != m_config->endAll(); ++index) {
378 if (CStringUtil::CaselessCmp::equal(index->second, m_name) &&
379 !CStringUtil::CaselessCmp::equal(index->second, index->first)) {
380 aliases.push_back(index->first);
381 }
382 }
383}
384
385void
386CAddScreen::getOptions(CConfig::CScreenOptions& optionsOut) const
387{
388 const CConfig::CScreenOptions* options = m_config->getOptions(m_name);
389 if (options == NULL) {
390 optionsOut = CConfig::CScreenOptions();
391 }
392 else {
393 optionsOut = *options;
394 }
395}
396
397void
398CAddScreen::tokenize(CStringList& tokens, const CString& src)
399{
400 // find first non-whitespace
401 CString::size_type x = src.find_first_not_of(" \t\r\n");
402 if (x == CString::npos) {
403 return;
404 }
405
406 // find next whitespace
407 do {
408 CString::size_type y = src.find_first_of(" \t\r\n", x);
409 if (y == CString::npos) {
410 y = src.size();
411 }
412 tokens.push_back(src.substr(x, y - x));
413 x = src.find_first_not_of(" \t\r\n", y);
414 } while (x != CString::npos);
415}
416
417bool
418CAddScreen::isNameInList(const CStringList& names, const CString& name)
419{
420 for (CStringList::const_iterator index = names.begin();
421 index != names.end(); ++index) {
422 if (CStringUtil::CaselessCmp::equal(name, *index)) {
423 return true;
424 }
425 }
426 return false;
427}
Note: See TracBrowser for help on using the repository browser.