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

« back to all changes in this revision

Viewing changes to hw/xwin/winclipboardwndproc.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
 
3
 *
 
4
 *Permission is hereby granted, free of charge, to any person obtaining
 
5
 * a copy of this software and associated documentation files (the
 
6
 *"Software"), to deal in the Software without restriction, including
 
7
 *without limitation the rights to use, copy, modify, merge, publish,
 
8
 *distribute, sublicense, and/or sell copies of the Software, and to
 
9
 *permit persons to whom the Software is furnished to do so, subject to
 
10
 *the following conditions:
 
11
 *
 
12
 *The above copyright notice and this permission notice shall be
 
13
 *included in all copies or substantial portions of the Software.
 
14
 *
 
15
 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
16
 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
18
 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
 
19
 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 
20
 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
21
 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
 *
 
23
 *Except as contained in this notice, the name of Harold L Hunt II
 
24
 *shall not be used in advertising or otherwise to promote the sale, use
 
25
 *or other dealings in this Software without prior written authorization
 
26
 *from Harold L Hunt II.
 
27
 *
 
28
 * Authors:     Harold L Hunt II
 
29
 */
 
30
 
 
31
#ifdef HAVE_XWIN_CONFIG_H
 
32
#include <xwin-config.h>
 
33
#endif
 
34
#include <sys/types.h>
 
35
#include <sys/time.h>
 
36
#include "winclipboard.h"
 
37
 
 
38
 
 
39
/*
 
40
 * Constants
 
41
 */
 
42
 
 
43
#define WIN_CLIPBOARD_PROP      "cyg_clipboard_prop"
 
44
#define WIN_POLL_TIMEOUT        1
 
45
 
 
46
 
 
47
/*
 
48
 * References to external symbols
 
49
 */
 
50
 
 
51
extern Bool             g_fUseUnicode;
 
52
extern Bool             g_fUnicodeSupport;
 
53
extern void             *g_pClipboardDisplay;
 
54
extern Window           g_iClipboardWindow;
 
55
extern Atom             g_atomLastOwnedSelection;
 
56
 
 
57
 
 
58
/* 
 
59
 * Local function prototypes
 
60
 */
 
61
 
 
62
static Bool
 
63
winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
 
64
                          Bool fUseUnicode, int iTimeoutSec);
 
65
 
 
66
 
 
67
/*
 
68
 * Process X events up to specified timeout
 
69
 */
 
70
 
 
71
static int
 
72
winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
 
73
                          Bool fUseUnicode, int iTimeoutSec)
 
74
{
 
75
  int                   iConnNumber;
 
76
  struct timeval        tv;
 
77
  int                   iReturn;
 
78
  DWORD                 dwStopTime = (GetTickCount () / 1000) + iTimeoutSec;
 
79
 
 
80
  /* We need to ensure that all pending events are processed */
 
81
  XSync (pDisplay, FALSE);
 
82
 
 
83
  /* Get our connection number */
 
84
  iConnNumber = ConnectionNumber (pDisplay);
 
85
 
 
86
  /* Loop for X events */
 
87
  while (1)
 
88
    {
 
89
      fd_set            fdsRead;
 
90
 
 
91
      /* Setup the file descriptor set */
 
92
      FD_ZERO (&fdsRead);
 
93
      FD_SET (iConnNumber, &fdsRead);
 
94
 
 
95
      /* Adjust timeout */
 
96
      tv.tv_sec = dwStopTime - (GetTickCount () / 1000);
 
97
      tv.tv_usec = 0;
 
98
 
 
99
      /* Break out if no time left */
 
100
      if (tv.tv_sec < 0)
 
101
        return WIN_XEVENTS_SUCCESS;
 
102
 
 
103
      /* Wait for a Windows event or an X event */
 
104
      iReturn = select (iConnNumber + 1,/* Highest fds number */
 
105
                        &fdsRead,       /* Read mask */
 
106
                        NULL,           /* No write mask */
 
107
                        NULL,           /* No exception mask */
 
108
                        &tv);           /* No timeout */
 
109
      if (iReturn <= 0)
 
110
        {
 
111
          ErrorF ("winProcessXEventsTimeout - Call to select () failed: %d.  "
 
112
                  "Bailing.\n", iReturn);
 
113
          break;
 
114
        }
 
115
 
 
116
      /* Branch on which descriptor became active */
 
117
      if (FD_ISSET (iConnNumber, &fdsRead))
 
118
        {
 
119
          /* Process X events */
 
120
          /* Exit when we see that server is shutting down */
 
121
          iReturn = winClipboardFlushXEvents (hwnd,
 
122
                                              iWindow,
 
123
                                              pDisplay,
 
124
                                              fUseUnicode);
 
125
          if (WIN_XEVENTS_NOTIFY == iReturn
 
126
              || WIN_XEVENTS_CONVERT == iReturn)
 
127
            {
 
128
              /* Bail out if convert or notify processed */
 
129
              return iReturn;
 
130
            }
 
131
        }
 
132
    }
 
133
 
 
134
  return WIN_XEVENTS_SUCCESS;
 
135
}
 
