~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xwin/xlaunch/main.cc

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2005 Alexander Gottwald
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice shall be included in
 
12
 * all copies or substantial portions of the Software.
 
13
 *
 
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 
17
 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
18
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
19
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
20
 * DEALINGS IN THE SOFTWARE.
 
21
 *
 
22
 * Except as contained in this notice, the name(s) of the above copyright
 
23
 * holders shall not be used in advertising or otherwise to promote the sale,
 
24
 * use or other dealings in this Software without prior written authorization.
 
25
 */
 
26
#include "window/util.h"
 
27
#include "window/wizard.h"
 
28
#include "resources/resources.h"
 
29
#include "config.h"
 
30
#include <prsht.h>
 
31
#include <commctrl.h>
 
32
 
 
33
#include <stdexcept>
 
34
 
 
35
#include <X11/Xlib.h>
 
36
 
 
37
/// @brief Send WM_ENDSESSION to all program windows.
 
38
/// This will shutdown the started xserver
 
39
BOOL CALLBACK KillWindowsProc(HWND hwnd, LPARAM lParam)
 
40
{
 
41
    SendMessage(hwnd, WM_ENDSESSION, 0, 0);
 
42
    return TRUE;
 
43
}
 
44
 
 
45
/// @brief Actual wizard implementation.
 
46
/// This is based on generic CWizard but handles the special dialogs
 
47
class CMyWizard : public CWizard 
 
48
{
 
49
    public:
 
50
    private:
 
51
        CConfig config; /// Storage for config options.
 
52
    public:
 
53
        /// @brief Constructor.
 
54
        /// Set wizard pages.
 
55
        CMyWizard() : CWizard() 
 
56
        {
 
57
            AddPage(IDD_DISPLAY, IDS_DISPLAY_TITLE, IDS_DISPLAY_SUBTITLE);
 
58
            AddPage(IDD_CLIENTS, IDS_CLIENTS_TITLE, IDS_CLIENTS_SUBTITLE);
 
59
            AddPage(IDD_PROGRAM, IDS_PROGRAM_TITLE, IDS_PROGRAM_SUBTITLE);
 
60
            AddPage(IDD_XDMCP, IDS_XDMCP_TITLE, IDS_XDMCP_SUBTITLE);
 
61
            //AddPage(IDD_FONTPATH, IDS_FONTPATH_TITLE, IDS_FONTPATH_SUBTITLE);
 
62
            AddPage(IDD_CLIPBOARD, IDS_CLIPBOARD_TITLE, IDS_CLIPBOARD_SUBTITLE);
 
63
            AddPage(IDD_FINISH, IDS_FINISH_TITLE, IDS_FINISH_SUBTITLE);
 
64
        }
 
65
 
 
66
        virtual void LoadConfig(const char *filename)
 
67
        {
 
68
            try {
 
69
                config.Load(filename);
 
70
            } catch (std::runtime_error &e)
 
71
            {
 
72
                printf("Fehler: %s\n", e.what());
 
73
            }
 
74
        }
 
75
 
 
76
        /// @brief Handle the PSN_WIZNEXT message.
 
77
        /// @param hwndDlg Handle to active page dialog.
 
78
        /// @param index Index of current page.
 
79
        /// @return TRUE if the message was handled. FALSE otherwise. 
 
80
        virtual BOOL WizardNext(HWND hwndDlg, unsigned index)
 
81
        {
 
82
#ifdef _DEBUG
 
83
            printf("%s %d\n", __FUNCTION__, index);
 
84
#endif
 
85
            switch (PageID(index))
 
86
            {
 
87
                case IDD_DISPLAY:
 
88
                    // Check for select window mode
 
89
                    if (IsDlgButtonChecked(hwndDlg, IDC_MULTIWINDOW))
 
90
                        config.window = CConfig::MultiWindow;
 
91
                    else if (IsDlgButtonChecked(hwndDlg, IDC_FULLSCREEN))
 
92
                        config.window = CConfig::Fullscreen;
 
93
                    else if (IsDlgButtonChecked(hwndDlg, IDC_WINDOWED))
 
94
                        config.window = CConfig::Windowed;
 
95
                    else if (IsDlgButtonChecked(hwndDlg, IDC_NODECORATION))
 
96
                        config.window = CConfig::Nodecoration;
 
97
                    else
 
98
                    {
 
99
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, -1);
 
100
                        return TRUE;
 
101
                    }
 
102
                    // Get selected display number
 
103
                    {
 
104
                        char buffer[512];
 
105
                        GetDlgItemText(hwndDlg, IDC_DISPLAY, buffer, 512);
 
106
                        buffer[511] = 0;
 
107
                        config.display = buffer;
 
108
                    }
 
109
                    // Check for valid input
 
110
                    if (config.display.empty())
 
111
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, -1);
 
112
                    else
 
113
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIENTS);
 
