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