136
 
 
137
 
 
138
/*
 
139
 * Process a given Windows message
 
140
 */
 
141
 
 
142
LRESULT CALLBACK
 
143
winClipboardWindowProc (HWND hwnd, UINT message, 
 
144
                        WPARAM wParam, LPARAM lParam)
 
145
{
 
146
  static HWND           s_hwndNextViewer;
 
147
  static Bool           s_fCBCInitialized;
 
148
 
 
149
  /* Branch on message type */
 
150
  switch (message)
 
151
    {
 
152
    case WM_DESTROY:
 
153
      {
 
154
        winDebug ("winClipboardWindowProc - WM_DESTROY\n");
 
155
 
 
156
        /* Remove ourselves from the clipboard chain */
 
157
        ChangeClipboardChain (hwnd, s_hwndNextViewer);
 
158
        
 
159
        s_hwndNextViewer = NULL;
 
160
 
 
161
        PostQuitMessage (0);
 
162
      }
 
163
      return 0;
 
164
 
 
165
 
 
166
    case WM_CREATE:
 
167
      {
 
168
        winDebug ("winClipboardWindowProc - WM_CREATE\n");
 
169
        
 
170
        /* Add ourselves to the clipboard viewer chain */
 
171
        s_hwndNextViewer = SetClipboardViewer (hwnd);
 
172
        if (s_hwndNextViewer == hwnd)
 
173
          {
 
174
            s_hwndNextViewer = NULL;
 
175
            winErrorFVerb (1, "winClipboardWindowProc - WM_CREATE: "
 
176
                           "attempted to set next window to ourselves.");
 
177
          }
 
178
      }
 
179
      return 0;
 
180
 
 
181
 
 
182
    case WM_CHANGECBCHAIN:
 
183
      {
 
184
        static Bool s_fProcessingChangeCBChain = FALSE;
 
185
        winDebug ("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%x) "
 
186
                  "lParam(%x) s_hwndNextViewer(%x)\n", 
 
187
                  wParam, lParam, s_hwndNextViewer);
 
188
 
 
189
 
 
190
        /*
 
191
         * We've occasionally seen a loop in the clipboard chain.  Break
 
192
         * it on the first hint of recursion.
 
193
         */
 
194
        if (! s_fProcessingChangeCBChain) 
 
195
          {
 
196
            s_fProcessingChangeCBChain = TRUE;
 
197
          }
 
198
        else
 
199
          {
 
200
            winErrorFVerb (1, "winClipboardWindowProc - WM_CHANGECBCHAIN - "
 
201
                           "Nested calls detected.  Bailing.\n");
 
202
            winDebug ("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
 
203
            return 0;
 
204
          }
 
205
        
 
206
        if ((HWND) wParam == s_hwndNextViewer)
 
207
          {
 
208
            s_hwndNextViewer = (HWND) lParam;
 
209
            if (s_hwndNextViewer == hwnd)
 
210
              {
 
211
                s_hwndNextViewer = NULL;
 
212
                winErrorFVerb (1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
 
213
                               "attempted to set next window to ourselves.");
 
214
              }
 
215
          }
 
216
        else if (s_hwndNextViewer)
 
217
          SendMessage (s_hwndNextViewer, message,
 
218
                       wParam, lParam);
 
219
 
 
220
        s_fProcessingChangeCBChain = FALSE;
 
221
      }
 
222
      winDebug ("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
 
223
      return 0;
 
224
 
 
225
    case WM_WM_REINIT:
 
226
      {
 
227
        /* Ensure that we're in the clipboard chain.  Some apps,
 
228
         * WinXP's remote desktop for one, don't play nice with the
 
229
         * chain.  This message is called whenever we receive a
 
230
         * WM_ACTIVATEAPP message to ensure that we continue to
 
231
         * receive clipboard messages.
 
232
         *
 
233
         * It might be possible to detect if we're still in the chain
 
234
         * by calling SendMessage (GetClipboardViewer(),
 
235
         * WM_DRAWCLIPBOARD, 0, 0); and then seeing if we get the
 
236
         * WM_DRAWCLIPBOARD message.  That, however, might be more
 
237
         * expensive than just putting ourselves back into the chain.
 
238
         */
 
239
 
 
240
        winDebug ("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
 
241
        if (hwnd != GetClipboardViewer ())
 
242
          {
 
243
            winDebug ("  WM_WM_REINIT: Replacing us(%x) with %x at head "
 
244
                      "of chain\n", hwnd, s_hwndNextViewer);
 
245
            s_fCBCInitialized = FALSE;
 
246
            ChangeClipboardChain (hwnd, s_hwndNextViewer);
 
247
            s_hwndNextViewer = NULL;
 
248
            s_fCBCInitialized = FALSE;
 
249
            winDebug ("  WM_WM_REINIT: Putting us back at head of chain.\n");
 
250
            s_hwndNextViewer = SetClipboardViewer (hwnd);
 
251
            if (s_hwndNextViewer == hwnd)
 
252
              {
 
253
                s_hwndNextViewer = NULL;
 
254
                winErrorFVerb (1, "winClipboardWindowProc - WM_WM_REINIT: "
 
255
                               "attempted to set next window to ourselves.\n");
 
256
              }
 
257
          }
 
258
        else
 
259
          {
 
260
            winDebug ("  WM_WM_REINIT: already at head of viewer chain.\n");
 
261
          }
 
262
      }
 
263
      winDebug ("winClipboardWindowProc - WM_WM_REINIT: Exit\n");
 
264
      return 0;
 
265
 
 
266
 
 
267
    case WM_DRAWCLIPBOARD:
 
268
      {
 
269
        static Bool s_fProcessingDrawClipboard = FALSE;
 
270
        Display *pDisplay = g_pClipboardDisplay;
 
271
        Window  iWindow = g_iClipboardWindow;
 
272
        int     iReturn;
 
273
 
 
274
        winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
 
275
 
 
276
        /*
 
277
         * We've occasionally seen a loop in the clipboard chain.  Break
 
278
         * it on the first hint of recursion.
 
279
         */
 
280
        if (! s_fProcessingDrawClipboard) 
 
281
          {
 
282
            s_fProcessingDrawClipboard = TRUE;
 
283
          }
 
284
        else
 
285
          {
 
286
            winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
287
                           "Nested calls detected.  Bailing.\n");
 
288
            winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 
289
            return 0;
 
290
          }
 
291
 
 
292
        /* Pass the message on the next window in the clipboard viewer chain */
 
293
        if (s_hwndNextViewer)
 
294
          SendMessage (s_hwndNextViewer, message, 0, 0);
 
295
        
 
296
        /* Bail on first message */
 
297
        if (!s_fCBCInitialized)
 
298
          {
 
299
            s_fCBCInitialized = TRUE;
 
300
            s_fProcessingDrawClipboard = FALSE;
 
301
            winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 
302
            return 0;
 
303
          }
 
304
 
 
305
        /*
 
306
         * NOTE: We cannot bail out when NULL == GetClipboardOwner ()
 
307
         * because some applications deal with the clipboard in a manner
 
308
         * that causes the clipboard owner to be NULL when they are in
 
309
         * fact taking ownership.  One example of this is the Win32
 
310
         * native compile of emacs.
 
311
         */
 
312
        
 
313
        /* Bail when we still own the clipboard */
 
314
        if (hwnd == GetClipboardOwner ())
 
315
          {
 
316
 
 
317
            winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
318
                    "We own the clipboard, returning.\n");
 
319
            winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 
320
            s_fProcessingDrawClipboard = FALSE;
 
321
            return 0;
 
322
          }
 
323
 
 
324
        /*
 
325
         * Do not take ownership of the X11 selections when something
 
326
         * other than CF_TEXT or CF_UNICODETEXT has been copied
 
327
         * into the Win32 clipboard.
 
328
         */
 
329
        if (!IsClipboardFormatAvailable (CF_TEXT)
 
330
            && !IsClipboardFormatAvailable (CF_UNICODETEXT))
 
331
          {
 
332
 
 
333
            winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
334
                    "Clipboard does not contain CF_TEXT nor "
 
335
                    "CF_UNICODETEXT.\n");
 
336
 
 
337
            /*
 
338
             * We need to make sure that the X Server has processed
 
339
             * previous XSetSelectionOwner messages.
 
340
             */
 
341
            XSync (pDisplay, FALSE);
 
342
 
 
343
            winDebug("winClipboardWindowProc - XSync done.\n");
 
344
            
 
345
            /* Release PRIMARY selection if owned */
 
346
            iReturn = XGetSelectionOwner (pDisplay, XA_PRIMARY);
 
347
            if (iReturn == g_iClipboardWindow)
 
348
              {
 
349
                winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
350
                        "PRIMARY selection is owned by us.\n");
 
351
                XSetSelectionOwner (pDisplay,
 
352
                                    XA_PRIMARY,
 
353
                                    None,
 
354
                                    CurrentTime);
 
355
              }
 
356
            else if (BadWindow == iReturn || BadAtom == iReturn)
 
357
              winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
358
                      "XGetSelection failed for PRIMARY: %d\n", iReturn);
 
359
 
 
360
            /* Release CLIPBOARD selection if owned */
 
361
            iReturn = XGetSelectionOwner (pDisplay,
 
362
                                          XInternAtom (pDisplay,
 
363
                                                       "CLIPBOARD",
 
364
                                                       False));
 
365
            if (iReturn == g_iClipboardWindow)
 
366
              {
 
367
                winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
368
                        "CLIPBOARD selection is owned by us.\n");
 
369
                XSetSelectionOwner (pDisplay,
 
370
                                    XInternAtom (pDisplay,
 
371
                                                 "CLIPBOARD",
 
372
                                                 False),
 
373
                                    None,
 
374
                                    CurrentTime);
 
375
              }
 
376
            else if (BadWindow == iReturn || BadAtom == iReturn)
 
377
              winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
378
                      "XGetSelection failed for CLIPBOARD: %d\n", iReturn);
 