114
                    return TRUE;
 
115
                case IDD_CLIENTS:
 
116
                    // Check for select client startup method
 
117
                    if (IsDlgButtonChecked(hwndDlg, IDC_CLIENT))
 
118
                    {
 
119
                        config.client = CConfig::StartProgram;
 
120
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_PROGRAM);
 
121
                    } else if (IsDlgButtonChecked(hwndDlg, IDC_XDMCP))
 
122
                    {
 
123
                        config.client = CConfig::XDMCP;
 
124
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_XDMCP);
 
125
                    } else if (IsDlgButtonChecked(hwndDlg, IDC_CLIENT_NONE))
 
126
                    {
 
127
                        config.client = CConfig::NoClient;
 
128
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIPBOARD);
 
129
                    } else
 
130
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, -1);
 
131
                    return TRUE;
 
132
                case IDD_PROGRAM:
 
133
                    // Check wether local or remote client should be started
 
134
                    if (IsDlgButtonChecked(hwndDlg, IDC_CLIENT_LOCAL))
 
135
                        config.local = true;
 
136
                    else if (IsDlgButtonChecked(hwndDlg, IDC_CLIENT_REMOTE))
 
137
                        config.local = false;
 
138
                    else
 
139
                    {
 
140
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, -1);
 
141
                        return TRUE;
 
142
                    }
 
143
                    // Read program, user and host name
 
144
                    {
 
145
                        char buffer[512];
 
146
                        GetDlgItemText(hwndDlg, IDC_CLIENT_USER, buffer, 512);
 
147
                        buffer[511] = 0;
 
148
                        config.user = buffer;
 
149
                        GetDlgItemText(hwndDlg, IDC_CLIENT_HOST, buffer, 512);
 
150
                        buffer[511] = 0;
 
151
                        config.host = buffer;
 
152
                        GetDlgItemText(hwndDlg, IDC_CLIENT_PROGRAM, buffer, 512);
 
153
                        buffer[511] = 0;
 
154
                        config.program = buffer;
 
155
                    }
 
156
                    // Check for valid input
 
157
                    if (!config.local && (config.host.empty() || config.program.empty()))
 
158
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, -1);
 
159
                    else
 
160
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIPBOARD);
 
161
                    return TRUE;
 
162
                case IDD_XDMCP:
 
163
                    // Check for broadcast
 
164
                    if (IsDlgButtonChecked(hwndDlg, IDC_XDMCP_BROADCAST))
 
165
                        config.broadcast = true;
 
166
                    else if (IsDlgButtonChecked(hwndDlg, IDC_XDMCP_QUERY))
 
167
                        config.broadcast = false;
 
168
                    else
 
169
                    {
 
170
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, -1);
 
171
                        return TRUE;
 
172
                    }
 
173
                    // Check for indirect mode
 
174
                    if (IsDlgButtonChecked(hwndDlg, IDC_XDMCP_INDIRECT))
 
175
                        config.indirect = true;
 
176
                    else
 
177
                        config.indirect = false;
 
178
                    // Read hostname
 
