System dependent standard directory retrieval functions update : return const strings...
[blender.git] / intern / ghost / intern / GHOST_SystemWin32.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /**
30
31  * $Id$
32  * Copyright (C) 2001 NaN Technologies B.V.
33  * @author      Maarten Gribnau
34  * @date        May 7, 2001
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "GHOST_SystemWin32.h"
42 #include "GHOST_EventDragnDrop.h"
43
44 // win64 doesn't define GWL_USERDATA
45 #ifdef WIN32
46 #ifndef GWL_USERDATA
47 #define GWL_USERDATA GWLP_USERDATA
48 #define GWL_WNDPROC GWLP_WNDPROC
49 #endif
50 #endif
51
52 /*
53  * According to the docs the mouse wheel message is supported from windows 98 
54  * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the 
55  * wheel detent value are undefined.
56  */
57 #ifndef WM_MOUSEWHEEL
58 #define WM_MOUSEWHEEL 0x020A
59 #endif // WM_MOUSEWHEEL
60 #ifndef WHEEL_DELTA
61 #define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */
62 #endif // WHEEL_DELTA
63
64 /* 
65  * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2.
66  * MSDN: Declared in Winuser.h, include Windows.h 
67  * This does not seem to work with MinGW so we define our own here.
68  */
69 #ifndef XBUTTON1
70 #define XBUTTON1 0x0001
71 #endif // XBUTTON1
72 #ifndef XBUTTON2
73 #define XBUTTON2 0x0002
74 #endif // XBUTTON2
75 #ifndef WM_XBUTTONUP
76 #define WM_XBUTTONUP 524
77 #endif // WM_XBUTTONUP
78 #ifndef WM_XBUTTONDOWN
79 #define WM_XBUTTONDOWN 523
80 #endif // WM_XBUTTONDOWN
81
82 #include "GHOST_Debug.h"
83 #include "GHOST_DisplayManagerWin32.h"
84 #include "GHOST_EventButton.h"
85 #include "GHOST_EventCursor.h"
86 #include "GHOST_EventKey.h"
87 #include "GHOST_EventWheel.h"
88 #include "GHOST_EventNDOF.h"
89 #include "GHOST_TimerTask.h"
90 #include "GHOST_TimerManager.h"
91 #include "GHOST_WindowManager.h"
92 #include "GHOST_WindowWin32.h"
93 #include "GHOST_NDOFManager.h"
94
95 // Key code values not found in winuser.h
96 #ifndef VK_MINUS
97 #define VK_MINUS 0xBD
98 #endif // VK_MINUS
99 #ifndef VK_SEMICOLON
100 #define VK_SEMICOLON 0xBA
101 #endif // VK_SEMICOLON
102 #ifndef VK_PERIOD
103 #define VK_PERIOD 0xBE
104 #endif // VK_PERIOD
105 #ifndef VK_COMMA
106 #define VK_COMMA 0xBC
107 #endif // VK_COMMA
108 #ifndef VK_QUOTE
109 #define VK_QUOTE 0xDE
110 #endif // VK_QUOTE
111 #ifndef VK_BACK_QUOTE
112 #define VK_BACK_QUOTE 0xC0
113 #endif // VK_BACK_QUOTE
114 #ifndef VK_SLASH
115 #define VK_SLASH 0xBF
116 #endif // VK_SLASH
117 #ifndef VK_BACK_SLASH
118 #define VK_BACK_SLASH 0xDC
119 #endif // VK_BACK_SLASH
120 #ifndef VK_EQUALS
121 #define VK_EQUALS 0xBB
122 #endif // VK_EQUALS
123 #ifndef VK_OPEN_BRACKET
124 #define VK_OPEN_BRACKET 0xDB
125 #endif // VK_OPEN_BRACKET
126 #ifndef VK_CLOSE_BRACKET
127 #define VK_CLOSE_BRACKET 0xDD
128 #endif // VK_CLOSE_BRACKET
129 #ifndef VK_GR_LESS
130 #define VK_GR_LESS 0xE2
131 #endif // VK_GR_LESS
132
133
134 GHOST_SystemWin32::GHOST_SystemWin32()
135 : m_hasPerformanceCounter(false), m_freq(0), m_start(0),
136   m_separateLeftRight(false),
137   m_separateLeftRightInitialized(false)
138 {
139         m_displayManager = new GHOST_DisplayManagerWin32 ();
140         GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
141         m_displayManager->initialize();
142         
143         // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
144         OleInitialize(0);
145 }
146
147 GHOST_SystemWin32::~GHOST_SystemWin32()
148 {
149         // Shutdown COM
150         OleUninitialize();
151 }
152
153
154 GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const
155 {
156         // Hardware does not support high resolution timers. We will use GetTickCount instead then.
157         if (!m_hasPerformanceCounter) {
158                 return ::GetTickCount();
159         }
160
161         // Retrieve current count
162         __int64 count = 0;
163         ::QueryPerformanceCounter((LARGE_INTEGER*)&count);
164
165         // Calculate the time passed since system initialization.
166         __int64 delta = 1000*(count-m_start);
167
168         GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq);
169         return t; 
170 }
171
172
173 GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const
174 {
175         GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n");
176         GHOST_TUns8 numDisplays;
177         m_displayManager->getNumDisplays(numDisplays);
178         return numDisplays;
179 }
180
181
182 void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
183 {
184         width = ::GetSystemMetrics(SM_CXSCREEN);
185         height= ::GetSystemMetrics(SM_CYSCREEN);
186 }
187
188
189 GHOST_IWindow* GHOST_SystemWin32::createWindow(
190         const STR_String& title, 
191         GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
192         GHOST_TWindowState state, GHOST_TDrawingContextType type,
193         bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow )
194 {
195         GHOST_Window* window = 0;
196         window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples);
197         if (window) {
198                 if (window->getValid()) {
199                         // Store the pointer to the window
200 //                      if (state != GHOST_kWindowStateFullScreen) {
201                                 m_windowManager->addWindow(window);
202 //                      }
203                 }
204                 else {
205                         // An invalid window could be one that was used to test for AA
206                         GHOST_Window *other_window = ((GHOST_WindowWin32*)window)->getNextWindow();
207
208                         delete window;
209                         window = 0;
210                         
211                         // If another window is found, let the wm know about that one, but not the old one
212                         if (other_window)
213                         {
214                                 m_windowManager->addWindow(other_window);
215                                 window = other_window;
216                         }
217                 }
218         }
219         return window;
220 }
221
222
223 bool GHOST_SystemWin32::processEvents(bool waitForEvent)
224 {
225         MSG msg;
226         bool anyProcessed = false;
227
228         do {
229                 GHOST_TimerManager* timerMgr = getTimerManager();
230
231                 if (waitForEvent && !::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) {
232 #if 1
233                         ::Sleep(1);
234 #else
235                         GHOST_TUns64 next = timerMgr->nextFireTime();
236                         GHOST_TInt64 maxSleep = next - getMilliSeconds();
237                         
238                         if (next == GHOST_kFireTimeNever) {
239                                 ::WaitMessage();
240                         } else if(maxSleep >= 0.0) {
241                                 ::SetTimer(NULL, 0, maxSleep, NULL);
242                                 ::WaitMessage();
243                                 ::KillTimer(NULL, 0);
244                         }
245 #endif
246                 }
247
248                 if (timerMgr->fireTimers(getMilliSeconds())) {
249                         anyProcessed = true;
250                 }
251
252                 // Process all the events waiting for us
253                 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) {
254                         ::TranslateMessage(&msg);
255                         ::DispatchMessage(&msg);
256                         anyProcessed = true;
257                 }
258         } while (waitForEvent && !anyProcessed);
259
260         return anyProcessed;
261 }
262
263
264 GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
265 {
266         POINT point;
267         if(::GetCursorPos(&point)){
268                 x = point.x;
269                 y = point.y;
270                 return GHOST_kSuccess;
271         }
272         return GHOST_kFailure;
273 }
274
275
276 GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
277 {
278         return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
279 }
280
281
282 GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const
283 {
284         /*
285         GetKeyState and GetAsyncKeyState only work with Win95, Win98, NT4,
286         Terminal Server and Windows 2000.
287         But on WinME it always returns zero. These two functions are simply
288         skipped by Millenium Edition!
289
290         Official explanation from Microsoft:
291         Intentionally disabled.
292         It didn't work all that well on some newer hardware, and worked less 
293         well with the passage of time, so it was fully disabled in ME.
294         */
295         if (m_separateLeftRight && m_separateLeftRightInitialized) {
296                 bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
297                 keys.set(GHOST_kModifierKeyLeftShift, down);
298                 down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
299                 keys.set(GHOST_kModifierKeyRightShift, down);
300                 down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
301                 keys.set(GHOST_kModifierKeyLeftAlt, down);
302                 down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
303                 keys.set(GHOST_kModifierKeyRightAlt, down);
304                 down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
305                 keys.set(GHOST_kModifierKeyLeftControl, down);
306                 down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
307                 keys.set(GHOST_kModifierKeyRightControl, down);
308         }
309         else {
310                 bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0;
311                 keys.set(GHOST_kModifierKeyLeftShift, down);
312                 keys.set(GHOST_kModifierKeyRightShift, down);
313                 down = HIBYTE(::GetKeyState(VK_MENU)) != 0;
314                 keys.set(GHOST_kModifierKeyLeftAlt, down);
315                 keys.set(GHOST_kModifierKeyRightAlt, down);
316                 down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0;
317                 keys.set(GHOST_kModifierKeyLeftControl, down);
318                 keys.set(GHOST_kModifierKeyRightControl, down);
319         }
320         return GHOST_kSuccess;
321 }
322
323
324 GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const
325 {
326         /* Check for swapped buttons (left-handed mouse buttons)
327          * GetAsyncKeyState() will give back the state of the physical mouse buttons.
328          */
329         bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
330
331         bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0;
332         buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down);
333
334         down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0;
335         buttons.set(GHOST_kButtonMaskMiddle, down);
336
337         down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0;
338         buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down);
339         return GHOST_kSuccess;
340 }
341
342
343 GHOST_TSuccess GHOST_SystemWin32::init()
344 {
345         GHOST_TSuccess success = GHOST_System::init();
346
347         /* Disable scaling on high DPI displays on Vista */
348         HMODULE user32 = ::LoadLibraryA("user32.dll");
349         typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
350         LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
351                 (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
352         if (SetProcessDPIAware)
353                 SetProcessDPIAware();
354         FreeLibrary(user32);
355
356         // Determine whether this system has a high frequency performance counter. */
357         m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
358         if (m_hasPerformanceCounter) {
359                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n")
360                 ::QueryPerformanceCounter((LARGE_INTEGER*)&m_start);
361         }
362         else {
363                 GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n")
364         }
365
366         if (success) {
367                 WNDCLASS wc;
368                 wc.style= CS_HREDRAW | CS_VREDRAW;
369                 wc.lpfnWndProc= s_wndProc;
370                 wc.cbClsExtra= 0;
371                 wc.cbWndExtra= 0;
372                 wc.hInstance= ::GetModuleHandle(0);
373                 wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
374                 
375                 if (!wc.hIcon) {
376                         ::LoadIcon(NULL, IDI_APPLICATION);
377                 }
378                 wc.hCursor = ::LoadCursor(0, IDC_ARROW);
379                 wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
380                 wc.lpszMenuName = 0;
381                 wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
382     
383                 // Use RegisterClassEx for setting small icon
384                 if (::RegisterClass(&wc) == 0) {
385                         success = GHOST_kFailure;
386                 }
387         }
388         return success;
389 }
390
391
392 GHOST_TSuccess GHOST_SystemWin32::exit()
393 {
394         return GHOST_System::exit();
395 }
396
397
398 GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const
399 {
400         GHOST_TKey key;
401         bool isExtended = (lParam&(1<<24))?true:false;
402
403         if ((wParam >= '0') && (wParam <= '9')) {
404                 // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
405                 key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0);
406         }
407         else if ((wParam >= 'A') && (wParam <= 'Z')) {
408                 // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
409                 key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA);
410         }
411         else if ((wParam >= VK_F1) && (wParam <= VK_F24)) {
412                 key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1);
413         }
414         else {
415                 switch (wParam) {
416                 case VK_RETURN:
417                         key = isExtended?GHOST_kKeyNumpadEnter:GHOST_kKeyEnter;
418                         break;
419
420                 case VK_BACK:     key = GHOST_kKeyBackSpace;            break;
421                 case VK_TAB:      key = GHOST_kKeyTab;                          break;
422                 case VK_ESCAPE:   key = GHOST_kKeyEsc;                          break;
423                 case VK_SPACE:    key = GHOST_kKeySpace;                        break;
424                 case VK_PRIOR:    key = GHOST_kKeyUpPage;                       break;
425                 case VK_NEXT:     key = GHOST_kKeyDownPage;                     break;
426                 case VK_END:      key = GHOST_kKeyEnd;                          break;
427                 case VK_HOME:     key = GHOST_kKeyHome;                         break;
428                 case VK_INSERT:   key = GHOST_kKeyInsert;                       break;
429                 case VK_DELETE:   key = GHOST_kKeyDelete;                       break;
430                 case VK_LEFT:     key = GHOST_kKeyLeftArrow;            break;
431                 case VK_RIGHT:    key = GHOST_kKeyRightArrow;           break;
432                 case VK_UP:       key = GHOST_kKeyUpArrow;                      break;
433                 case VK_DOWN:     key = GHOST_kKeyDownArrow;            break;
434                 case VK_NUMPAD0:  key = GHOST_kKeyNumpad0;                      break;
435                 case VK_NUMPAD1:  key = GHOST_kKeyNumpad1;                      break;
436                 case VK_NUMPAD2:  key = GHOST_kKeyNumpad2;                      break;
437                 case VK_NUMPAD3:  key = GHOST_kKeyNumpad3;                      break;
438                 case VK_NUMPAD4:  key = GHOST_kKeyNumpad4;                      break;
439                 case VK_NUMPAD5:  key = GHOST_kKeyNumpad5;                      break;
440                 case VK_NUMPAD6:  key = GHOST_kKeyNumpad6;                      break;
441                 case VK_NUMPAD7:  key = GHOST_kKeyNumpad7;                      break;
442                 case VK_NUMPAD8:  key = GHOST_kKeyNumpad8;                      break;
443                 case VK_NUMPAD9:  key = GHOST_kKeyNumpad9;                      break;
444                 case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen;          break;
445                 case VK_PAUSE:    key = GHOST_kKeyPause;                        break;
446                 case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk;        break;
447                 case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus;          break;
448                 case VK_DECIMAL:  key = GHOST_kKeyNumpadPeriod;         break;
449                 case VK_DIVIDE:   key = GHOST_kKeyNumpadSlash;          break;
450                 case VK_ADD:      key = GHOST_kKeyNumpadPlus;           break;
451
452                 case VK_SEMICOLON:              key = GHOST_kKeySemicolon;              break;
453                 case VK_EQUALS:                 key = GHOST_kKeyEqual;                  break;
454                 case VK_COMMA:                  key = GHOST_kKeyComma;                  break;
455                 case VK_MINUS:                  key = GHOST_kKeyMinus;                  break;
456                 case VK_PERIOD:                 key = GHOST_kKeyPeriod;                 break;
457                 case VK_SLASH:                  key = GHOST_kKeySlash;                  break;
458                 case VK_BACK_QUOTE:             key = GHOST_kKeyAccentGrave;    break;
459                 case VK_OPEN_BRACKET:   key = GHOST_kKeyLeftBracket;    break;
460                 case VK_BACK_SLASH:             key = GHOST_kKeyBackslash;              break;
461                 case VK_CLOSE_BRACKET:  key = GHOST_kKeyRightBracket;   break;
462                 case VK_QUOTE:                  key = GHOST_kKeyQuote;                  break;
463                 case VK_GR_LESS:                key = GHOST_kKeyGrLess;                 break;
464
465                 // Process these keys separately because we need to distinguish right from left modifier keys
466                 case VK_SHIFT:
467                 case VK_CONTROL:
468                 case VK_MENU:
469
470                 // Ignore these keys
471                 case VK_NUMLOCK:
472                 case VK_SCROLL:
473                 case VK_CAPITAL:
474                 default:
475                         key = GHOST_kKeyUnknown;
476                         break;
477                 }
478         }
479         return key;
480 }
481
482
483 void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window)
484 {
485         GHOST_ModifierKeys oldModifiers, newModifiers;
486         // Retrieve old state of the modifier keys
487         ((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers);
488         // Retrieve current state of the modifier keys
489         ((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers);
490
491         // Compare the old and the new
492         if (!newModifiers.equals(oldModifiers)) {
493                 // Create events for the masks that changed
494                 for (int i = 0; i < GHOST_kModifierKeyNumMasks; i++) {
495                         if (newModifiers.get((GHOST_TModifierKeyMask)i) != oldModifiers.get((GHOST_TModifierKeyMask)i)) {
496                                 // Convert the mask to a key code
497                                 GHOST_TKey key = GHOST_ModifierKeys::getModifierKeyCode((GHOST_TModifierKeyMask)i);
498                                 bool keyDown = newModifiers.get((GHOST_TModifierKeyMask)i);
499                                 GHOST_EventKey* event;
500                                 if (key != GHOST_kKeyUnknown) {
501                                         // Create an event
502                                         event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key);
503                                         pushEvent(event);
504                                 }
505                         }
506                 }
507         }
508
509         // Store new modifier keys state
510         ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers);
511 }
512
513
514 GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
515 {
516         return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
517 }
518
519
520 GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
521 {
522         GHOST_TInt32 x_screen, y_screen;
523         GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
524         GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
525         
526         system->getCursorPosition(x_screen, y_screen);
527
528         if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
529         {
530                 GHOST_TInt32 x_new= x_screen;
531                 GHOST_TInt32 y_new= y_screen;
532                 GHOST_TInt32 x_accum, y_accum;
533                 GHOST_Rect bounds;
534
535                 /* fallback to window bounds */
536                 if(window->getCursorGrabBounds(bounds)==GHOST_kFailure){
537                         window->getClientBounds(bounds);
538                 }
539
540                 /* could also clamp to screen bounds
541                  * wrap with a window outside the view will fail atm  */
542
543                 bounds.wrapPoint(x_new, y_new, 2); /* offset of one incase blender is at screen bounds */
544
545                 window->getCursorGrabAccum(x_accum, y_accum);
546                 if(x_new != x_screen|| y_new != y_screen) {
547                         /* when wrapping we don't need to add an event because the
548                          * setCursorPosition call will cause a new event after */
549                         system->setCursorPosition(x_new, y_new); /* wrap */
550                         window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
551                 }else{
552                         return new GHOST_EventCursor(system->getMilliSeconds(),
553                                                                                  GHOST_kEventCursorMove,
554                                                                                  window,
555                                                                                  x_screen + x_accum,
556                                                                                  y_screen + y_accum
557                         );
558                 }
559
560         }
561         else {
562                 return new GHOST_EventCursor(system->getMilliSeconds(),
563                                                                          GHOST_kEventCursorMove,
564                                                                          window,
565                                                                          x_screen,
566                                                                          y_screen
567                 );
568         }
569         return NULL;
570 }
571
572
573 GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
574 {
575         // short fwKeys = LOWORD(wParam);                       // key flags
576         int zDelta = (short) HIWORD(wParam);    // wheel rotation
577         
578         // zDelta /= WHEEL_DELTA;
579         // temporary fix below: microsoft now has added more precision, making the above division not work
580         if (zDelta <= 0 ) zDelta= -1; else zDelta= 1;   
581         
582         // short xPos = (short) LOWORD(lParam); // horizontal position of pointer
583         // short yPos = (short) HIWORD(lParam); // vertical position of pointer
584         return new GHOST_EventWheel (getSystem()->getMilliSeconds(), window, zDelta);
585 }
586
587
588 GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam)
589 {
590         GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(wParam, lParam);
591         GHOST_EventKey* event;
592         if (key != GHOST_kKeyUnknown) {
593                 MSG keyMsg;
594                 char ascii = '\0';
595
596                         /* Eat any character related messages */
597                 if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) {
598                         ascii = (char) keyMsg.wParam;
599                 }
600
601                 event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
602         }
603         else {
604                 event = 0;
605         }
606         return event;
607 }
608
609
610 GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
611 {
612         return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
613 }
614
615 GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, 
616                                                                                                         GHOST_TDragnDropTypes draggedObjectType,
617                                                                                                         GHOST_IWindow* window,
618                                                                                                         int mouseX, int mouseY,
619                                                                                                         void* data)
620 {
621         GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
622         return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
623                                                                                                           eventType,
624                                                                                                           draggedObjectType,
625                                                                                                           window,mouseX,mouseY,data)
626                         );
627 }
628
629 void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
630 {
631         minmax->ptMinTrackSize.x=320;
632         minmax->ptMinTrackSize.y=240;
633 }
634
635
636 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
637 {
638         GHOST_Event* event = 0;
639         LRESULT lResult = 0;
640         GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
641         GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
642
643         if (hwnd) {
644                 GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
645                 if (window) {
646                         switch (msg) {
647                                 ////////////////////////////////////////////////////////////////////////
648                                 // Keyboard events, processed
649                                 ////////////////////////////////////////////////////////////////////////
650                                 case WM_KEYDOWN:
651                                         /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a 
652                                          * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt
653                                          * key is not pressed. 
654                                          */
655                                 case WM_SYSKEYDOWN:
656                                         /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when 
657                                          * the user presses the F10 key (which activates the menu bar) or holds down the 
658                                          * alt key and then presses another key. It also occurs when no window currently 
659                                          * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the 
660                                          * active window. The window that receives the message can distinguish between these 
661                                          * two contexts by checking the context code in the lKeyData parameter. 
662                                          */
663                                         switch (wParam) {
664                                                 case VK_SHIFT:
665                                                 case VK_CONTROL:
666                                                 case VK_MENU:
667                                                         if (!system->m_separateLeftRightInitialized) {
668                                                                 // Check whether this system supports separate left and right keys
669                                                                 switch (wParam) {
670                                                                         case VK_SHIFT:
671                                                                                 system->m_separateLeftRight = 
672                                                                                         (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
673                                                                                         (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
674                                                                                         true : false;
675                                                                                 break;
676                                                                         case VK_CONTROL:
677                                                                                 system->m_separateLeftRight = 
678                                                                                         (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
679                                                                                         (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
680                                                                                         true : false;
681                                                                                 break;
682                                                                         case VK_MENU:
683                                                                                 system->m_separateLeftRight = 
684                                                                                         (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
685                                                                                         (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
686                                                                                         true : false;
687                                                                                 break;
688                                                                 }
689                                                                 system->m_separateLeftRightInitialized = true;
690                                                         }
691                                                         system->processModifierKeys(window);
692                                                         // Bypass call to DefWindowProc
693                                                         return 0;
694                                                 default:
695                                                         event = processKeyEvent(window, true, wParam, lParam);
696                                                         if (!event) {
697                                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
698                                                                 GHOST_PRINT(msg)
699                                                                 GHOST_PRINT(" key ignored\n")
700                                                         }
701                                                         break;
702                                                 }
703                                         break;
704
705                                 case WM_KEYUP:
706                                 case WM_SYSKEYUP:
707                                         switch (wParam) {
708                                                 case VK_SHIFT:
709                                                 case VK_CONTROL:
710                                                 case VK_MENU:
711                                                         system->processModifierKeys(window);
712                                                         // Bypass call to DefWindowProc
713                                                         return 0;
714                                                 default:
715                                                         event = processKeyEvent(window, false, wParam, lParam);
716                                                         if (!event) {
717                                                                 GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
718                                                                 GHOST_PRINT(msg)
719                                                                 GHOST_PRINT(" key ignored\n")
720                                                         }
721                                                         break;
722                                         }
723                                         break;
724
725                                 ////////////////////////////////////////////////////////////////////////
726                                 // Keyboard events, ignored
727                                 ////////////////////////////////////////////////////////////////////////
728                                 case WM_CHAR:
729                                         /* The WM_CHAR message is posted to the window with the keyboard focus when 
730                                          * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR 
731                                          * contains the character code of the key that was pressed. 
732                                          */
733                                 case WM_DEADCHAR:
734                                         /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
735                                          * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR 
736                                          * specifies a character code generated by a dead key. A dead key is a key that 
737                                          * generates a character, such as the umlaut (double-dot), that is combined with 
738                                          * another character to form a composite character. For example, the umlaut-O 
739                                          * character (Ù) is generated by typing the dead key for the umlaut character, and 
740                                          * then typing the O key.
741                                          */
742                                 case WM_SYSDEADCHAR:
743                                         /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when 
744                                          * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. 
745                                          * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, 
746                                          * a dead key that is pressed while holding down the alt key. 
747                                          */
748                                         break;
749                                 ////////////////////////////////////////////////////////////////////////
750                                 // Tablet events, processed
751                                 ////////////////////////////////////////////////////////////////////////
752                                 case WT_PACKET:
753                                         ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam);
754                                         break;
755                                 case WT_CSRCHANGE:
756                                 case WT_PROXIMITY:
757                                         ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent();
758                                         break;
759                                 ////////////////////////////////////////////////////////////////////////
760                                 // Mouse events, processed
761                                 ////////////////////////////////////////////////////////////////////////
762                                 case WM_LBUTTONDOWN:
763                                         window->registerMouseClickEvent(true);
764                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
765                                         break;
766                                 case WM_MBUTTONDOWN:
767                                         window->registerMouseClickEvent(true);
768                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
769                                         break;
770                                 case WM_RBUTTONDOWN:
771                                         window->registerMouseClickEvent(true);
772                                         event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
773                                         break;
774                                 case WM_XBUTTONDOWN:
775                                         window->registerMouseClickEvent(true);
776                                         if ((short) HIWORD(wParam) == XBUTTON1){
777                                                 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4);
778                                         }else if((short) HIWORD(wParam) == XBUTTON2){
779                                                 event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5);
780                                         }
781                                         break;
782                                 case WM_LBUTTONUP:
783                                         window->registerMouseClickEvent(false);
784                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
785                                         break;
786                                 case WM_MBUTTONUP:
787                                         window->registerMouseClickEvent(false);
788                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
789                                         break;
790                                 case WM_RBUTTONUP:
791                                         window->registerMouseClickEvent(false);
792                                         event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
793                                         break;
794                                 case WM_XBUTTONUP:
795                                         window->registerMouseClickEvent(false);
796                                         if ((short) HIWORD(wParam) == XBUTTON1){
797                                                 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4);
798                                         }else if((short) HIWORD(wParam) == XBUTTON2){
799                                                 event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5);
800                                         }
801                                         break;
802                                 case WM_MOUSEMOVE:
803                                         event = processCursorEvent(GHOST_kEventCursorMove, window);
804                                         break;
805                                 case WM_MOUSEWHEEL:
806                                         /* The WM_MOUSEWHEEL message is sent to the focus window 
807                                          * when the mouse wheel is rotated. The DefWindowProc 
808                                          * function propagates the message to the window's parent.
809                                          * There should be no internal forwarding of the message, 
810                                          * since DefWindowProc propagates it up the parent chain 
811                                          * until it finds a window that processes it.
812                                          */
813                                         event = processWheelEvent(window, wParam, lParam);
814                                         break;
815                                 case WM_SETCURSOR:
816                                         /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
817                                          * to move within a window and mouse input is not captured.
818                                          * This means we have to set the cursor shape every time the mouse moves!
819                                          * The DefWindowProc function uses this message to set the cursor to an 
820                                          * arrow if it is not in the client area.
821                                          */
822                                         if (LOWORD(lParam) == HTCLIENT) {
823                                                 // Load the current cursor
824                                                 window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
825                                                 // Bypass call to DefWindowProc
826                                                 return 0;
827                                         } 
828                                         else {
829                                                 // Outside of client area show standard cursor
830                                                 window->loadCursor(true, GHOST_kStandardCursorDefault);
831                                         }
832                                         break;
833
834                                 ////////////////////////////////////////////////////////////////////////
835                                 // Mouse events, ignored
836                                 ////////////////////////////////////////////////////////////////////////
837                                 case WM_NCMOUSEMOVE:
838                                         /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved 
839                                          * within the nonclient area of the window. This message is posted to the window 
840                                          * that contains the cursor. If a window has captured the mouse, this message is not posted.
841                                          */
842                                 case WM_NCHITTEST:
843                                         /* The WM_NCHITTEST message is sent to a window when the cursor moves, or 
844                                          * when a mouse button is pressed or released. If the mouse is not captured, 
845                                          * the message is sent to the window beneath the cursor. Otherwise, the message 
846                                          * is sent to the window that has captured the mouse. 
847                                          */
848                                         break;
849
850                                 ////////////////////////////////////////////////////////////////////////
851                                 // Window events, processed
852                                 ////////////////////////////////////////////////////////////////////////
853                                 case WM_CLOSE:
854                                         /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */
855                                         event = processWindowEvent(GHOST_kEventWindowClose, window);
856                                         break;
857                                 case WM_ACTIVATE:
858                                         /* The WM_ACTIVATE message is sent to both the window being activated and the window being 
859                                          * deactivated. If the windows use the same input queue, the message is sent synchronously, 
860                                          * first to the window procedure of the top-level window being deactivated, then to the window
861                                          * procedure of the top-level window being activated. If the windows use different input queues,
862                                          * the message is sent asynchronously, so the window is activated immediately. 
863                                          */
864                                         event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
865                                         /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
866                                         will not be dispatched to OUR active window if we minimize one of OUR windows. */
867                                         lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
868                                         break;
869                                 case WM_PAINT:
870                                         /* An application sends the WM_PAINT message when the system or another application 
871                                          * makes a request to paint a portion of an application's window. The message is sent
872                                          * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage 
873                                          * function when the application obtains a WM_PAINT message by using the GetMessage or 
874                                          * PeekMessage function. 
875                                          */
876                                         event = processWindowEvent(GHOST_kEventWindowUpdate, window);
877                                         ::ValidateRect(hwnd, NULL);
878                                         break;
879                                 case WM_GETMINMAXINFO:
880                                         /* The WM_GETMINMAXINFO message is sent to a window when the size or 
881                                          * position of the window is about to change. An application can use 
882                                          * this message to override the window's default maximized size and 
883                                          * position, or its default minimum or maximum tracking size. 
884                                          */
885                                         processMinMaxInfo((MINMAXINFO *) lParam);
886                                         /* Let DefWindowProc handle it. */
887                                         break;
888                                 case WM_SIZE:
889                                         /* The WM_SIZE message is sent to a window after its size has changed.
890                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
891                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
892                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
893                                          * message without calling DefWindowProc.
894                                          */
895                                         event = processWindowEvent(GHOST_kEventWindowSize, window);
896                                         break;
897                                 case WM_CAPTURECHANGED:
898                                         window->lostMouseCapture();
899                                         break;
900                                 case WM_MOVING:
901                                         /* The WM_MOVING message is sent to a window that the user is moving. By processing 
902                                          * this message, an application can monitor the size and position of the drag rectangle
903                                          * and, if needed, change its size or position.
904                                          */
905                                 case WM_MOVE:
906                                         /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
907                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
908                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
909                                          * message without calling DefWindowProc. 
910                                          */
911                                         event = processWindowEvent(GHOST_kEventWindowMove, window);
912                                         break;
913                                 ////////////////////////////////////////////////////////////////////////
914                                 // Window events, ignored
915                                 ////////////////////////////////////////////////////////////////////////
916                                 case WM_WINDOWPOSCHANGED:
917                                         /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
918                                          * in the Z order has changed as a result of a call to the SetWindowPos function or 
919                                          * another window-management function.
920                                          * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
921                                          * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
922                                          * to perform any move or size change processing during the WM_WINDOWPOSCHANGED 
923                                          * message without calling DefWindowProc.
924                                          */
925                                 case WM_ERASEBKGND:
926                                         /* An application sends the WM_ERASEBKGND message when the window background must be 
927                                          * erased (for example, when a window is resized). The message is sent to prepare an 
928                                          * invalidated portion of a window for painting. 
929                                          */
930                                 case WM_NCPAINT:
931                                         /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */
932                                 case WM_NCACTIVATE:
933                                         /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed 
934                                          * to indicate an active or inactive state. 
935                                          */
936                                 case WM_DESTROY:
937                                         /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window 
938                                          * procedure of the window being destroyed after the window is removed from the screen. 
939                                          * This message is sent first to the window being destroyed and then to the child windows 
940                                          * (if any) as they are destroyed. During the processing of the message, it can be assumed 
941                                          * that all child windows still exist. 
942                                          */
943                                 case WM_NCDESTROY:
944                                         /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The 
945                                          * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY
946                                          * message. WM_DESTROY is used to free the allocated memory object associated with the window. 
947                                          */
948                                 case WM_KILLFOCUS:
949                                         /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */
950                                 case WM_SHOWWINDOW:
951                                         /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
952                                 case WM_WINDOWPOSCHANGING:
953                                         /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in 
954                                          * the Z order is about to change as a result of a call to the SetWindowPos function or 
955                                          * another window-management function. 
956                                          */
957                                 case WM_SETFOCUS:
958                                         /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
959                                 case WM_ENTERSIZEMOVE:
960                                         /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving 
961                                          * or sizing modal loop. The window enters the moving or sizing modal loop when the user 
962                                          * clicks the window's title bar or sizing border, or when the window passes the 
963                                          * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the 
964                                          * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when 
965                                          * DefWindowProc returns. 
966                                          */
967                                         break;
968                                         
969                                 ////////////////////////////////////////////////////////////////////////
970                                 // Other events
971                                 ////////////////////////////////////////////////////////////////////////
972                                 case WM_GETTEXT:
973                                         /* An application sends a WM_GETTEXT message to copy the text that 
974                                          * corresponds to a window into a buffer provided by the caller. 
975                                          */
976                                 case WM_ACTIVATEAPP:
977                                         /* The WM_ACTIVATEAPP message is sent when a window belonging to a 
978                                          * different application than the active window is about to be activated.
979                                          * The message is sent to the application whose window is being activated
980                                          * and to the application whose window is being deactivated. 
981                                          */
982                                 case WM_TIMER:
983                                         /* The WIN32 docs say:
984                                          * The WM_TIMER message is posted to the installing thread's message queue
985                                          * when a timer expires. You can process the message by providing a WM_TIMER
986                                          * case in the window procedure. Otherwise, the default window procedure will
987                                          * call the TimerProc callback function specified in the call to the SetTimer
988                                          * function used to install the timer. 
989                                          *
990                                          * In GHOST, we let DefWindowProc call the timer callback.
991                                          */
992                                         break;
993                                 case WM_BLND_NDOF_AXIS:
994                                         {
995                                                 GHOST_TEventNDOFData ndofdata;
996                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
997                                                 system->m_eventManager->
998                                                         pushEvent(new GHOST_EventNDOF(
999                                                                 system->getMilliSeconds(), 
1000                                                                 GHOST_kEventNDOFMotion, 
1001                                                                 window, ndofdata));
1002                                         }
1003                                         break;
1004                                 case WM_BLND_NDOF_BTN:
1005                                         {
1006                                                 GHOST_TEventNDOFData ndofdata;
1007                                                 system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
1008                                                 system->m_eventManager->
1009                                                         pushEvent(new GHOST_EventNDOF(
1010                                                                 system->getMilliSeconds(), 
1011                                                                 GHOST_kEventNDOFButton, 
1012                                                                 window, ndofdata));
1013                                         }
1014                                         break;
1015                         }
1016                 }
1017                 else {
1018                         // Event found for a window before the pointer to the class has been set.
1019                         GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
1020                         /* These are events we typically miss at this point:
1021                            WM_GETMINMAXINFO     0x24
1022                            WM_NCCREATE                  0x81
1023                            WM_NCCALCSIZE                0x83
1024                            WM_CREATE                    0x01
1025                            We let DefWindowProc do the work.
1026                         */
1027                 }
1028         }
1029         else {
1030                 // Events without valid hwnd
1031                 GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
1032         }
1033
1034         if (event) {
1035                 system->pushEvent(event);
1036         }
1037         else {
1038                 lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
1039         }
1040         return lResult;
1041 }
1042
1043 GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const 
1044 {
1045         char *buffer;
1046         char *temp_buff;
1047         
1048         if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) {
1049                 HANDLE hData = GetClipboardData( CF_TEXT );
1050                 if (hData == NULL) {
1051                         CloseClipboard();
1052                         return NULL;
1053                 }
1054                 buffer = (char*)GlobalLock( hData );
1055                 
1056                 temp_buff = (char*) malloc(strlen(buffer)+1);
1057                 strcpy(temp_buff, buffer);
1058                 
1059                 GlobalUnlock( hData );
1060                 CloseClipboard();
1061                 
1062                 temp_buff[strlen(buffer)] = '\0';
1063                 if (buffer) {
1064                         return (GHOST_TUns8*)temp_buff;
1065                 } else {
1066                         return NULL;
1067                 }
1068         } else {
1069                 return NULL;
1070         }
1071 }
1072
1073 void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
1074 {
1075         if(selection) {return;} // for copying the selection, used on X11
1076
1077         if (OpenClipboard(NULL)) {
1078                 HLOCAL clipbuffer;
1079                 char *data;
1080                 
1081                 if (buffer) {
1082                         EmptyClipboard();
1083                         
1084                         clipbuffer = LocalAlloc(LMEM_FIXED,((strlen(buffer)+1)));
1085                         data = (char*)GlobalLock(clipbuffer);
1086
1087                         strcpy(data, (char*)buffer);
1088                         data[strlen(buffer)] = '\0';
1089                         LocalUnlock(clipbuffer);
1090                         SetClipboardData(CF_TEXT,clipbuffer);
1091                 }
1092                 CloseClipboard();
1093         } else {
1094                 return;
1095         }
1096 }
1097
1098 const GHOST_TUns8* GHOST_SystemWin32::getSystemDir() const
1099 {
1100         return NULL;
1101 }
1102
1103 const GHOST_TUns8* GHOST_SystemWin32::getUserDir() const
1104 {
1105         return NULL;
1106 }