Create a branch for header work.
[reactos.git] / base / applications / mstsc / win32.c
1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 win32 calls
4 Copyright (C) Jay Sorg 2006
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <winsock2.h> /* winsock2.h first */
22 #include <precomp.h>
23
24 //FIXME: remove eventually
25 #ifndef _UNICODE
26 #define _UNICODE
27 #endif
28 #include <tchar.h>
29
30
31 extern char g_username[];
32 extern char g_hostname[];
33 extern char g_servername[];
34 extern char g_password[];
35 extern char g_shell[];
36 extern char g_directory[];
37 extern char g_domain[];
38 extern int g_width;
39 extern int g_height;
40 extern int g_tcp_sck;
41 extern int g_server_depth;
42 extern int g_tcp_port_rdp; /* in tcp.c */
43 extern int pal_entries[];
44
45 static HWND g_Wnd = 0;
46 static HINSTANCE g_Instance = 0;
47 static HCURSOR g_cursor = 0;
48 static int g_block = 0;
49 static int g_xoff = 0; /* offset from window to client coords */
50 static int g_yoff = 0;
51 static int g_xscroll = 0; /* current scroll position */
52 static int g_yscroll = 0;
53 static int g_screen_width = 0;
54 static int g_screen_height = 0;
55 static int g_wnd_cwidth = 0; /* set from WM_SIZE */
56 static int g_wnd_cheight = 0;
57 static int g_fullscreen = 0;
58 static int g_workarea = 0;
59 static int g_mousex = 0; /* in client coords */
60 static int g_mousey = 0;
61 //static int g_width_height_set = 0;
62
63 static int g_clip_left = 0;
64 static int g_clip_top = 0;
65 static int g_clip_right = 800;
66 static int g_clip_bottom = 600;
67 static RECT g_wnd_clip; /* this client area of whats actually visable */
68 /* set from WM_SIZE */
69
70 /*****************************************************************************/
71 static void
72 str_to_uni(TCHAR * sizex, char * size1)
73 {
74 int len;
75 int i;
76
77 len = strlen(size1);
78 for (i = 0; i < len; i++)
79 {
80 sizex[i] = size1[i];
81 }
82 sizex[len] = 0;
83 }
84
85 /*****************************************************************************/
86 static void
87 uni_to_str(char * sizex, TCHAR * size1)
88 {
89 int len;
90 int i;
91
92 len = _tcslen(size1);
93 for (i = 0; i < len; i++)
94 {
95 sizex[i] = (char)size1[i];
96 }
97 sizex[len] = 0;
98 }
99
100 /*****************************************************************************/
101 /* returns non zero if it processed something */
102 static int
103 check_sck(void)
104 {
105 fd_set rfds;
106 struct timeval tm;
107 int count;
108 int rv;
109
110 rv = 0;
111 if (g_block == 0)
112 {
113 g_block = 1;
114 /* see if there really is data */
115 FD_ZERO(&rfds);
116 FD_SET((unsigned int)g_tcp_sck, &rfds);
117 ZeroMemory(&tm, sizeof(tm));
118 count = select(g_tcp_sck + 1, &rfds, 0, 0, &tm);
119 if (count > 0)
120 {
121 if (ui_read_wire())
122 {
123 rv = 1;
124 }
125 else
126 {
127 PostQuitMessage(0);
128 }
129 }
130 g_block = 0;
131 }
132 return rv;
133 }
134
135 /*****************************************************************************/
136 void
137 mi_error(char * msg)
138 {
139 #ifdef WITH_DEBUG
140 printf(msg);
141 #else /* WITH_DEBUG */
142 TCHAR lmsg[512];
143 TCHAR ltitle[512];
144
145 str_to_uni(lmsg, msg);
146 str_to_uni(ltitle, "Error");
147 MessageBox(g_Wnd, lmsg, ltitle, MB_OK);
148 #endif /* WITH_DEBUG */
149 }
150
151 /*****************************************************************************/
152 static int
153 get_scan_code_from_ascii(int code)
154 {
155 int rv;
156
157 rv = 0;
158 switch (code & 0xff)
159 {
160 case 0x30: rv = 0x0b; break; // 0
161 case 0x31: rv = 0x02; break; // 1
162 case 0x32: rv = 0x03; break; // 2
163 case 0x33: rv = 0x04; break; // 3
164 case 0x34: rv = 0x05; break; // 4
165 case 0x35: rv = 0x06; break; // 5
166 case 0x36: rv = 0x07; break; // 6
167 case 0x37: rv = 0x08; break; // 7
168 case 0x38: rv = 0x09; break; // 8
169 case 0x39: rv = 0x0a; break; // 9
170
171 case 0xbd: rv = 0x0c; break; // -
172 case 0xbb: rv = 0x0d; break; // =
173 case 0x08: rv = 0x0e; break; // backspace
174 case 0x09: rv = 0x0f; break; // tab
175 case 0xdb: rv = 0x1b; break; // ]
176 case 0xdd: rv = 0x1a; break; // [
177 case 0x14: rv = 0x3a; break; // capslock
178 case 0xba: rv = 0x27; break; // ;
179 case 0xde: rv = 0x28; break; // '
180 case 0x10: rv = 0x2a; break; // shift
181 case 0xbc: rv = 0x33; break; // ,
182 case 0xbe: rv = 0x34; break; // .
183 case 0xbf: rv = 0x35; break; // /
184 case 0x0d: rv = 0x1c; break; // enter
185 case 0x27: rv = 0x4d; break; // arrow right
186 case 0x25: rv = 0x4b; break; // arrow left
187 case 0x26: rv = 0x48; break; // arrow up
188 case 0x28: rv = 0x50; break; // arrow down
189 case 0x20: rv = 0x39; break; // space
190 case 0xdc: rv = 0x2b; break; // backslash
191 case 0xc0: rv = 0x29; break; // `
192 case 0x11: rv = 0x1d; break; // ctl
193
194 case 0x41: rv = 0x1e; break; // a
195 case 0x42: rv = 0x30; break; // b
196 case 0x43: rv = 0x2e; break; // c
197 case 0x44: rv = 0x20; break; // d
198 case 0x45: rv = 0x12; break; // e
199 case 0x46: rv = 0x21; break; // f
200 case 0x47: rv = 0x22; break; // g
201 case 0x48: rv = 0x23; break; // h
202 case 0x49: rv = 0x17; break; // i
203 case 0x4a: rv = 0x24; break; // j
204 case 0x4b: rv = 0x25; break; // k
205 case 0x4c: rv = 0x26; break; // l
206 case 0x4d: rv = 0x32; break; // m
207 case 0x4e: rv = 0x31; break; // n
208 case 0x4f: rv = 0x18; break; // o
209 case 0x50: rv = 0x19; break; // p
210 case 0x51: rv = 0x10; break; // q
211 case 0x52: rv = 0x13; break; // r
212 case 0x53: rv = 0x1f; break; // s
213 case 0x54: rv = 0x14; break; // t
214 case 0x55: rv = 0x16; break; // u
215 case 0x56: rv = 0x2f; break; // v
216 case 0x57: rv = 0x11; break; // w
217 case 0x58: rv = 0x2d; break; // x
218 case 0x59: rv = 0x15; break; // y
219 case 0x5a: rv = 0x2c; break; // z
220 }
221 return rv;
222 }
223
224 /*****************************************************************************/
225 static void
226 mi_scroll(int dx, int dy)
227 {
228 HRGN rgn;
229
230 rgn = CreateRectRgn(0, 0, 0, 0);
231 ScrollWindowEx(g_Wnd, dx, dy, 0, 0, rgn, 0, SW_ERASE);
232 InvalidateRgn(g_Wnd, rgn, 0);
233 DeleteObject(rgn);
234 }
235
236 /*****************************************************************************/
237 int
238 mi_read_keyboard_state(void)
239 {
240 short keydata;
241 int code;
242
243 code = 0;
244 keydata = GetKeyState(VK_SCROLL);
245 if (keydata & 0x0001)
246 {
247 code |= 1;
248 }
249 keydata = GetKeyState(VK_NUMLOCK);
250 if (keydata & 0x0001)
251 {
252 code |= 2;
253 }
254 keydata = GetKeyState(VK_CAPITAL);
255 if (keydata & 0x0001)
256 {
257 code |= 4;
258 }
259 return code;
260 }
261
262 /*****************************************************************************/
263 static void
264 mi_check_modifier(void)
265 {
266 int code;
267
268 code = mi_read_keyboard_state();
269 ui_set_modifier_state(code);
270 }
271
272 /*****************************************************************************/
273 static LRESULT
274 handle_WM_SETCURSOR(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
275 {
276 if (g_mousex >= g_wnd_clip.left &&
277 g_mousey >= g_wnd_clip.top &&
278 g_mousex < g_wnd_clip.right &&
279 g_mousey < g_wnd_clip.bottom)
280 {
281 SetCursor(g_cursor);
282 }
283 /* need default behavoir here */
284 return DefWindowProc(hWnd, message, wParam, lParam);
285 }
286
287 /*****************************************************************************/
288 static LRESULT
289 handle_WM_NCHITTEST(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
290 {
291 POINT pt;
292
293 pt.x = LOWORD(lParam);
294 pt.y = HIWORD(lParam);
295 if (ScreenToClient(g_Wnd, &pt))
296 {
297 g_mousex = pt.x;
298 g_mousey = pt.y;
299 }
300 return DefWindowProc(hWnd, message, wParam, lParam);
301 }
302
303 /*****************************************************************************/
304 static LRESULT
305 handle_WM_MOUSEMOVE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
306 {
307 g_mousex = LOWORD(lParam);
308 g_mousey = HIWORD(lParam);
309 ui_mouse_move(g_mousex + g_xscroll, g_mousey + g_yscroll);
310 return 0;
311 }
312
313 /*****************************************************************************/
314 static LRESULT
315 handle_WM_LBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
316 {
317 g_mousex = LOWORD(lParam);
318 g_mousey = HIWORD(lParam);
319 ui_mouse_button(1, g_mousex + g_xscroll, g_mousey + g_yscroll, 1);
320 return 0;
321 }
322
323 /*****************************************************************************/
324 static LRESULT
325 handle_WM_LBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
326 {
327 g_mousex = LOWORD(lParam);
328 g_mousey = HIWORD(lParam);
329 ui_mouse_button(1, g_mousex + g_xscroll, g_mousey + g_yscroll, 0);
330 return 0;
331 }
332
333 /*****************************************************************************/
334 static LRESULT
335 handle_WM_RBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
336 {
337 g_mousex = LOWORD(lParam);
338 g_mousey = HIWORD(lParam);
339 ui_mouse_button(2, g_mousex + g_xscroll, g_mousey + g_yscroll, 1);
340 return 0;
341 }
342
343 /*****************************************************************************/
344 static LRESULT
345 handle_WM_RBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
346 {
347 g_mousex = LOWORD(lParam);
348 g_mousey = HIWORD(lParam);
349 ui_mouse_button(2, g_mousex + g_xscroll, g_mousey + g_yscroll, 0);
350 return 0;
351 }
352
353 /*****************************************************************************/
354 static LRESULT
355 handle_WM_MBUTTONDOWN(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
356 {
357 g_mousex = LOWORD(lParam);
358 g_mousey = HIWORD(lParam);
359 ui_mouse_button(3, g_mousex + g_xscroll, g_mousey + g_yscroll, 1);
360 return 0;
361 }
362
363 /*****************************************************************************/
364 static LRESULT
365 handle_WM_MBUTTONUP(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
366 {
367 g_mousex = LOWORD(lParam);
368 g_mousey = HIWORD(lParam);
369 ui_mouse_button(3, g_mousex + g_xscroll, g_mousey + g_yscroll, 0);
370 return 0;
371 }
372
373 /*****************************************************************************/
374 static LRESULT
375 handle_WM_MOUSEWHEEL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
376 {
377 int delta;
378
379 delta = ((signed short)HIWORD(wParam)); /* GET_WHEEL_DELTA_WPARAM(wParam); */
380 if (delta > 0)
381 {
382 ui_mouse_button(4, 0, 0, 1);
383 ui_mouse_button(4, 0, 0, 0);
384 }
385 else
386 {
387 ui_mouse_button(5, 0, 0, 1);
388 ui_mouse_button(5, 0, 0, 0);
389 }
390 return 0;
391 }
392
393 /*****************************************************************************/
394 static LRESULT
395 handle_WM_KEY(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
396 {
397 int scancode;
398 int ext;
399 int down;
400
401 ext = HIWORD(lParam);
402 scancode = ext;
403 down = !(ext & 0x8000);
404 scancode &= 0xff;
405 if (scancode == 0)
406 {
407 scancode = get_scan_code_from_ascii(wParam);
408 }
409 ext &= 0x0100;
410 if (scancode == 0x0045) /* num lock */
411 {
412 ext &= ~0x0100;
413 }
414 if (down)
415 {
416 ui_key_down(scancode, ext);
417 }
418 else
419 {
420 ui_key_up(scancode, ext);
421 }
422 return 0;
423 }
424
425 /*****************************************************************************/
426 static LRESULT
427 handle_WM_PAINT(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
428 {
429 PAINTSTRUCT ps;
430 RECT rect;
431 HBRUSH brush;
432
433 BeginPaint(hWnd, &ps);
434 /* paint the area outside the rdp screen with one colour */
435 rect = ps.rcPaint;
436 rect.left = UI_MAX(rect.left, g_width);
437 if (!IsRectEmpty(&rect))
438 {
439 brush = CreateSolidBrush(RGB(0, 0, 255));
440 FillRect(ps.hdc, &rect, brush);
441 DeleteObject(brush);
442 }
443 rect = ps.rcPaint;
444 rect.top = UI_MAX(rect.top, g_height);
445 if (!IsRectEmpty(&rect))
446 {
447 brush = CreateSolidBrush(RGB(0, 0, 255));
448 FillRect(ps.hdc, &rect, brush);
449 DeleteObject(brush);
450 }
451 rect = ps.rcPaint;
452 EndPaint(hWnd, &ps);
453 ui_invalidate(rect.left + g_xscroll,
454 rect.top + g_yscroll,
455 (rect.right - rect.left) + 1,
456 (rect.bottom - rect.top) + 1);
457 return 0;
458 }
459
460 /*****************************************************************************/
461 static LRESULT
462 handle_WM_SIZE(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
463 {
464 int oldxscroll;
465 int oldyscroll;
466
467 if (wParam == SIZE_MINIMIZED)
468 {
469 return DefWindowProc(hWnd, message, wParam, lParam);
470 }
471 g_wnd_cwidth = LOWORD(lParam); /* client width / height */
472 g_wnd_cheight = HIWORD(lParam);
473 g_wnd_clip.left = 0;
474 g_wnd_clip.top = 0;
475 g_wnd_clip.right = g_wnd_clip.left + g_wnd_cwidth;
476 g_wnd_clip.bottom = g_wnd_clip.top + g_wnd_cheight;
477 if (g_wnd_cwidth < g_width || g_wnd_cheight < g_height)
478 {
479 SetScrollRange(g_Wnd, SB_HORZ, 0, g_width - g_wnd_cwidth, 1);
480 SetScrollRange(g_Wnd, SB_VERT, 0, g_height - g_wnd_cheight, 1);
481 }
482 oldxscroll = g_xscroll;
483 oldyscroll = g_yscroll;
484 if (g_wnd_cwidth >= g_width)
485 {
486 g_xscroll = 0;
487 }
488 else
489 {
490 g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth);
491 }
492 if (g_wnd_cheight >= g_height)
493 {
494 g_yscroll = 0;
495 }
496 else
497 {
498 g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight);
499 }
500 mi_scroll(oldxscroll - g_xscroll, oldyscroll - g_yscroll);
501 if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
502 {
503 /* check the caps, num, and scroll lock here */
504 mi_check_modifier();
505 }
506 return 0;
507 }
508
509 /*****************************************************************************/
510 static LRESULT
511 handle_WM_SIZING(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
512 {
513 LPRECT prect;
514 int width;
515 int height;
516 int style;
517
518 prect = (LPRECT) lParam; /* total window rect */
519 width = (prect->right - prect->left) - (g_xoff * 2);
520 height = (prect->bottom - prect->top) - (g_yoff + g_xoff);
521 if (height < g_height || width < g_width)
522 {
523 style = GetWindowLongPtr(g_Wnd, GWL_STYLE);
524 if (!(style & WS_HSCROLL))
525 {
526 style |= WS_HSCROLL | WS_VSCROLL;
527 SetWindowLongPtr(g_Wnd, GWL_STYLE, style);
528 g_xscroll = 0;
529 g_yscroll = 0;
530 SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
531 SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
532 }
533 }
534 else if (height >= g_height && width >= g_width)
535 {
536 style = GetWindowLongPtr(g_Wnd, GWL_STYLE);
537 if (style & WS_HSCROLL)
538 {
539 style &= ~WS_HSCROLL;
540 style &= ~WS_VSCROLL;
541 SetWindowLongPtr(g_Wnd, GWL_STYLE, style);
542 g_xscroll = 0;
543 g_yscroll = 0;
544 }
545 }
546 return 0;
547 }
548
549 /*****************************************************************************/
550 static LRESULT
551 handle_WM_HSCROLL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
552 {
553 int code;
554 int oldxscroll;
555
556 code = (int) LOWORD(wParam); /* scroll bar value */
557 if (code == SB_LINELEFT)
558 {
559 oldxscroll = g_xscroll;
560 g_xscroll--;
561 g_xscroll = UI_MAX(g_xscroll, 0);
562 SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
563 mi_scroll(oldxscroll - g_xscroll, 0);
564 }
565 else if (code == SB_LINERIGHT)
566 {
567 oldxscroll = g_xscroll;
568 g_xscroll++;
569 g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth);
570 SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
571 mi_scroll(oldxscroll - g_xscroll, 0);
572 }
573 else if (code == SB_PAGELEFT)
574 {
575 oldxscroll = g_xscroll;
576 g_xscroll -= g_wnd_cwidth / 2;
577 g_xscroll = UI_MAX(g_xscroll, 0);
578 SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
579 mi_scroll(oldxscroll - g_xscroll, 0);
580 }
581 else if (code == SB_PAGERIGHT)
582 {
583 oldxscroll = g_xscroll;
584 g_xscroll += g_wnd_cwidth / 2;
585 g_xscroll = UI_MIN(g_xscroll, g_width - g_wnd_cwidth);
586 SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
587 mi_scroll(oldxscroll - g_xscroll, 0);
588 }
589 else if (code == SB_BOTTOM)
590 {
591 oldxscroll = g_xscroll;
592 g_xscroll = g_width - g_wnd_cwidth;
593 SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
594 mi_scroll(oldxscroll - g_xscroll, 0);
595 }
596 else if (code == SB_TOP)
597 {
598 oldxscroll = g_xscroll;
599 g_xscroll = 0;
600 SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
601 mi_scroll(oldxscroll - g_xscroll, 0);
602 }
603 else if (code == SB_THUMBPOSITION)
604 {
605 oldxscroll = g_xscroll;
606 g_xscroll = (signed short) HIWORD(wParam);
607 SetScrollPos(g_Wnd, SB_HORZ, g_xscroll, 1);
608 mi_scroll(oldxscroll - g_xscroll, 0);
609 }
610 return 0;
611 }
612
613 /*****************************************************************************/
614 static LRESULT
615 handle_WM_VSCROLL(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
616 {
617 int code;
618 int oldyscroll;
619
620 code = (int) LOWORD(wParam); /* scroll bar value */
621 if (code == SB_LINELEFT)
622 {
623 oldyscroll = g_yscroll;
624 g_yscroll--;
625 g_yscroll = UI_MAX(g_yscroll, 0);
626 SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
627 mi_scroll(0, oldyscroll - g_yscroll);
628 }
629 else if (code == SB_LINERIGHT)
630 {
631 oldyscroll = g_yscroll;
632 g_yscroll++;
633 g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight);
634 SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
635 mi_scroll(0, oldyscroll - g_yscroll);
636 }
637 else if (code == SB_PAGELEFT)
638 {
639 oldyscroll = g_yscroll;
640 g_yscroll -= g_wnd_cheight / 2;
641 g_yscroll = UI_MAX(g_yscroll, 0);
642 SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
643 mi_scroll(0, oldyscroll - g_yscroll);
644 }
645 else if (code == SB_PAGERIGHT)
646 {
647 oldyscroll = g_yscroll;
648 g_yscroll += g_wnd_cheight / 2;
649 g_yscroll = UI_MIN(g_yscroll, g_height - g_wnd_cheight);
650 SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
651 mi_scroll(0, oldyscroll - g_yscroll);
652 }
653 else if (code == SB_BOTTOM)
654 {
655 oldyscroll = g_yscroll;
656 g_yscroll = g_height - g_wnd_cheight;
657 SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
658 mi_scroll(0, oldyscroll - g_yscroll);
659 }
660 else if (code == SB_TOP)
661 {
662 oldyscroll = g_yscroll;
663 g_yscroll = 0;
664 SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
665 mi_scroll(0, oldyscroll - g_yscroll);
666 }
667 else if (code == SB_THUMBPOSITION)
668 {
669 oldyscroll = g_yscroll;
670 g_yscroll = (signed short) HIWORD(wParam);
671 SetScrollPos(g_Wnd, SB_VERT, g_yscroll, 1);
672 mi_scroll(0, oldyscroll - g_yscroll);
673 }
674 return 0;
675 }
676
677
678 /*****************************************************************************/
679 LRESULT CALLBACK
680 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
681 {
682 switch (message)
683 {
684 case WM_SETCURSOR:
685 return handle_WM_SETCURSOR(hWnd, message, wParam, lParam);
686 case 0x0084: /* WinCE don't have this WM_NCHITTEST: */
687 return handle_WM_NCHITTEST(hWnd, message, wParam, lParam);
688 case WM_MOUSEMOVE:
689 return handle_WM_MOUSEMOVE(hWnd, message, wParam, lParam);
690 case WM_LBUTTONDOWN:
691 return handle_WM_LBUTTONDOWN(hWnd, message, wParam, lParam);
692 case WM_LBUTTONUP:
693 return handle_WM_LBUTTONUP(hWnd, message, wParam, lParam);
694 case WM_RBUTTONDOWN:
695 return handle_WM_RBUTTONDOWN(hWnd, message, wParam, lParam);
696 case WM_RBUTTONUP:
697 return handle_WM_RBUTTONUP(hWnd, message, wParam, lParam);
698 case WM_MBUTTONDOWN:
699 return handle_WM_MBUTTONDOWN(hWnd, message, wParam, lParam);
700 case WM_MBUTTONUP:
701 return handle_WM_MBUTTONUP(hWnd, message, wParam, lParam);
702 /* some windows compilers don't have these defined like vc6 */
703 case 0x020a: /* WM_MOUSEWHEEL: */
704 return handle_WM_MOUSEWHEEL(hWnd, message, wParam, lParam);
705 case WM_KEYDOWN:
706 case WM_KEYUP:
707 case WM_SYSKEYDOWN:
708 case WM_SYSKEYUP:
709 return handle_WM_KEY(hWnd, message, wParam, lParam);
710 case WM_CHAR:
711 case WM_DEADCHAR:
712 case WM_SYSCHAR:
713 case WM_SYSDEADCHAR:
714 break;
715 case WM_PAINT:
716 return handle_WM_PAINT(hWnd, message, wParam, lParam);
717 case WM_DESTROY:
718 PostQuitMessage(0);
719 break;
720 case WM_APP + 1:
721 case WM_TIMER:
722 check_sck();
723 break;
724 case WM_SIZE:
725 return handle_WM_SIZE(hWnd, message, wParam, lParam);
726 case 532: /* not defined in wince WM_SIZING: */
727 return handle_WM_SIZING(hWnd, message, wParam, lParam);
728 case WM_HSCROLL:
729 return handle_WM_HSCROLL(hWnd, message, wParam, lParam);
730 case WM_VSCROLL:
731 return handle_WM_VSCROLL(hWnd, message, wParam, lParam);
732 case WM_SETFOCUS:
733 mi_check_modifier();
734 return DefWindowProc(hWnd, message, wParam, lParam);
735 default:
736 return DefWindowProc(hWnd, message, wParam, lParam);
737 }
738 return 0;
739 }
740
741 /*****************************************************************************/
742 static HRGN
743 mi_clip(HDC dc)
744 {
745 HRGN rgn;
746
747 rgn = CreateRectRgn(g_clip_left + g_xoff - g_xscroll,
748 g_clip_top + g_yoff - g_yscroll,
749 g_clip_right + g_xoff - g_xscroll,
750 g_clip_bottom + g_yoff - g_yscroll);
751 SelectClipRgn(dc, rgn);
752 IntersectClipRect(dc, g_wnd_clip.left + g_xoff, g_wnd_clip.top + g_yoff,
753 g_wnd_clip.right + g_xoff, g_wnd_clip.bottom + g_yoff);
754 return rgn;
755 }
756
757 /*****************************************************************************/
758 /* returns non zero if ok */
759 int
760 mi_create_window(void)
761 {
762 RECT rc;
763 WNDCLASS wc;
764 TCHAR classname[512];
765 TCHAR caption[512];
766 DWORD style;
767 int x;
768 int y;
769 int w;
770 int h;
771
772 if (g_Wnd != 0 || g_Instance != 0)
773 {
774 return 0;
775 }
776 g_Instance = GetModuleHandle(NULL);
777 ZeroMemory(&wc, sizeof(wc));
778 wc.lpfnWndProc = WndProc; /* points to window procedure */
779 /* name of window class */
780 str_to_uni(classname, "rdesktop");
781 wc.lpszClassName = classname;
782 str_to_uni(caption, "ReactOS Remote Desktop");
783 wc.hIcon = LoadIcon(g_Instance,
784 MAKEINTRESOURCE(IDI_MSTSC));
785 /* Register the window class. */
786 if (!RegisterClass(&wc))
787 {
788 return 0; /* Failed to register window class */
789 }
790 rc.left = 0;
791 rc.right = rc.left + UI_MIN(g_width, g_screen_width);
792 rc.top = 0;
793 rc.bottom = rc.top + UI_MIN(g_height, g_screen_height);
794
795 if (g_fullscreen)
796 {
797 style = WS_POPUP;
798 }
799 else
800 {
801 style = WS_OVERLAPPED | WS_CAPTION | WS_POPUP | WS_MINIMIZEBOX |
802 WS_SYSMENU | WS_SIZEBOX | WS_MAXIMIZEBOX;
803 }
804 if (g_screen_width < g_width || g_screen_height < g_height)
805 {
806 style |= WS_HSCROLL | WS_VSCROLL;
807 }
808 AdjustWindowRectEx(&rc, style, 0, 0);
809 x = CW_USEDEFAULT;
810 y = CW_USEDEFAULT;
811 w = rc.right - rc.left;
812 h = rc.bottom - rc.top;
813
814 g_Wnd = CreateWindow(wc.lpszClassName, caption,
815 style, x, y, w, h,
816 (HWND) NULL, (HMENU) NULL, g_Instance,
817 (LPVOID) NULL);
818 g_clip_left = 0;
819 g_clip_top = 0;
820 g_clip_right = g_clip_left + g_width;
821 g_clip_bottom = g_clip_top + g_height;
822 if (g_workarea)
823 {
824 ShowWindow(g_Wnd, SW_SHOWMAXIMIZED);
825 }
826 else
827 {
828 ShowWindow(g_Wnd, SW_SHOWNORMAL);
829 }
830 UpdateWindow(g_Wnd);
831
832 WSAAsyncSelect(g_tcp_sck, g_Wnd, WM_APP + 1, FD_READ);
833 SetTimer(g_Wnd, 1, 333, 0);
834
835 return 1;
836 }
837
838 /*****************************************************************************/
839 int
840 mi_main_loop(void)
841 {
842 MSG msg;
843
844 while (GetMessage(&msg, NULL, 0, 0))
845 {
846 TranslateMessage(&msg);
847 DispatchMessage(&msg);
848 }
849 return msg.wParam;
850 }
851
852 /*****************************************************************************/
853 void
854 mi_warning(char * msg)
855 {
856 }
857
858 /*****************************************************************************/
859 static void
860 mi_show_error(char * caption)
861 {
862 LPVOID lpMsgBuf;
863 TCHAR lcaption[512];
864
865 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
866 NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
867 (LPTSTR) &lpMsgBuf, 0, NULL);
868 #ifdef WITH_DEBUG
869 printf(lpMsgBuf);
870 #else /* WITH_DEBUG */
871 str_to_uni(lcaption, caption);
872 MessageBox(g_Wnd, (LPTSTR) lpMsgBuf, lcaption,
873 MB_OK | MB_ICONINFORMATION);
874 #endif /* WITH_DEBUG */
875 LocalFree(lpMsgBuf);
876 }
877
878 /*****************************************************************************/
879 void
880 mi_paint_rect(char * data, int width, int height, int x, int y, int cx, int cy)
881 {
882 HBITMAP bitmap;
883 BITMAPINFO bi;
884 HDC dc;
885 HDC maindc;
886 HGDIOBJ save;
887 HRGN rgn;
888 void * bits;
889 int i;
890 int j;
891 int colour;
892 int red;
893 int green;
894 int blue;
895
896 ZeroMemory(&bi, sizeof(bi));
897 bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
898 bi.bmiHeader.biWidth = width;
899 bi.bmiHeader.biHeight = -height;
900 bi.bmiHeader.biPlanes = 1;
901 bi.bmiHeader.biBitCount = 32;
902 bi.bmiHeader.biCompression = BI_RGB;
903 maindc = GetWindowDC(g_Wnd);
904 bitmap = CreateDIBSection(maindc, &bi, DIB_RGB_COLORS, (void **) &bits, 0, 0);
905 if (bitmap == 0)
906 {
907 mi_show_error("CreateDIBSection failed");
908 }
909
910 if (g_server_depth == 8)
911 {
912 for (i = cy - 1; i >= 0; i--)
913 {
914 for (j = cx - 1; j >= 0; j--)
915 {
916 colour = ((unsigned char*)data)[i * cx + j];
917 red = (pal_entries[colour & 0xff] & 0xff0000) >> 16;
918 green = (pal_entries[colour & 0xff] & 0xff00) >> 8;
919 blue = pal_entries[colour & 0xff] & 0xff;
920 MAKE_COLOUR32(colour, red, green, blue);
921 ((unsigned int*)bits)[i * cx + j] = colour;
922 }
923 }
924 }
925 else if (g_server_depth == 15)
926 {
927 for (i = cy - 1; i >= 0; i--)
928 {
929 for (j = cx - 1; j >= 0; j--)
930 {
931 colour = ((unsigned short*)data)[i * cx + j];
932 SPLIT_COLOUR15(colour, red, green, blue);
933 MAKE_COLOUR32(colour, red, green, blue);
934 ((unsigned int*)bits)[i * cx + j] = colour;
935 }
936 }
937 }
938 else if (g_server_depth == 16)
939 {
940 for (i = cy - 1; i >= 0; i--)
941 {
942 for (j = cx - 1; j >= 0; j--)
943 {
944 colour = ((unsigned short*)data)[i * cx + j];
945 SPLIT_COLOUR16(colour, red, green, blue);
946 MAKE_COLOUR32(colour, red, green, blue);
947 ((unsigned int*)bits)[i * cx + j] = colour;
948 }
949 }
950 }
951 dc = CreateCompatibleDC(maindc);
952 if (dc == 0)
953 {
954 mi_show_error("CreateCompatibleDC failed");
955 }
956 save = SelectObject(dc, bitmap);
957 rgn = mi_clip(maindc);
958 BitBlt(maindc, x + g_xoff - g_xscroll, y + g_yoff - g_yscroll, cx, cy, dc,
959 0, 0, SRCCOPY);
960 SelectObject(dc, save);
961 DeleteObject(bitmap);
962 DeleteDC(dc);
963 ReleaseDC(g_Wnd, maindc);
964 DeleteObject(rgn);
965
966 }
967
968
969 static BOOL
970 ParseCommandLine(LPWSTR lpCmdLine,
971 PRDPSETTINGS pRdpSettings,
972 BOOL *bSkipDlg)
973 {
974 LPWSTR lpStr = lpCmdLine;
975 WCHAR szSeps[] = L"/";
976 LPWSTR lpToken;
977 BOOL bRet = TRUE;
978
979 *bSkipDlg = TRUE;
980
981 if (*lpCmdLine != L'/')
982 {
983 LoadRdpSettingsFromFile(pRdpSettings, lpCmdLine);
984 }
985 else
986 {
987 /* default to 16bpp */
988 SetIntegerToSettings(pRdpSettings, L"session bpp", 16);
989
990 lpToken = wcstok(lpStr, szSeps);
991 while (lpToken)
992 {
993 if (wcsncmp(lpToken, L"edit", 4) == 0)
994 {
995 lpToken += 5;
996 LoadRdpSettingsFromFile(pRdpSettings, lpToken);
997 *bSkipDlg = FALSE;
998 break;
999 }
1000
1001 if (*lpToken == L'v')
1002 {
1003 lpToken += 2;
1004 SetStringToSettings(pRdpSettings, L"full address", lpToken);
1005 }
1006 else if (*lpToken == L'w')
1007 {
1008 lpToken += 2;
1009 SetIntegerToSettings(pRdpSettings, L"desktopwidth", _wtoi(lpToken));
1010 }
1011 else if (*lpToken == L'h')
1012 {
1013 lpToken += 2;
1014 SetIntegerToSettings(pRdpSettings, L"desktopheight", _wtoi(lpToken));
1015 }
1016
1017 lpToken = wcstok(NULL, szSeps);
1018 }
1019 }
1020
1021 return bRet;
1022 }
1023
1024 /*****************************************************************************/
1025 int WINAPI
1026 wWinMain(HINSTANCE hInstance,
1027 HINSTANCE hPrevInstance,
1028 LPWSTR lpCmdLine,
1029 int nCmdShow)
1030 {
1031 PRDPSETTINGS pRdpSettings;
1032 WSADATA d;
1033 int ret = 1;
1034
1035 if (WSAStartup(MAKEWORD(2, 0), &d) == 0)
1036 {
1037 pRdpSettings = HeapAlloc(GetProcessHeap(),
1038 0,
1039 sizeof(RDPSETTINGS));
1040 if (pRdpSettings)
1041 {
1042 pRdpSettings->pSettings = NULL;
1043 pRdpSettings->NumSettings = 0;
1044
1045 if (InitRdpSettings(pRdpSettings))
1046 {
1047 BOOL bSkipDlg = FALSE;
1048
1049 if (*lpCmdLine)
1050 ParseCommandLine(lpCmdLine, pRdpSettings,&bSkipDlg);
1051 else
1052 LoadRdpSettingsFromFile(pRdpSettings, NULL);
1053
1054 if (bSkipDlg || OpenRDPConnectDialog(hInstance,
1055 pRdpSettings))
1056 {
1057 char szValue[MAXVALUE];
1058
1059 uni_to_str(szValue, GetStringFromSettings(pRdpSettings, L"full address"));
1060
1061 strcpy(g_servername, szValue);
1062 //g_port = 3389;
1063 strcpy(g_username, "");
1064 strcpy(g_password, "");
1065 g_server_depth = GetIntegerFromSettings(pRdpSettings, L"session bpp");
1066 if (g_server_depth > 16) g_server_depth = 16; /* hack, we don't support 24bpp yet */
1067 g_width = GetIntegerFromSettings(pRdpSettings, L"desktopwidth");
1068 g_height = GetIntegerFromSettings(pRdpSettings, L"desktopheight");
1069 g_screen_width = GetSystemMetrics(SM_CXSCREEN);
1070 g_screen_height = GetSystemMetrics(SM_CYSCREEN);
1071 g_xoff = GetSystemMetrics(SM_CXEDGE) * 2;
1072 g_yoff = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYEDGE) * 2;
1073
1074 ui_main();
1075 ret = 0;
1076 }
1077
1078 HeapFree(GetProcessHeap(),
1079 0,
1080 pRdpSettings->pSettings);
1081 }
1082
1083 HeapFree(GetProcessHeap(),
1084 0,
1085 pRdpSettings);
1086 }
1087
1088 WSACleanup();
1089 }
1090
1091 return ret;
1092 }
1093
1094
1095 /*****************************************************************************/
1096 void
1097 mi_begin_update(void)
1098 {
1099 }
1100
1101 /*****************************************************************************/
1102 void
1103 mi_end_update(void)
1104 {
1105 }
1106
1107 /*****************************************************************************/
1108 void
1109 mi_fill_rect(int x, int y, int cx, int cy, int colour)
1110 {
1111 HBRUSH brush;
1112 RECT rect;
1113 HDC maindc;
1114 HRGN rgn;
1115 int red;
1116 int green;
1117 int blue;
1118
1119 if (g_server_depth == 8)
1120 {
1121 red = (pal_entries[colour & 0xff] & 0xff0000) >> 16;
1122 green = (pal_entries[colour & 0xff] & 0xff00) >> 8;
1123 blue = pal_entries[colour & 0xff] & 0xff;
1124 }
1125 else if (g_server_depth == 15)
1126 {
1127 SPLIT_COLOUR15(colour, red, green, blue);
1128 }
1129 else if (g_server_depth == 16)
1130 {
1131 SPLIT_COLOUR16(colour, red, green, blue);
1132 }
1133 else
1134 {
1135 red = 0;
1136 green = 0;
1137 blue = 0;
1138 }
1139 maindc = GetWindowDC(g_Wnd);
1140 rgn = mi_clip(maindc);
1141 brush = CreateSolidBrush(RGB(red, green, blue));
1142 rect.left = x + g_xoff - g_xscroll;
1143 rect.top = y + g_yoff - g_yscroll;
1144 rect.right = rect.left + cx;
1145 rect.bottom = rect.top + cy;
1146 FillRect(maindc, &rect, brush);
1147 DeleteObject(brush);
1148 ReleaseDC(g_Wnd, maindc);
1149 DeleteObject(rgn);
1150 }
1151
1152 /*****************************************************************************/
1153 void
1154 mi_line(int x1, int y1, int x2, int y2, int colour)
1155 {
1156 HPEN pen;
1157 HDC maindc;
1158 HGDIOBJ save;
1159 HRGN rgn;
1160 int red;
1161 int green;
1162 int blue;
1163
1164 if (g_server_depth == 8)
1165 {
1166 red = (pal_entries[colour & 0xff] & 0xff0000) >> 16;
1167 green = (pal_entries[colour & 0xff] & 0xff00) >> 8;
1168 blue = pal_entries[colour & 0xff] & 0xff;
1169 }
1170 else if (g_server_depth == 15)
1171 {
1172 SPLIT_COLOUR15(colour, red, green, blue);
1173 }
1174 else if (g_server_depth == 16)
1175 {
1176 SPLIT_COLOUR16(colour, red, green, blue);
1177 }
1178 else
1179 {
1180 red = 0;
1181 green = 0;
1182 blue = 0;
1183 }
1184 maindc = GetWindowDC(g_Wnd);
1185 rgn = mi_clip(maindc);
1186 pen = CreatePen(PS_SOLID, 0, RGB(red, green, blue));
1187 save = SelectObject(maindc, pen);
1188 MoveToEx(maindc, x1 + g_xoff - g_xscroll, y1 + g_yoff - g_yscroll, 0);
1189 LineTo(maindc, x2 + g_xoff - g_xscroll, y2 + g_yoff - g_yscroll);
1190 SelectObject(maindc, save);
1191 DeleteObject(pen);
1192 ReleaseDC(g_Wnd, maindc);
1193 DeleteObject(rgn);
1194 }
1195
1196 /*****************************************************************************/
1197 void
1198 mi_screen_copy(int x, int y, int cx, int cy, int srcx, int srcy)
1199 {
1200 RECT rect;
1201 RECT clip_rect;
1202 RECT draw_rect;
1203 HRGN rgn;
1204 int ok_to_ScrollWindowEx;
1205
1206 ok_to_ScrollWindowEx = 1;
1207
1208 if (!ok_to_ScrollWindowEx)
1209 {
1210 rgn = CreateRectRgn(x - g_xscroll, y - g_yscroll,
1211 (x - g_xscroll) + cx,
1212 (y - g_yscroll) + cy);
1213 InvalidateRgn(g_Wnd, rgn, 0);
1214 DeleteObject(rgn);
1215 }
1216 else
1217 {
1218 /* this is all in client coords */
1219 rect.left = srcx - g_xscroll;
1220 rect.top = srcy - g_yscroll;
1221 rect.right = rect.left + cx;
1222 rect.bottom = rect.top + cy;
1223 clip_rect.left = g_clip_left - g_xscroll;
1224 clip_rect.top = g_clip_top - g_yscroll;
1225 clip_rect.right = g_clip_right - g_xscroll;
1226 clip_rect.bottom = g_clip_bottom - g_yscroll;
1227 if (IntersectRect(&draw_rect, &clip_rect, &g_wnd_clip))
1228 {
1229 rgn = CreateRectRgn(0, 0, 0, 0);
1230 ScrollWindowEx(g_Wnd, x - srcx, y - srcy, &rect, &draw_rect,
1231 rgn, 0, SW_ERASE);
1232 InvalidateRgn(g_Wnd, rgn, 0);
1233 DeleteObject(rgn);
1234 }
1235 }
1236 }
1237
1238 /*****************************************************************************/
1239 void
1240 mi_set_clip(int x, int y, int cx, int cy)
1241 {
1242 g_clip_left = x;
1243 g_clip_top = y;
1244 g_clip_right = g_clip_left + cx;
1245 g_clip_bottom = g_clip_top + cy;
1246 }
1247
1248 /*****************************************************************************/
1249 void
1250 mi_reset_clip(void)
1251 {
1252 g_clip_left = 0;
1253 g_clip_top = 0;
1254 g_clip_right = g_clip_left + g_width;
1255 g_clip_bottom = g_clip_top + g_height;
1256 }
1257
1258 /*****************************************************************************/
1259 void *
1260 mi_create_cursor(unsigned int x, unsigned int y,
1261 int width, int height,
1262 unsigned char * andmask, unsigned char * xormask)
1263 {
1264 HCURSOR hCur;
1265
1266 hCur = CreateCursor(g_Instance, x, y, width, height, andmask, xormask);
1267 if (hCur == 0)
1268 {
1269 hCur = LoadCursor(NULL, IDC_ARROW);
1270 }
1271 return hCur;
1272 }
1273
1274 /*****************************************************************************/
1275 void
1276 mi_destroy_cursor(void * cursor)
1277 {
1278 if (g_cursor == cursor)
1279 {
1280 g_cursor = 0;
1281 }
1282 DestroyCursor(cursor);
1283 }
1284
1285 /*****************************************************************************/
1286 void
1287 mi_set_cursor(void * cursor)
1288 {
1289 g_cursor = cursor;
1290 SetCursor(g_cursor);
1291 }
1292
1293 /*****************************************************************************/
1294 void
1295 mi_set_null_cursor(void)
1296 {
1297 }
1298