179
                    {
 
180
                        char buffer[512];
 
181
                        GetDlgItemText(hwndDlg, IDC_XDMCP_HOST, buffer, 512);
 
182
                        buffer[511] = 0;
 
183
                        config.xdmcp_host = buffer;
 
184
                    }
 
185
                    // Check for valid input
 
186
                    if (!config.broadcast && config.xdmcp_host.empty())
 
187
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, -1);
 
188
                    else        
 
189
                        SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIPBOARD);
 
190
                    return TRUE;
 
191
                case IDD_CLIPBOARD:
 
192
                    // check for clipboard
 
193
                    if (IsDlgButtonChecked(hwndDlg, IDC_CLIPBOARD))
 
194
                        config.clipboard = true;
 
195
                    else
 
196
                        config.clipboard = false;
 
197
                    // read parameters
 
198
                    {
 
199
                        char buffer[512];
 
200
                        GetDlgItemText(hwndDlg, IDC_EXTRA_PARAMS, buffer, 512);
 
201
                        buffer[511] = 0;
 
202
                        config.extra_params = buffer;
 
203
                    }
 
204
                    SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_FINISH);
 
205
                    return TRUE;
 
206
                default:
 
207
                    break;
 
208
            }
 
209
            return FALSE;
 
210
        }
 
211
        /// @brief Handle PSN_WIZFINISH message.
 
212
        /// @param hwndDlg Handle to active page dialog.
 
213
        /// @param index Index of current page.
 
214
        /// @return TRUE if the message was handled. FALSE otherwise. 
 
215
        virtual BOOL WizardFinish(HWND hwndDlg, unsigned index)
 
216
        {
 
217
#ifdef _DEBUG
 
218
            printf("finish %d\n", index);
 
219
#endif
 
220
            return FALSE;
 
221
        }
 
222
        /// @brief Handle PSN_WIZBACK message.
 
223
        /// Basicly handles switching to proper page (skipping XDMCP or program page
 
224
        /// if required).
 
225
        /// @param hwndDlg Handle to active page dialog.
 
226
        /// @param index Index of current page.
 
227
        /// @return TRUE if the message was handled. FALSE otherwise. 
 
228
        virtual BOOL WizardBack(HWND hwndDlg, unsigned index)
 
229
        {
 
230
            switch (PageID(index))
 
231
            {
 
232
                case IDD_PROGRAM:
 
233
                case IDD_XDMCP:
 
234
                    SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIENTS);
 
235
                    return TRUE;
 
236
                case IDD_FONTPATH:
 
237
                case IDD_CLIPBOARD: // temporary. fontpath is disabled
 
238
                    switch (config.client)
 
239
                    {
 
240
                        case CConfig::NoClient: 
 
241
                            SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIENTS);
 
242
                            return TRUE;
 
243
                        case CConfig::StartProgram:
 
244
                            SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_PROGRAM);
 
245
                            return TRUE;
 
246
                        case CConfig::XDMCP:
 
247
                            SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_XDMCP);
 
248
                            return TRUE;
 
249
                    }
 
250
                    break;
 
251
            }
 
252
            return FALSE;
 
253
        }
 
254
        /// @brief Handle PSN_SETACTIVE message.
 
255
        /// @param hwndDlg Handle to active page dialog.
 
256
        /// @param index Index of current page.
 
257
        /// @return TRUE if the message was handled. FALSE otherwise. 
 
258
        virtual BOOL WizardActivate(HWND hwndDlg, unsigned index)
 
259
        {
 
260
#ifdef _DEBUG
 
261
            printf("%s %d\n", __FUNCTION__, index);
 
262
#endif
 
263
            switch (PageID(index))
 
264
            {
 
265
                case IDD_CLIENTS:
 
266
                    // Enable or disable XDMCP radiobutton and text
 
267
                    EnableWindow(GetDlgItem(hwndDlg, IDC_XDMCP), config.window != CConfig::MultiWindow);
 
268
                    EnableWindow(GetDlgItem(hwndDlg, IDC_XDMCP_DESC), config.window != CConfig::MultiWindow);
 
269
                    break;
 
270
            }
 
271
            return FALSE;
 
272
        }
 