379
 
 
380
            winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 
381
            s_fProcessingDrawClipboard = FALSE;
 
382
            return 0;
 
383
          }
 
384
 
 
385
        /* Reassert ownership of PRIMARY */       
 
386
        iReturn = XSetSelectionOwner (pDisplay,
 
387
                                      XA_PRIMARY,
 
388
                                      iWindow,
 
389
                                      CurrentTime);
 
390
        if (iReturn == BadAtom || iReturn == BadWindow)
 
391
          {
 
392
            winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
393
                    "Could not reassert ownership of PRIMARY\n");
 
394
          }
 
395
        else
 
396
          {
 
397
            winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
398
                    "Reasserted ownership of PRIMARY\n");
 
399
          }
 
400
        
 
401
        /* Reassert ownership of the CLIPBOARD */         
 
402
        iReturn = XSetSelectionOwner (pDisplay,
 
403
                                      XInternAtom (pDisplay,
 
404
                                                   "CLIPBOARD",
 
405
                                                   False),
 
406
                                      iWindow,
 
407
                                      CurrentTime);
 
408
        if (iReturn == BadAtom || iReturn == BadWindow)
 
409
          {
 
410
            winErrorFVerb (1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
411
                    "Could not reassert ownership of CLIPBOARD\n");
 
412
          }
 
