blob: f4085b4d84c7892ec0ec5c4d323f5c00ab8bab19 [file] [log] [blame]
Constantin Kaplinsky729598c2006-05-25 05:12:25 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19#include <vncviewer/CConnOptions.h>
20#include <rfb/Configuration.h>
21#include <rfb/encodings.h>
22#include <rfb/LogWriter.h>
george82c439ebb2007-04-30 05:21:41 +000023#include <rfb/ScaleFilters.h>
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000024#include <rfb_win32/MsgBox.h>
25#include <rfb_win32/Registry.h>
Adam Tkac3fed5a42010-12-08 13:48:29 +000026#include <rfb/SecurityClient.h>
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000027#include <rdr/HexInStream.h>
28#include <rdr/HexOutStream.h>
29#include <stdlib.h>
30
31using namespace rfb;
32using namespace rfb::win32;
33
34static StringParameter passwordFile("PasswordFile",
35 "Password file for VNC authentication", "");
36
37// - Settings stored in the registry & in .vnc files, by Save Defaults and
38// Save Configuration respectively.
39
40static BoolParameter useLocalCursor("UseLocalCursor", "Render the mouse cursor locally", true);
41static BoolParameter useDesktopResize("UseDesktopResize", "Support dynamic desktop resizing", true);
42
43static BoolParameter fullColour("FullColor",
44 "Use full color", true);
45static AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour);
46
47static IntParameter lowColourLevel("LowColorLevel",
48 "Color level to use on slow connections. "
49 "0 = Very Low (8 colors), 1 = Low (64 colors), 2 = Medium (256 colors)",
50 2);
51static AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel);
52
53static BoolParameter fullScreen("FullScreen",
54 "Use the whole display to show the remote desktop."
55 "(Press F8 to access the viewer menu)",
56 false);
57static StringParameter preferredEncoding("PreferredEncoding",
58 "Preferred encoding to use (Tight, ZRLE, Hextile or"
59 " Raw)", "Tight");
60static BoolParameter autoSelect("AutoSelect",
61 "Auto select pixel format and encoding. "
62 "Default if PreferredEncoding and FullColor are not specified.",
63 true);
64static BoolParameter sharedConnection("Shared",
65 "Allow existing connections to the server to continue."
66 "(Default is to disconnect all other clients)",
67 false);
68
Pierre Ossmand6d19942009-03-24 12:29:50 +000069StringParameter desktopSize("DesktopSize",
70 "Reconfigure desktop size on the server on "
71 "connect (if possible)", "");
72
Constantin Kaplinsky729598c2006-05-25 05:12:25 +000073static BoolParameter sendPtrEvents("SendPointerEvents",
74 "Send pointer (mouse) events to the server.", true);
75static BoolParameter sendKeyEvents("SendKeyEvents",
76 "Send key presses (and releases) to the server.", true);
77
78static BoolParameter clientCutText("ClientCutText",
79 "Send clipboard changes to the server.", true);
80static BoolParameter serverCutText("ServerCutText",
81 "Accept clipboard changes from the server.", true);
82
83static BoolParameter disableWinKeys("DisableWinKeys",
84 "Pass special Windows keys directly to the server.", true);
85
86static BoolParameter protocol3_3("Protocol3.3",
87 "Only use protocol version 3.3", false);
88
89static IntParameter ptrEventInterval("PointerEventInterval",
90 "The interval to delay between sending one pointer event "
91 "and the next.", 0);
92static BoolParameter emulate3("Emulate3",
93 "Emulate middle mouse button when left and right buttons "
94 "are used simulatenously.", false);
95
96static BoolParameter acceptBell("AcceptBell",
97 "Produce a system beep when requested to by the server.",
98 true);
99
100static BoolParameter showToolbar("ShowToolbar", "Show toolbar by default.", true);
101
102static StringParameter monitor("Monitor", "The monitor to open the VNC Viewer window on, if available.", "");
103static StringParameter menuKey("MenuKey", "The key which brings up the popup menu", "F8");
104static BoolParameter autoReconnect("AutoReconnect", "Offer to reconnect to the remote server if the connection"
105 "is dropped because an error occurs.", true);
106
107static BoolParameter customCompressLevel("CustomCompressLevel",
108 "Use custom compression level. "
109 "Default if CompressLevel is specified.", false);
110
111static IntParameter compressLevel("CompressLevel",
112 "Use specified compression level"
113 "0 = Low, 9 = High",
114 6);
115
116static BoolParameter noJpeg("NoJPEG",
117 "Disable lossy JPEG compression in Tight encoding.",
118 false);
119
120static IntParameter qualityLevel("QualityLevel",
121 "JPEG quality level. "
122 "0 = Low, 9 = High",
Pierre Ossman7dfa22e2009-03-12 13:03:22 +0000123 8);
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000124
george82444e8862006-05-27 10:21:28 +0000125static BoolParameter autoScaling("AutoScaling",
126 "Auto rescale local copy of the remote desktop to the client window.",
127 false);
128static IntParameter scale("Scale",
129 "Scale local copy of the remote desktop, in percent",
130 100);
131
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000132CConnOptions::CConnOptions()
Peter Åstranda850e642008-12-11 09:04:02 +0000133: useLocalCursor (::useLocalCursor),
134useDesktopResize(::useDesktopResize),
135fullScreen(::fullScreen),
136fullColour(::fullColour),
137lowColourLevel(::lowColourLevel),
Pierre Ossman7dfa22e2009-03-12 13:03:22 +0000138preferredEncoding(encodingTight),
Peter Åstranda850e642008-12-11 09:04:02 +0000139autoSelect(::autoSelect),
140shared(::sharedConnection),
Pierre Ossmand6d19942009-03-24 12:29:50 +0000141desktopSize(::desktopSize.getData()),
Peter Åstranda850e642008-12-11 09:04:02 +0000142sendPtrEvents(::sendPtrEvents),
143sendKeyEvents(::sendKeyEvents),
144showToolbar(::showToolbar),
145clientCutText(::clientCutText),
146serverCutText(::serverCutText),
147disableWinKeys(::disableWinKeys),
148emulate3(::emulate3),
149pointerEventInterval(ptrEventInterval),
150protocol3_3(::protocol3_3),
151acceptBell(::acceptBell),
152autoScaling(::autoScaling),
153scale(::scale),
154monitor(::monitor.getData()),
155autoReconnect(::autoReconnect),
156customCompressLevel(::customCompressLevel),
157compressLevel(::compressLevel),
158noJpeg(::noJpeg),
Peter Åstrandf7d04362008-12-11 10:13:02 +0000159qualityLevel(::qualityLevel),
160passwordFile(::passwordFile.getData())
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000161{
Adam Tkac3fed5a42010-12-08 13:48:29 +0000162 char *sectypes;
163
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000164 if (autoSelect) {
Pierre Ossman7dfa22e2009-03-12 13:03:22 +0000165 preferredEncoding = encodingTight;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000166 } else {
167 CharArray encodingName(::preferredEncoding.getData());
168 preferredEncoding = encodingNum(encodingName.buf);
169 }
170 setMenuKey(CharArray(::menuKey.getData()).buf);
171
172 if (!::autoSelect.hasBeenSet()) {
173 // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
174 autoSelect = (!::preferredEncoding.hasBeenSet()
175 && !::fullColour.hasBeenSet()
176 && !::fullColourAlias.hasBeenSet());
177 }
178 if (!::customCompressLevel.hasBeenSet()) {
179 // Default to CustomCompressLevel=1 if CompressLevel is used.
180 customCompressLevel = ::compressLevel.hasBeenSet();
181 }
Adam Tkac3fed5a42010-12-08 13:48:29 +0000182
183 sectypes = SecurityClient::secTypes.getDefaultStr();
184 secTypes = parseSecTypes(sectypes);
185 delete [] sectypes;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000186}
187
188
189void CConnOptions::readFromFile(const char* filename) {
190 FILE* f = fopen(filename, "r");
191 if (!f)
192 throw rdr::Exception("Failed to read configuration file");
193
194 try {
195 char line[4096];
196 CharArray section;
197
198 CharArray hostTmp;
199 int portTmp = 0;
200
201 while (!feof(f)) {
202 // Read the next line
203 if (!fgets(line, sizeof(line), f)) {
204 if (feof(f))
205 break;
206 throw rdr::SystemException("fgets", ferror(f));
207 }
208 int len=strlen(line);
209 if (line[len-1] == '\n') {
210 line[len-1] = 0;
211 len--;
212 }
213
214 // Process the line
215 if (line[0] == ';') {
216 // Comment
217 } else if (line[0] == '[') {
218 // Entering a new section
219 if (!strSplit(&line[1], ']', &section.buf, 0))
220 throw rdr::Exception("bad Section");
221 } else {
222 // Reading an option
223 CharArray name;
224 CharArray value;
225 if (!strSplit(line, '=', &name.buf, &value.buf))
226 throw rdr::Exception("bad Name/Value pair");
227
228 if (stricmp(section.buf, "Connection") == 0) {
229 if (stricmp(name.buf, "Host") == 0) {
230 hostTmp.replaceBuf(value.takeBuf());
231 } else if (stricmp(name.buf, "Port") == 0) {
232 portTmp = atoi(value.buf);
233 } else if (stricmp(name.buf, "UserName") == 0) {
234 userName.replaceBuf(value.takeBuf());
235 } else if (stricmp(name.buf, "Password") == 0) {
236 ObfuscatedPasswd obfPwd;
237 rdr::HexInStream::hexStrToBin(value.buf, (char**)&obfPwd.buf, &obfPwd.length);
238 PlainPasswd passwd(obfPwd);
239 password.replaceBuf(passwd.takeBuf());
240 }
241 } else if (stricmp(section.buf, "Options") == 0) {
242 // V4 options
243 if (stricmp(name.buf, "UseLocalCursor") == 0) {
244 useLocalCursor = atoi(value.buf);
245 } else if (stricmp(name.buf, "UseDesktopResize") == 0) {
246 useDesktopResize = atoi(value.buf);
247 } else if (stricmp(name.buf, "FullScreen") == 0) {
248 fullScreen = atoi(value.buf);
249 } else if (stricmp(name.buf, "FullColour") == 0) {
250 fullColour = atoi(value.buf);
251 } else if (stricmp(name.buf, "LowColourLevel") == 0) {
252 lowColourLevel = atoi(value.buf);
253 } else if (stricmp(name.buf, "PreferredEncoding") == 0) {
254 preferredEncoding = encodingNum(value.buf);
255 } else if ((stricmp(name.buf, "AutoDetect") == 0) ||
256 (stricmp(name.buf, "AutoSelect") == 0)) {
257 autoSelect = atoi(value.buf);
258 } else if (stricmp(name.buf, "Shared") == 0) {
259 shared = atoi(value.buf);
260 } else if (stricmp(name.buf, "SendPtrEvents") == 0) {
261 sendPtrEvents = atoi(value.buf);
262 } else if (stricmp(name.buf, "SendKeyEvents") == 0) {
263 sendKeyEvents = atoi(value.buf);
264 } else if (stricmp(name.buf, "SendCutText") == 0) {
265 clientCutText = atoi(value.buf);
266 } else if (stricmp(name.buf, "AcceptCutText") == 0) {
267 serverCutText = atoi(value.buf);
268 } else if (stricmp(name.buf, "DisableWinKeys") == 0) {
269 disableWinKeys = atoi(value.buf);
270 } else if (stricmp(name.buf, "AcceptBell") == 0) {
271 acceptBell = atoi(value.buf);
272 } else if (stricmp(name.buf, "Emulate3") == 0) {
273 emulate3 = atoi(value.buf);
274 } else if (stricmp(name.buf, "ShowToolbar") == 0) {
275 showToolbar = atoi(value.buf);
276 } else if (stricmp(name.buf, "PointerEventInterval") == 0) {
277 pointerEventInterval = atoi(value.buf);
278 } else if (stricmp(name.buf, "Monitor") == 0) {
279 monitor.replaceBuf(value.takeBuf());
280 } else if (stricmp(name.buf, "MenuKey") == 0) {
281 setMenuKey(value.buf);
282 } else if (stricmp(name.buf, "AutoReconnect") == 0) {
283 autoReconnect = atoi(value.buf);
284
285 } else if (stricmp(name.buf, "CustomCompressLevel") == 0) {
286 customCompressLevel = atoi(value.buf);
287 } else if (stricmp(name.buf, "CompressLevel") == 0) {
288 compressLevel = atoi(value.buf);
289 } else if (stricmp(name.buf, "NoJPEG") == 0) {
290 noJpeg = atoi(value.buf);
291 } else if (stricmp(name.buf, "QualityLevel") == 0) {
292 qualityLevel = atoi(value.buf);
293 // Legacy options
294 } else if (stricmp(name.buf, "Preferred_Encoding") == 0) {
295 preferredEncoding = atoi(value.buf);
296 } else if (stricmp(name.buf, "8bit") == 0) {
297 fullColour = !atoi(value.buf);
298 } else if (stricmp(name.buf, "FullScreen") == 0) {
299 fullScreen = atoi(value.buf);
300 } else if (stricmp(name.buf, "ViewOnly") == 0) {
301 sendPtrEvents = sendKeyEvents = !atoi(value.buf);
302 } else if (stricmp(name.buf, "DisableClipboard") == 0) {
303 clientCutText = serverCutText = !atoi(value.buf);
george82444e8862006-05-27 10:21:28 +0000304 } else if (stricmp(name.buf, "AutoScaling") == 0) {
305 autoScaling = atoi(value.buf);
306 } else if (stricmp(name.buf, "Scale") == 0) {
307 scale = atoi(value.buf);
Adam Tkac3fed5a42010-12-08 13:48:29 +0000308 } else if (stricmp(name.buf, "SecurityTypes") == 0) {
309 secTypes = parseSecTypes(value.buf);
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000310 }
311 }
312 }
313 }
314 fclose(f); f=0;
315
316 // Process the Host and Port
317 if (hostTmp.buf) {
318 int hostLen = strlen(hostTmp.buf) + 2 + 17;
319 host.replaceBuf(new char[hostLen]);
320 strCopy(host.buf, hostTmp.buf, hostLen);
321 if (portTmp) {
322 strncat(host.buf, "::", hostLen-1);
323 char tmp[16];
324 sprintf(tmp, "%d", portTmp);
325 strncat(host.buf, tmp, hostLen-1);
326 }
327 }
328
329 // If AutoSelect is enabled then override the preferred encoding
330 if (autoSelect)
331 preferredEncoding = encodingZRLE;
332
333 setConfigFileName(filename);
334 } catch (rdr::Exception&) {
335 if (f) fclose(f);
336 throw;
337 }
338}
339
340void CConnOptions::writeToFile(const char* filename) {
341 FILE* f = fopen(filename, "w");
342 if (!f)
343 throw rdr::Exception("Failed to write configuration file");
344
345 try {
346 // - Split server into host and port and save
347 fprintf(f, "[Connection]\n");
348
349 fprintf(f, "Host=%s\n", host.buf);
350 if (userName.buf)
351 fprintf(f, "UserName=%s\n", userName.buf);
352 if (password.buf) {
353 // - Warn the user before saving the password
354 if (MsgBox(0, _T("Do you want to include the VNC Password in this configuration file?\n")
355 _T("Storing the password is more convenient but poses a security risk."),
356 MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDYES) {
357 ObfuscatedPasswd obfPwd(password);
Peter Åstrandb22dbef2008-12-09 14:57:53 +0000358 CharArray obfuscatedHex(rdr::HexOutStream::binToHexStr(obfPwd.buf, obfPwd.length));
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000359 fprintf(f, "Password=%s\n", obfuscatedHex.buf);
360 }
361 }
362
363 // - Save the other options
364 fprintf(f, "[Options]\n");
365
366 fprintf(f, "UseLocalCursor=%d\n", (int)useLocalCursor);
367 fprintf(f, "UseDesktopResize=%d\n", (int)useDesktopResize);
368 fprintf(f, "FullScreen=%d\n", (int)fullScreen);
369 fprintf(f, "FullColour=%d\n", (int)fullColour);
370 fprintf(f, "LowColourLevel=%d\n", lowColourLevel);
371 fprintf(f, "PreferredEncoding=%s\n", encodingName(preferredEncoding));
372 fprintf(f, "AutoSelect=%d\n", (int)autoSelect);
373 fprintf(f, "Shared=%d\n", (int)shared);
374 fprintf(f, "SendPtrEvents=%d\n", (int)sendPtrEvents);
375 fprintf(f, "SendKeyEvents=%d\n", (int)sendKeyEvents);
376 fprintf(f, "SendCutText=%d\n", (int)clientCutText);
377 fprintf(f, "AcceptCutText=%d\n", (int)serverCutText);
378 fprintf(f, "DisableWinKeys=%d\n", (int)disableWinKeys);
379 fprintf(f, "AcceptBell=%d\n", (int)acceptBell);
380 fprintf(f, "Emulate3=%d\n", (int)emulate3);
381 fprintf(f, "ShowToolbar=%d\n", (int)showToolbar);
382 fprintf(f, "PointerEventInterval=%d\n", pointerEventInterval);
383 if (monitor.buf)
384 fprintf(f, "Monitor=%s\n", monitor.buf);
385 fprintf(f, "MenuKey=%s\n", CharArray(menuKeyName()).buf);
386 fprintf(f, "AutoReconnect=%d\n", (int)autoReconnect);
387 fprintf(f, "CustomCompressLevel=%d\n", customCompressLevel);
388 fprintf(f, "CompressLevel=%d\n", compressLevel);
389 fprintf(f, "NoJPEG=%d\n", noJpeg);
390 fprintf(f, "QualityLevel=%d\n", qualityLevel);
george82444e8862006-05-27 10:21:28 +0000391 fprintf(f, "AutoScaling=%d\n", (int)autoScaling);
392 fprintf(f, "Scale=%d\n", scale);
Adam Tkac3fed5a42010-12-08 13:48:29 +0000393
394 fprintf(f, "SecurityTypes=");
395 std::list<rdr::U32>::iterator i;
396 for (i = secTypes.begin(); i != secTypes.end(); i++)
397 fprintf(f, "%s,", secTypeName(*i));
398 fprintf(f, "\n");
399
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000400 fclose(f); f=0;
401
402 setConfigFileName(filename);
403 } catch (rdr::Exception&) {
404 if (f) fclose(f);
405 throw;
406 }
407}
408
409
410void CConnOptions::writeDefaults() {
411 RegKey key;
Peter Åstrand4eacc022009-02-27 10:12:14 +0000412 key.createKey(HKEY_CURRENT_USER, _T("Software\\TigerVNC\\VNCviewer4"));
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000413 key.setBool(_T("UseLocalCursor"), useLocalCursor);
414 key.setBool(_T("UseDesktopResize"), useDesktopResize);
415 key.setBool(_T("FullScreen"), fullScreen);
416 key.setBool(_T("FullColour"), fullColour);
417 key.setInt(_T("LowColourLevel"), lowColourLevel);
418 key.setString(_T("PreferredEncoding"), TStr(encodingName(preferredEncoding)));
419 key.setBool(_T("AutoSelect"), autoSelect);
420 key.setBool(_T("Shared"), shared);
421 key.setBool(_T("SendPointerEvents"), sendPtrEvents);
422 key.setBool(_T("SendKeyEvents"), sendKeyEvents);
423 key.setBool(_T("ClientCutText"), clientCutText);
424 key.setBool(_T("ServerCutText"), serverCutText);
425 key.setBool(_T("DisableWinKeys"), disableWinKeys);
426 key.setBool(_T("Protocol3.3"), protocol3_3);
427 key.setBool(_T("AcceptBell"), acceptBell);
428 key.setBool(_T("ShowToolbar"), showToolbar);
429 key.setBool(_T("Emulate3"), emulate3);
430 key.setInt(_T("PointerEventInterval"), pointerEventInterval);
431 if (monitor.buf)
432 key.setString(_T("Monitor"), TStr(monitor.buf));
433 key.setString(_T("MenuKey"), TCharArray(menuKeyName()).buf);
434 key.setBool(_T("AutoReconnect"), autoReconnect);
435 key.setInt(_T("CustomCompressLevel"), customCompressLevel);
436 key.setInt(_T("CompressLevel"), compressLevel);
437 key.setInt(_T("NoJPEG"), noJpeg);
438 key.setInt(_T("QualityLevel"), qualityLevel);
george82444e8862006-05-27 10:21:28 +0000439 key.setBool(_T("AutoScaling"), autoScaling);
440 key.setInt(_T("Scale"), scale);
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000441}
442
443
444void CConnOptions::setUserName(const char* user) {userName.replaceBuf(strDup(user));}
445void CConnOptions::setPassword(const char* pwd) {password.replaceBuf(strDup(pwd));}
446void CConnOptions::setConfigFileName(const char* cfn) {configFileName.replaceBuf(strDup(cfn));}
447void CConnOptions::setHost(const char* h) {host.replaceBuf(strDup(h));}
448void CConnOptions::setMonitor(const char* m) {monitor.replaceBuf(strDup(m));}
449
450void CConnOptions::setMenuKey(const char* keyName) {
451 if (!keyName[0]) {
452 menuKey = 0;
453 } else {
454 menuKey = VK_F8;
455 if (keyName[0] == 'F') {
456 UINT fKey = atoi(&keyName[1]);
457 if (fKey >= 1 && fKey <= 12)
458 menuKey = fKey-1 + VK_F1;
459 }
460 }
461}
462char* CConnOptions::menuKeyName() {
463 int fNum = (menuKey-VK_F1)+1;
464 if (fNum<1 || fNum>12)
465 return strDup("");
466 CharArray menuKeyStr(4);
467 sprintf(menuKeyStr.buf, "F%d", fNum);
468 return menuKeyStr.takeBuf();
469}
470
471
472CConnOptions& CConnOptions::operator=(const CConnOptions& o) {
473 useLocalCursor = o.useLocalCursor;
474 useDesktopResize = o.useDesktopResize;
475 fullScreen = o.fullScreen;
476 fullColour = o.fullColour;
477 lowColourLevel = o.lowColourLevel;
478 preferredEncoding = o.preferredEncoding;
479 autoSelect = o.autoSelect;
480 shared = o.shared;
481 sendPtrEvents = o.sendPtrEvents;
482 sendKeyEvents = o.sendKeyEvents;
483 clientCutText = o.clientCutText;
484 serverCutText = o.serverCutText;
485 disableWinKeys = o.disableWinKeys;
486 emulate3 = o.emulate3;
487 pointerEventInterval = o.pointerEventInterval;
488 protocol3_3 = o.protocol3_3;
489 acceptBell = o.acceptBell;
490 showToolbar = o.showToolbar;
491 setUserName(o.userName.buf);
492 setPassword(o.password.buf);
493 setConfigFileName(o.configFileName.buf);
494 setHost(o.host.buf);
495 setMonitor(o.monitor.buf);
496 menuKey = o.menuKey;
497 autoReconnect = o.autoReconnect;
498 customCompressLevel = o.customCompressLevel;
499 compressLevel = o.compressLevel;
500 noJpeg = o.noJpeg;
501 qualityLevel = o.qualityLevel;
george82444e8862006-05-27 10:21:28 +0000502 autoScaling = o.autoScaling;
503 scale = o.scale;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000504
505 return *this;
506}