273
    protected:
 
274
        /// @brief Enable or disable the control for remote clients.
 
275
        /// @param hwndDlg Handle to active page dialog.
 
276
        /// @param state State of control group.
 
277
        void EnableRemoteProgramGroup(HWND hwndDlg, BOOL state)
 
278
        {
 
279
            EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_PROTOCOL), state);
 
280
            EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_HOST), state);
 
281
            EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_USER), state);
 
282
            EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_PROTOCOL_DESC), state);
 
283
            EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_HOST_DESC), state);
 
284
            EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_USER_DESC), state);
 
285
        }
 
286
        /// @brief Enable or disable the control for XDMCP connection.
 
287
        /// @param hwndDlg Handle to active page dialog.
 
288
        /// @param state State of control group.
 
289
        void EnableXDMCPQueryGroup(HWND hwndDlg, BOOL state)
 
290
        {
 
291
            EnableWindow(GetDlgItem(hwndDlg, IDC_XDMCP_HOST), state);
 
292
            EnableWindow(GetDlgItem(hwndDlg, IDC_XDMCP_INDIRECT), state);
 
293
        }
 
294
        /// @brief Fill program box with default values.
 
295
        /// @param hwndDlg Handle to active page dialog.
 
296
        void FillProgramBox(HWND hwndDlg)
 
297
        {
 
298
            HWND cbwnd = GetDlgItem(hwndDlg, IDC_CLIENT_PROGRAM);
 
299
            if (cbwnd == NULL)
 
300
                return;
 
301
            SendMessage(cbwnd, CB_RESETCONTENT, 0, 0);
 
302
            SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "xterm");
 
303
            SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "startkde");
 
304
            SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "gnome-session");
 
305
            SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) ".xinitrc");
 
306
            SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "wmaker");
 
307
            SendMessage(cbwnd, CB_SETCURSEL, 0, 0);
 
308
        }
 
309
        /// @brief Fill protocol box with default values.
 
310
        /// @param hwndDlg Handle to active page dialog.
 
311
        void FillProtocolBox(HWND hwndDlg)
 
312
        {
 
313
            HWND cbwnd = GetDlgItem(hwndDlg, IDC_CLIENT_PROTOCOL);
 
314
            if (cbwnd == NULL)
 
315
                return;
 
316
            SendMessage(cbwnd, CB_RESETCONTENT, 0, 0);
 
317
            SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "Putty");
 
318
            //SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "OpenSSH");
 
319
            SendMessage(cbwnd, CB_SETCURSEL, 0, 0);
 
320
        }
 
321
        void ShowSaveDialog(HWND parent)
 
322
        {
 
323
            char szTitle[512];
 
324
            char szFilter[512];
 
325
            char szFileTitle[512];
 
326
            char szFile[MAX_PATH];
 
327
            HINSTANCE hInst = GetModuleHandle(NULL);
 
328
            
 
329
            LoadString(hInst, IDS_SAVE_TITLE, szTitle, sizeof(szTitle));
 
330
            LoadString(hInst, IDS_SAVE_FILETITLE, szFileTitle, sizeof(szFileTitle));
 
331
            LoadString(hInst, IDS_SAVE_FILTER, szFilter, sizeof(szFilter));
 
332
            for (unsigned i=0; szFilter[i]; i++) 
 
333
                if (szFilter[i] == '%') 
 
334
                    szFilter[i] = '\0'; 
 
335
 
 
336
            strcpy(szFile, "config.xlaunch");
 
337
 
 
338
            OPENFILENAME ofn;
 
339
            memset(&ofn, 0, sizeof(OPENFILENAME));
 
340
            ofn.lStructSize = sizeof(OPENFILENAME); 
 
341
            ofn.hwndOwner = parent; 
 
342
            ofn.lpstrFilter = szFilter; 
 
343
            ofn.lpstrFile= szFile; 
 
344
            ofn.nMaxFile = sizeof(szFile)/ sizeof(*szFile); 
 
345
            ofn.lpstrFileTitle = szFileTitle; 
 
346
            ofn.nMaxFileTitle = sizeof(szFileTitle); 
 
347
            ofn.lpstrInitialDir = (LPSTR)NULL; 
 
348
            ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT; 
 
349
            ofn.lpstrTitle = szTitle;
 
350
 
 
351
            if (GetSaveFileName(&ofn))
 
352
            {
 
353
                try {
 
354
                    config.Save(ofn.lpstrFile);
 
355
                } catch (std::runtime_error &e)
 
356
                {
 
357
                    printf("Fehler: %s\n", e.what());
 
358
                }
 
359
            } 
 
360
        }
 