413
        else
 
414
          {
 
415
            winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
 
416
                    "Reasserted ownership of CLIPBOARD\n");
 
417
          }
 
418
        
 
419
        /* Flush the pending SetSelectionOwner event now */
 
420
        XFlush (pDisplay);
 
421
 
 
422
        s_fProcessingDrawClipboard = FALSE;
 
423
      }
 
424
      winDebug ("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
 
425
      return 0;
 
426
 
 
427
 
 
428
    case WM_DESTROYCLIPBOARD:
 
429
      /*
 
430
       * NOTE: Intentionally do nothing.
 
431
       * Changes in the Win32 clipboard are handled by WM_DRAWCLIPBOARD
 
432
       * above.  We only process this message to conform to the specs
 
433
       * for delayed clipboard rendering in Win32.  You might think
 
434
       * that we need to release ownership of the X11 selections, but
 
435
       * we do not, because a WM_DRAWCLIPBOARD message will closely
 
436
       * follow this message and reassert ownership of the X11
 
437
       * selections, handling the issue for us.
 
438
       */
 
439
      return 0;
 
440
 
 
441
 
 
442
    case WM_RENDERFORMAT:
 
443
    case WM_RENDERALLFORMATS:
 
444
      {
 
445
        int     iReturn;
 
446
        Display *pDisplay = g_pClipboardDisplay;
 
447
        Window  iWindow = g_iClipboardWindow;
 
448
        Bool    fConvertToUnicode;
 
449
 
 
450
        winDebug ("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
 
451
 
 
452
        /* Flag whether to convert to Unicode or not */
 
453
        if (message == WM_RENDERALLFORMATS)
 
454
          fConvertToUnicode = FALSE;
 
455
        else
 
456
          fConvertToUnicode = g_fUnicodeSupport && (CF_UNICODETEXT == wParam);
 
457
 
 
458
        /* Request the selection contents */
 
459
        iReturn = XConvertSelection (pDisplay,
 
460
                                     g_atomLastOwnedSelection,
 
461
                                     XInternAtom (pDisplay,
 
462
                                                  "COMPOUND_TEXT", False),
 
463
                                     XInternAtom (pDisplay,
 
464
                                                  "CYGX_CUT_BUFFER", False),
 
465
                                     iWindow,
 
466
                                     CurrentTime);
 
467
        if (iReturn == BadAtom || iReturn == BadWindow)
 
468
          {
 
469
            winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
 
470
                    "XConvertSelection () failed\n");
 
471
            break;
 
472
          }
 
473
 
 
474
        /* Special handling for WM_RENDERALLFORMATS */
 
475
        if (message == WM_RENDERALLFORMATS)
 
476
          {
 
477
            /* We must open and empty the clipboard */
 
478
 
 
479
            /* Close clipboard if we have it open already */
 
480
            if (GetOpenClipboardWindow () == hwnd)
 
481
              {
 
482
                CloseClipboard ();
 
483
              }     
 
484
 
 
485
            if (!OpenClipboard (hwnd))
 
486
              {
 
487
                winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
 
488
                        "OpenClipboard () failed: %08x\n",
 
489
                        GetLastError ());
 
490
                break;
 
491
              }
 
492
            
 
493
            if (!EmptyClipboard ())
 
494
              {
 
495
                winErrorFVerb (1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
 
496
                        "EmptyClipboard () failed: %08x\n",
 
497
                      GetLastError ());
 
498
                break;
 
499
              }
 
500
          }
 
501
 
 
502
        /* Process the SelectionNotify event */
 
503
        iReturn = winProcessXEventsTimeout (hwnd,
 
504
                                            iWindow,
 
505
                                            pDisplay,
 
506
                                            fConvertToUnicode,
 
507
                                            WIN_POLL_TIMEOUT);
 
508
        if (WIN_XEVENTS_CONVERT == iReturn)
 
509
          {
 
510
            /*
 
511
             * The selection was offered for conversion first, so we have
 
512
             * to process a second SelectionNotify event to get the actual
 
513
             * data in the selection.
 
514
             */
 
515
            iReturn = winProcessXEventsTimeout (hwnd,
 
516
                                                iWindow,
 
517
                                                pDisplay,
 
518
                                                fConvertToUnicode,
 
519
                                                WIN_POLL_TIMEOUT);
 
520
          }
 
521
        
 
522
        /*
 
523
         * The last of the up-to two calls to winProcessXEventsTimeout
 
524
         * from above had better have seen a notify event, or else we
 
525
         * are dealing with a buggy or old X11 app.  In these cases we
 
526
         * have to paste some fake data to the Win32 clipboard to
 
527
         * satisfy the requirement that we write something to it.
 
528
         */
 
529
        if (WIN_XEVENTS_NOTIFY != iReturn)
 
530
          {
 
531
            /* Paste no data, to satisfy required call to SetClipboardData */
 
532
            if (g_fUnicodeSupport)
 
533
              SetClipboardData (CF_UNICODETEXT, NULL);
 
534
            SetClipboardData (CF_TEXT, NULL);
 
535
          }
 
536
 
 
537
        /* Special handling for WM_RENDERALLFORMATS */
 
538
        if (message == WM_RENDERALLFORMATS)
 
539
          {
 
540
            /* We must close the clipboard */
 
541
            
 
542
            if (!CloseClipboard ())
 
543
              {
 
544
              winErrorFVerb (1, "winClipboardWindowProc - WM_RENDERALLFORMATS - "
 
545
                      "CloseClipboard () failed: %08x\n",
 
546
                      GetLastError ());
 
547
              break;
 
548
              }
 
549
          }
 
550
 
 
551
        winDebug ("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
 
552
        return 0;
 
553
      }
 
554
    }
 
555
 
 
556
  /* Let Windows perform default processing for unhandled messages */
 
557
  return DefWindowProc (hwnd, message, wParam, lParam);
 
558
}
 
559
 
 
560
 
 
561
/*
 
562
 * Process any pending Windows messages
 
563
 */
 
564
 
 
565
BOOL
 
566
winClipboardFlushWindowsMessageQueue (HWND hwnd)
 
567
{
 
568
  MSG                   msg;
 
569
 
 
570
  /* Flush the messaging window queue */
 
571
  /* NOTE: Do not pass the hwnd of our messaging window to PeekMessage,
 
572
   * as this will filter out many non-window-specific messages that
 
573
   * are sent to our thread, such as WM_QUIT.
 
574
   */
 
575
  while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
 
576
    {
 
577
      /* Dispatch the message if not WM_QUIT */
 
578
      if (msg.message == WM_QUIT)
 
579
        return FALSE;
 
580
      else
 
581
        DispatchMessage (&msg);
 
582
    }
 
583
  
 
584
  return TRUE;
 
585
}