361
    public:
 
362
           
 
363
        /// @brief Handle messages fo the dialog pages.
 
364
        /// @param hwndDlg Handle of active dialog.
 
365
        /// @param uMsg Message code.
 
366
        /// @param wParam Message parameter.
 
367
        /// @param lParam Message parameter.
 
368
        /// @param psp Handle to sheet paramters. 
 
369
        virtual INT_PTR PageDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, PROPSHEETPAGE *psp)
 
370
        {
 
371
            HWND hwnd;
 
372
            switch (uMsg)
 
373
            {
 
374
                case WM_INITDIALOG:
 
375
                    switch (PageID(PageIndex(psp)))
 
376
                    {
 
377
                        case IDD_DISPLAY:
 
378
                            // Init display dialog. Enable correct check buttons
 
379
                            switch (config.window)
 
380
                            {
 
381
                                default:
 
382
                                case CConfig::MultiWindow:
 
383
                                    CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, IDC_MULTIWINDOW);
 
384
                                    break;
 
385
                                case  CConfig::Fullscreen:
 
386
                                    CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, IDC_FULLSCREEN);
 
387
                                    break;
 
388
                                case  CConfig::Windowed:
 
389
                                    CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, IDC_WINDOWED);
 
390
                                    break;
 
391
                                case  CConfig::Nodecoration:
 
392
                                    CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, IDC_NODECORATION);
 
393
                                    break;
 
394
                            }
 
395
                            // Set display number
 
396
                            SetDlgItemText(hwndDlg, IDC_DISPLAY, config.display.c_str());
 
397
                            break;
 
398
                        case IDD_CLIENTS:
 
399
                            // Init client dialog. Enable correct check buttons
 
400
                            switch (config.client)
 
401
                            {
 
402
                                default:
 
403
                                case CConfig::NoClient:
 
404
                                    CheckRadioButton(hwndDlg, IDC_CLIENT_NONE, IDC_CLIENT, IDC_CLIENT_NONE);
 
405
                                    break;
 
406
                                case CConfig::StartProgram:
 
407
                                    CheckRadioButton(hwndDlg, IDC_CLIENT_NONE, IDC_CLIENT, IDC_CLIENT);
 
408
                                    break;
 
409
                                case CConfig::XDMCP:
 
410
                                    CheckRadioButton(hwndDlg, IDC_CLIENT_NONE, IDC_CLIENT, IDC_XDMCP);
 
411
                                    break;
 
412
                            }
 
413
                            break;
 
414
                        case IDD_PROGRAM:
 
415
                            // Init program dialog. Check local and remote buttons 
 
416
                            CheckRadioButton(hwndDlg, IDC_CLIENT_LOCAL, IDC_CLIENT_REMOTE, config.local?IDC_CLIENT_LOCAL:IDC_CLIENT_REMOTE);
 
417
                            EnableRemoteProgramGroup(hwndDlg, config.local?FALSE:TRUE);
 
418
                            // Fill combo boxes
 
419
                            FillProgramBox(hwndDlg);
 
420
                            FillProtocolBox(hwndDlg);
 
421
                            // Set edit fields
 
422
                            if (!config.program.empty())
 
423
                                SetDlgItemText(hwndDlg, IDC_CLIENT_PROGRAM, config.program.c_str());
 
424
                            SetDlgItemText(hwndDlg, IDC_CLIENT_USER, config.user.c_str());
 
425
                            SetDlgItemText(hwndDlg, IDC_CLIENT_HOST, config.host.c_str());
 
426
                            break;
 
427
                        case IDD_XDMCP:
 
428
                            // Init XDMCP dialog. Check broadcast and indirect button
 
429
                            CheckRadioButton(hwndDlg, IDC_XDMCP_QUERY, IDC_XDMCP_BROADCAST, config.broadcast?IDC_XDMCP_BROADCAST:IDC_XDMCP_QUERY);
 
430
                            CheckDlgButton(hwndDlg, IDC_XDMCP_INDIRECT, config.indirect?BST_CHECKED:BST_UNCHECKED);
 
431
                            EnableXDMCPQueryGroup(hwndDlg, config.broadcast?FALSE:TRUE);
 
432
                            // Set hostname
 
433
                            SetDlgItemText(hwndDlg, IDC_XDMCP_HOST, config.xdmcp_host.c_str());
 
434
                            break;
 
435
                        case IDD_CLIPBOARD:
 
436
                            CheckDlgButton(hwndDlg, IDC_CLIPBOARD, config.clipboard?BST_CHECKED:BST_UNCHECKED);
 
437
                            SetDlgItemText(hwndDlg, IDC_EXTRA_PARAMS, config.extra_params.c_str());
 
438
                            break;
 
439
 
 
440
                    }
 
441
                case WM_COMMAND:
 
442
                    // Handle control messages
 
443
                    switch (LOWORD(wParam))
 
444
                    {
 
445
                        // Handle clicks on images. Check proper radiobutton
 
446
                        case IDC_MULTIWINDOW_IMG:
 
447
                        case IDC_FULLSCREEN_IMG:
 
448
                        case IDC_WINDOWED_IMG:
 
449
                        case IDC_NODECORATION_IMG:
 
450
                            CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, LOWORD(wParam)-4);
 
451
                            SetFocus(GetDlgItem(hwndDlg, LOWORD(wParam)-4));
 
452
                            break;
 
453
                        // Disable unavailable controls 
 
454
                        case IDC_CLIENT_REMOTE:
 
455
                        case IDC_CLIENT_LOCAL:
 
456
                            EnableRemoteProgramGroup(hwndDlg, LOWORD(wParam) == IDC_CLIENT_REMOTE);
 
457
                            break;
 
458
                        case IDC_XDMCP_QUERY:
 
459
                        case IDC_XDMCP_BROADCAST:
 
460
                            EnableXDMCPQueryGroup(hwndDlg, LOWORD(wParam) == IDC_XDMCP_QUERY);
 
461
                            break;
 
462
                        case IDC_FINISH_SAVE:
 
463
                            ShowSaveDialog(hwndDlg);
 
464
                            break;
 
465
                    }
 
466
            }
 
467
            // pass messages to parent
 
468
            return CWizard::PageDispatch(hwndDlg, uMsg, wParam, lParam, psp);
 
469
        }
 
470
        
 
471
        /// @brief Try to connect to server.
 
472
        /// Repeat until successful, server died or maximum number of retries
 
473
        /// reached.
 
474
        Display *WaitForServer(HANDLE serverProcess)
 
475
        {
 
476
            int     ncycles  = 120;         /* # of cycles to wait */
 
477
            int     cycles;                 /* Wait cycle count */
 
478
            Display *xd;
 
479
 
 
480
            for (cycles = 0; cycles < ncycles; cycles++) {
 
481
                if ((xd = XOpenDisplay(NULL))) {
 
482
                    return xd;
 
483
                }
 
484
                else {
 
485
                    if (WaitForSingleObject(serverProcess, 1000) == WAIT_TIMEOUT)
 
486
                        continue;
 
487
                }
 
488
            }
 
489
            return NULL;
 
490
        }
 
491
               
 
492
        /// @brief Do the actual start of Xming and clients
 
493
        void StartUp()
 
494
        {
 
495
            std::string buffer;
 
496
            std::string client;
 
497
 
 
498
            // Construct display strings
 
499
            std::string display_id = ":" + config.display;
 
500
            std::string display = "localhost" + display_id + ":0";
 
501
 
 
502
#ifdef _DEBUG
 
503
            // Debug only: Switch to Xming installation directory
 
504
            SetCurrentDirectory("C:\\Programme\\Xming");
 
505
#endif      
 
506
 
 
507
            // Build Xming commandline
 
508
            buffer = "Xming " + display_id + " ";
 
509
            switch (config.window)
 
510
            {
 
511
                case CConfig::MultiWindow:
 
512
                    buffer += "-multiwindow ";
 
513
                    break;
 
514
                case CConfig::Fullscreen:
 
515
                    buffer += "-fullscreen ";
 
516
                    break;
 
517
                case CConfig::Nodecoration:
 
518
                    buffer += "-nodecoration ";
 
519
                    break;
 
520
                default:
 
521
                    break;
 
522
            }
 
523
            // Add XDMCP parameter
 
524
            if (config.client == CConfig::XDMCP)
 
525
            {
 
526
                if (config.broadcast)
 
527
                    buffer += "-broadcast ";
 
528
                else 
 
529
                {
 
530
                    if (config.indirect)
 
531
                        buffer += "-indirect ";
 
532
                    else
 
533
                        buffer += "-query ";
 
534
                    buffer += config.xdmcp_host;
 
535
            buffer += " ";
 
536
                }
 
537
            }
 
538
            if (config.clipboard)
 
539
                buffer += "-clipboard ";
 
540
            if (!config.extra_params.empty())
 
541
            {
 
542
                buffer += config.extra_params;
 
543
                buffer += " ";
 
544
            }
 
545
            
 
546
            // Construct client commandline
 
547
            if (config.client == CConfig::StartProgram)
 
548
            {
 
549
                if (!config.local)
 
550
                {
 
551
                    char cmdline[512];
 
552
                    std::string host = config.host;
 
553
                    if (!config.user.empty())
 
554
                        host = config.user + "@" + config.host;
 
555
                    if (config.protocol == "Putty")
 
556
                        snprintf(cmdline,512,"plink -X %s %s", 
 
557
                                host.c_str(),config.program.c_str());
 
558
                    else
 
559
                        snprintf(cmdline,512,"ssh -Y %s %s", 
 
560
                                host.c_str(),config.program.c_str());
 
561
                    client += cmdline;
 
562
                } else
 
563
                    client += config.program.c_str();
 
564
            }
 
565
 
 
566
            // Prepare program startup
 
567
            STARTUPINFO si, sic;
 
568
            PROCESS_INFORMATION pi, pic;
 
569
            HANDLE handles[2];
 
570
            DWORD hcount = 0; 
 
571
            Display *dpy = NULL;
 
572
 
 
573
            ZeroMemory( &si, sizeof(si) );
 
574
            si.cb = sizeof(si);
 
575
            ZeroMemory( &pi, sizeof(pi) );
 
576
            ZeroMemory( &sic, sizeof(sic) );
 
577
            sic.cb = sizeof(sic);
 
578
            ZeroMemory( &pic, sizeof(pic) );
 
579
 
 
580
            // Start Xming process. 
 
581
#ifdef _DEBUG
 
582
            printf("%s\n", buffer.c_str());
 
583
#endif
 
584
            if( !CreateProcess( NULL, (CHAR*)buffer.c_str(), NULL, NULL, 
 
585
                        FALSE, 0, NULL, NULL, &si, &pi )) 
 
586
                throw win32_error("CreateProcess failed");
 
587
            handles[hcount++] = pi.hProcess;
 
588
 
 
589
            if (!client.empty())
 
590
            {
 
591
                // Set DISPLAY variable
 
592
                SetEnvironmentVariable("DISPLAY",display.c_str());
 
593
 
 
594
                // Wait for server to startup
 
595
                dpy = WaitForServer(pi.hProcess);
 
596
                if (dpy == NULL)
 
597
                {
 
598
                    while (hcount--)
 
599
                        TerminateProcess(handles[hcount], (DWORD)-1);
 
600
                    throw std::runtime_error("Connection to server failed");
 
601
                }
 
602
                
 
603
#ifdef _DEBUG
 
604
                printf("%s\n", client.c_str());
 
605
#endif
 
606
 
 
607
                // Hide a console window 
 
608
                // FIXME: This may make it impossible to enter the password
 
609
                sic.dwFlags = STARTF_USESHOWWINDOW;
 
610
                sic.wShowWindow = SW_HIDE;
 
611
 
 
612
                // Start the child process. 
 
613
                if( !CreateProcess( NULL, (CHAR*)client.c_str(), NULL, NULL,
 
614
                            FALSE, 0, NULL, NULL, &sic, &pic )) 
 
615
                {
 
616
                    DWORD err = GetLastError();
 
617
                    while (hcount--)
 
618
                        TerminateProcess(handles[hcount], (DWORD)-1);
 
619
                    throw win32_error("CreateProcess failed", err);
 
620
                }
 
621
                handles[hcount++] = pic.hProcess;
 
622
            }
 
623
 
 
624
            // Wait until any child process exits.
 
625
            DWORD ret = WaitForMultipleObjects(hcount, handles, FALSE, INFINITE );
 
626
 
 
627
#ifdef _DEBUG
 
628
            printf("killing process!\n");
 
629
#endif
 
630
            // Check if Xming is still running
 
631
            DWORD exitcode;
 
632
            GetExitCodeProcess(pi.hProcess, &exitcode);
 
633
            unsigned counter = 0;
 
634
            while (exitcode == STILL_ACTIVE)
 
635
            {
 
636
                if (++counter > 10)
 
637
                    TerminateProcess(pi.hProcess, (DWORD)-1);
 
638
                else
 
639
                    // Shutdown Xming (the soft way!)
 
640
                    EnumThreadWindows(pi.dwThreadId, KillWindowsProc, 0);
 
641
                Sleep(500);
 
642
                GetExitCodeProcess(pi.hProcess, &exitcode);
 
643
            }
 
644
            // Kill the client
 
645
            TerminateProcess(pic.hProcess, (DWORD)-1);
 
646
 
 
647
            // Close process and thread handles. 
 
648
            CloseHandle( pi.hProcess );
 
649
            CloseHandle( pi.hThread );
 
650
            CloseHandle( pic.hProcess );
 
651
            CloseHandle( pic.hThread );
 
652
        }
 
653
};
 
654
 
 
655
int main(int argc, char **argv)
 
656
{
 
657
    try {
 
658
        InitCommonControls();
 
659
        CMyWizard dialog;
 
660
 
 
661
        bool skip_wizard = false;
 
662
 
 
663
        for (int i = 1; i < argc; i++)
 
664
        {
 
665
            if (argv[i] == NULL)
 
666
                continue;
 
667
            
 
668
            std::string arg(argv[i]);
 
669
            if (arg == "-load" && i + 1 < argc)
 
670
            {
 
671
                i++;
 
672
                dialog.LoadConfig(argv[i]);
 
673
                continue;
 
674
            }
 
675
            if (arg == "-run" && i + 1 < argc)
 
676
            {
 
677
                i++;
 
678
                dialog.LoadConfig(argv[i]);
 
679
                skip_wizard = true;
 
680
                continue;
 
681
            }
 
682
        }
 
683
 
 
684
        int ret = 0; 
 
685
        if (skip_wizard || (ret =dialog.ShowModal()) != 0)
 
686
            dialog.StartUp();
 
687
#ifdef _DEBUG
 
688
        printf("return %d\n", ret);
 
689
#endif
 
690
        return 0;
 
691
    } catch (std::runtime_error &e)
 
692
    {
 
693
        printf("Fehler: %s\n", e.what());
 
694
        return -1;
 
695
    }
 
696
}
 
697
 
 
698
 
 
699
 
 
700