comparison win/dw.c @ 969:69f620df0c47

Step 1 in modernization of the Win32 module. Eliminate Windows NT based Windows checks, since that is all we support now. Eliminate thread limits by eliminating thread arrays and switching to using Thread Local Storage (TLS). Simplify dw_clipboard_get_text() by returning a malloc()ed buffer which now must need to be dw_free()ed. This makes this function the same as it does on OS/2 and Mac currently.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 05 May 2011 05:53:56 +0000
parents 0345e37d6c86
children b00943f21392
comparison
equal deleted inserted replaced
968:0345e37d6c86 969:69f620df0c47
59 HIMAGELIST hSmall = 0, hLarge = 0; 59 HIMAGELIST hSmall = 0, hLarge = 0;
60 60
61 /* Special flag used for internal tracking */ 61 /* Special flag used for internal tracking */
62 #define DW_CFA_RESERVED (1 << 30) 62 #define DW_CFA_RESERVED (1 << 30)
63 63
64 #define THREAD_LIMIT 128 64 DWORD _foreground;
65 COLORREF _foreground[THREAD_LIMIT]; 65 DWORD _background;
66 COLORREF _background[THREAD_LIMIT]; 66 DWORD _hPen;
67 HPEN _hPen[THREAD_LIMIT]; 67 DWORD _hBrush;
68 HBRUSH _hBrush[THREAD_LIMIT];
69 char *_clipboard_contents[THREAD_LIMIT];
70 68
71 BYTE _red[] = { 0x00, 0xbb, 0x00, 0xaa, 0x00, 0xbb, 0x00, 0xaa, 0x77, 69 BYTE _red[] = { 0x00, 0xbb, 0x00, 0xaa, 0x00, 0xbb, 0x00, 0xaa, 0x77,
72 0xff, 0x00, 0xee, 0x00, 0xff, 0x00, 0xff, 0xaa, 0x00 }; 70 0xff, 0x00, 0xee, 0x00, 0xff, 0x00, 0xff, 0xaa, 0x00 };
73 BYTE _green[] = { 0x00, 0x00, 0xbb, 0xaa, 0x00, 0x00, 0xbb, 0xaa, 0x77, 71 BYTE _green[] = { 0x00, 0x00, 0xbb, 0xaa, 0x00, 0x00, 0xbb, 0xaa, 0x77,
74 0x00, 0xff, 0xee, 0x00, 0x00, 0xee, 0xff, 0xaa, 0x00 }; 72 0x00, 0xff, 0xee, 0x00, 0x00, 0xee, 0xff, 0xaa, 0x00 };
245 argv = _convertargs(&argc, lpCmdLine); 243 argv = _convertargs(&argc, lpCmdLine);
246 244
247 return main(argc, argv); 245 return main(argc, argv);
248 } 246 }
249 #endif 247 #endif
250
251 /* This should return true for WinNT/2K/XP and false on Win9x */
252 int IsWinNT(void)
253 {
254 static int isnt = -1;
255
256 if(isnt == -1)
257 {
258 if (GetVersion() < 0x80000000)
259 isnt = 1;
260 else
261 isnt = 0;
262 }
263 return isnt;
264 }
265 248
266 void DrawTransparentBitmap(HDC hdc, HDC hdcSrc, HBITMAP hBitmap, int xStart, int yStart, COLORREF cTransparentColor) 249 void DrawTransparentBitmap(HDC hdc, HDC hdcSrc, HBITMAP hBitmap, int xStart, int yStart, COLORREF cTransparentColor)
267 { 250 {
268 BITMAP bm; 251 BITMAP bm;
269 COLORREF cColor; 252 COLORREF cColor;
2853 /* Tell the spinner control that a keypress has 2836 /* Tell the spinner control that a keypress has
2854 * occured and to update it's internal value. 2837 * occured and to update it's internal value.
2855 */ 2838 */
2856 if (cinfo->buddy && !cinfo->combo) 2839 if (cinfo->buddy && !cinfo->combo)
2857 { 2840 {
2858 if (IsWinNT()) 2841 PostMessage(cinfo->buddy, WM_USER+10, 0, 0);
2859 PostMessage(cinfo->buddy, WM_USER+10, 0, 0);
2860 else
2861 SendMessage(cinfo->buddy, WM_USER+10, 0, 0);
2862 } 2842 }
2863 break; 2843 break;
2864 case WM_USER+10: 2844 case WM_USER+10:
2865 { 2845 {
2866 if(cinfo->buddy) 2846 if(cinfo->buddy)
3639 free(file); 3619 free(file);
3640 } 3620 }
3641 return windowtype; 3621 return windowtype;
3642 } 3622 }
3643 3623
3624 /* Initialize thread local values to the defaults */
3625 void _init_thread(void)
3626 {
3627 COLORREF foreground = RGB(128,128,128);
3628 COLORREF background = DW_RGB_TRANSPARENT;
3629 TlsSetValue(_foreground, (LPVOID)foreground);
3630 TlsSetValue(_background, (LPVOID)background);
3631 TlsSetValue(_hPen, CreatePen(PS_SOLID, 1, foreground));
3632 TlsSetValue(_hBrush, CreateSolidBrush(foreground));
3633 }
3634
3644 /* 3635 /*
3645 * Initializes the Dynamic Windows engine. 3636 * Initializes the Dynamic Windows engine.
3646 * Parameters: 3637 * Parameters:
3647 * newthread: True if this is the only thread. 3638 * newthread: True if this is the only thread.
3648 * False if there is already a message loop running. 3639 * False if there is already a message loop running.
3652 WNDCLASS wc; 3643 WNDCLASS wc;
3653 int z; 3644 int z;
3654 INITCOMMONCONTROLSEX icc; 3645 INITCOMMONCONTROLSEX icc;
3655 char *fname; 3646 char *fname;
3656 HFONT oldfont; 3647 HFONT oldfont;
3648
3649 /* Initialize our thread local storage */
3650 _foreground = TlsAlloc();
3651 _background = TlsAlloc();
3652 _hPen = TlsAlloc();
3653 _hBrush = TlsAlloc();
3654 _init_thread();
3657 3655
3658 icc.dwSize = sizeof(INITCOMMONCONTROLSEX); 3656 icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
3659 icc.dwICC = ICC_WIN95_CLASSES|ICC_DATE_CLASSES; 3657 icc.dwICC = ICC_WIN95_CLASSES|ICC_DATE_CLASSES;
3660 3658
3661 InitCommonControlsEx(&icc); 3659 InitCommonControlsEx(&icc);
3755 } 3753 }
3756 3754
3757 /* We need the version to check capability like up-down controls */ 3755 /* We need the version to check capability like up-down controls */
3758 dwVersion = GetVersion(); 3756 dwVersion = GetVersion();
3759 dwComctlVer = GetDllVersion(TEXT("comctl32.dll")); 3757 dwComctlVer = GetDllVersion(TEXT("comctl32.dll"));
3760
3761 for ( z = 0; z < THREAD_LIMIT; z++ )
3762 {
3763 _foreground[z] = RGB(128,128,128);
3764 _background[z] = DW_RGB_TRANSPARENT;
3765 _hPen[z] = CreatePen(PS_SOLID, 1, _foreground[z]);
3766 _hBrush[z] = CreateSolidBrush(_foreground[z]);
3767 _clipboard_contents[z] = NULL;
3768 }
3769 3758
3770 /* Initialize Security for named events and memory */ 3759 /* Initialize Security for named events and memory */
3771 InitializeSecurityDescriptor(&_dwsd, SECURITY_DESCRIPTOR_REVISION); 3760 InitializeSecurityDescriptor(&_dwsd, SECURITY_DESCRIPTOR_REVISION);
3772 SetSecurityDescriptorDacl(&_dwsd, TRUE, (PACL) NULL, FALSE); 3761 SetSecurityDescriptorDacl(&_dwsd, TRUE, (PACL) NULL, FALSE);
3773 3762
8386 * green: green value. 8375 * green: green value.
8387 * blue: blue value. 8376 * blue: blue value.
8388 */ 8377 */
8389 void API dw_color_foreground_set(unsigned long value) 8378 void API dw_color_foreground_set(unsigned long value)
8390 { 8379 {
8391 int threadid = dw_thread_id(); 8380 HPEN hPen = TlsGetValue(_hPen);
8392 8381 HBRUSH hBrush = TlsGetValue(_hBrush);
8393 if(threadid < 0 || threadid >= THREAD_LIMIT) 8382 COLORREF foreground;
8394 threadid = 0;
8395 8383
8396 value = _internal_color(value); 8384 value = _internal_color(value);
8397 8385 foreground = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value));
8398 DeleteObject(_hPen[threadid]); 8386
8399 DeleteObject(_hBrush[threadid]); 8387 DeleteObject(hPen);
8400 _foreground[threadid] = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value)); 8388 DeleteObject(hBrush);
8401 _hPen[threadid] = CreatePen(PS_SOLID, 1, _foreground[threadid]); 8389 TlsSetValue(_foreground, (LPVOID)foreground);
8402 _hBrush[threadid] = CreateSolidBrush(_foreground[threadid]); 8390 TlsSetValue(_hPen, CreatePen(PS_SOLID, 1, foreground));
8391 TlsSetValue(_hBrush, CreateSolidBrush(foreground));
8403 } 8392 }
8404 8393
8405 /* Sets the current background drawing color. 8394 /* Sets the current background drawing color.
8406 * Parameters: 8395 * Parameters:
8407 * red: red value. 8396 * red: red value.
8408 * green: green value. 8397 * green: green value.
8409 * blue: blue value. 8398 * blue: blue value.
8410 */ 8399 */
8411 void API dw_color_background_set(unsigned long value) 8400 void API dw_color_background_set(unsigned long value)
8412 { 8401 {
8413 int threadid = dw_thread_id(); 8402 COLORREF background;
8414
8415 if(threadid < 0 || threadid >= THREAD_LIMIT)
8416 threadid = 0;
8417 8403
8418 value = _internal_color(value); 8404 value = _internal_color(value);
8405 background = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value));
8419 8406
8420 if(value == DW_RGB_TRANSPARENT) 8407 if(value == DW_RGB_TRANSPARENT)
8421 _background[threadid] = DW_RGB_TRANSPARENT; 8408 TlsSetValue(_background, (LPVOID)DW_RGB_TRANSPARENT);
8422 else 8409 else
8423 _background[threadid] = RGB(DW_RED_VALUE(value), DW_GREEN_VALUE(value), DW_BLUE_VALUE(value)); 8410 TlsSetValue(_background, (LPVOID)background);
8424 } 8411 }
8425 8412
8426 /* Allows the user to choose a color using the system's color chooser dialog. 8413 /* Allows the user to choose a color using the system's color chooser dialog.
8427 * Parameters: 8414 * Parameters:
8428 * value: current color 8415 * value: current color
8459 * y: Y coordinate. 8446 * y: Y coordinate.
8460 */ 8447 */
8461 void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y) 8448 void API dw_draw_point(HWND handle, HPIXMAP pixmap, int x, int y)
8462 { 8449 {
8463 HDC hdcPaint; 8450 HDC hdcPaint;
8464 int threadid = dw_thread_id();
8465
8466 if(threadid < 0 || threadid >= THREAD_LIMIT)
8467 threadid = 0;
8468 8451
8469 if(handle) 8452 if(handle)
8470 hdcPaint = GetDC(handle); 8453 hdcPaint = GetDC(handle);
8471 else if(pixmap) 8454 else if(pixmap)
8472 hdcPaint = pixmap->hdc; 8455 hdcPaint = pixmap->hdc;
8473 else 8456 else
8474 return; 8457 return;
8475 8458
8476 SetPixel(hdcPaint, x, y, _foreground[threadid]); 8459 SetPixel(hdcPaint, x, y, (COLORREF)TlsGetValue(_foreground));
8477 if(!pixmap) 8460 if(!pixmap)
8478 ReleaseDC(handle, hdcPaint); 8461 ReleaseDC(handle, hdcPaint);
8479 } 8462 }
8480 8463
8481 /* Draw a line on a window (preferably a render window). 8464 /* Draw a line on a window (preferably a render window).
8489 */ 8472 */
8490 void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2) 8473 void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2)
8491 { 8474 {
8492 HDC hdcPaint; 8475 HDC hdcPaint;
8493 HPEN oldPen; 8476 HPEN oldPen;
8494 int threadid = dw_thread_id();
8495
8496 if(threadid < 0 || threadid >= THREAD_LIMIT)
8497 threadid = 0;
8498 8477
8499 if(handle) 8478 if(handle)
8500 hdcPaint = GetDC(handle); 8479 hdcPaint = GetDC(handle);
8501 else if(pixmap) 8480 else if(pixmap)
8502 hdcPaint = pixmap->hdc; 8481 hdcPaint = pixmap->hdc;
8503 else 8482 else
8504 return; 8483 return;
8505 8484
8506 oldPen = SelectObject(hdcPaint, _hPen[threadid]); 8485 oldPen = SelectObject(hdcPaint, TlsGetValue(_hPen));
8507 MoveToEx(hdcPaint, x1, y1, NULL); 8486 MoveToEx(hdcPaint, x1, y1, NULL);
8508 LineTo(hdcPaint, x2, y2); 8487 LineTo(hdcPaint, x2, y2);
8509 SelectObject(hdcPaint, oldPen); 8488 SelectObject(hdcPaint, oldPen);
8510 /* For some reason Win98 (at least) fails 8489 /* For some reason Win98 (at least) fails
8511 * to draw the last pixel. So I do it myself. 8490 * to draw the last pixel. So I do it myself.
8512 */ 8491 */
8513 SetPixel(hdcPaint, x2, y2, _foreground[threadid]); 8492 SetPixel(hdcPaint, x2, y2, (COLORREF)TlsGetValue(_foreground));
8514 if(!pixmap) 8493 if(!pixmap)
8515 ReleaseDC(handle, hdcPaint); 8494 ReleaseDC(handle, hdcPaint);
8516 } 8495 }
8517 8496
8518 /* Draw a closed polygon on a window (preferably a render window). 8497 /* Draw a closed polygon on a window (preferably a render window).
8529 HDC hdcPaint; 8508 HDC hdcPaint;
8530 HBRUSH oldBrush; 8509 HBRUSH oldBrush;
8531 HPEN oldPen; 8510 HPEN oldPen;
8532 POINT *points; 8511 POINT *points;
8533 int i; 8512 int i;
8534 int threadid = dw_thread_id();
8535
8536 if(threadid < 0 || threadid >= THREAD_LIMIT)
8537 threadid = 0;
8538 8513
8539 if ( handle ) 8514 if ( handle )
8540 hdcPaint = GetDC( handle ); 8515 hdcPaint = GetDC( handle );
8541 else if ( pixmap ) 8516 else if ( pixmap )
8542 hdcPaint = pixmap->hdc; 8517 hdcPaint = pixmap->hdc;
8567 /* ... and increment the number of points */ 8542 /* ... and increment the number of points */
8568 npoints++; 8543 npoints++;
8569 } 8544 }
8570 } 8545 }
8571 8546
8572 oldBrush = SelectObject( hdcPaint, _hBrush[threadid] ); 8547 oldBrush = SelectObject( hdcPaint, TlsGetValue(_hBrush) );
8573 oldPen = SelectObject( hdcPaint, _hPen[threadid] ); 8548 oldPen = SelectObject( hdcPaint, TlsGetValue(_hPen) );
8574 if ( fill ) 8549 if ( fill )
8575 Polygon( hdcPaint, points, npoints ); 8550 Polygon( hdcPaint, points, npoints );
8576 else 8551 else
8577 Polyline( hdcPaint, points, npoints ); 8552 Polyline( hdcPaint, points, npoints );
8578 SelectObject( hdcPaint, oldBrush ); 8553 SelectObject( hdcPaint, oldBrush );
8593 */ 8568 */
8594 void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height) 8569 void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height)
8595 { 8570 {
8596 HDC hdcPaint; 8571 HDC hdcPaint;
8597 RECT Rect; 8572 RECT Rect;
8598 int threadid = dw_thread_id();
8599
8600 if(threadid < 0 || threadid >= THREAD_LIMIT)
8601 threadid = 0;
8602 8573
8603 if(handle) 8574 if(handle)
8604 hdcPaint = GetDC(handle); 8575 hdcPaint = GetDC(handle);
8605 else if(pixmap) 8576 else if(pixmap)
8606 hdcPaint = pixmap->hdc; 8577 hdcPaint = pixmap->hdc;
8607 else 8578 else
8608 return; 8579 return;
8609 8580
8610 SetRect(&Rect, x, y, x + width , y + height ); 8581 SetRect(&Rect, x, y, x + width , y + height );
8611 if(fill) 8582 if(fill)
8612 FillRect(hdcPaint, &Rect, _hBrush[threadid]); 8583 FillRect(hdcPaint, &Rect, TlsGetValue(_hBrush));
8613 else 8584 else
8614 FrameRect(hdcPaint, &Rect, _hBrush[threadid]); 8585 FrameRect(hdcPaint, &Rect, TlsGetValue(_hBrush));
8615 if(!pixmap) 8586 if(!pixmap)
8616 ReleaseDC(handle, hdcPaint); 8587 ReleaseDC(handle, hdcPaint);
8617 } 8588 }
8618 8589
8619 /* Draw text on a window (preferably a render window). 8590 /* Draw text on a window (preferably a render window).
8627 void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text) 8598 void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text)
8628 { 8599 {
8629 HDC hdc; 8600 HDC hdc;
8630 int mustdelete = 0; 8601 int mustdelete = 0;
8631 HFONT hFont = 0, oldFont = 0; 8602 HFONT hFont = 0, oldFont = 0;
8632 int threadid = dw_thread_id();
8633 ColorInfo *cinfo; 8603 ColorInfo *cinfo;
8634 8604 COLORREF background;
8635 if(threadid < 0 || threadid >= THREAD_LIMIT)
8636 threadid = 0;
8637 8605
8638 if(handle) 8606 if(handle)
8639 hdc = GetDC(handle); 8607 hdc = GetDC(handle);
8640 else if(pixmap) 8608 else if(pixmap)
8641 hdc = pixmap->hdc; 8609 hdc = pixmap->hdc;
8651 { 8619 {
8652 hFont = _acquire_font(handle, cinfo->fontname); 8620 hFont = _acquire_font(handle, cinfo->fontname);
8653 mustdelete = 1; 8621 mustdelete = 1;
8654 } 8622 }
8655 8623
8624 background = (COLORREF)TlsGetValue(_background);
8656 if(hFont) 8625 if(hFont)
8657 oldFont = SelectObject(hdc, hFont); 8626 oldFont = SelectObject(hdc, hFont);
8658 SetTextColor(hdc, _foreground[threadid]); 8627 SetTextColor(hdc, (COLORREF)TlsGetValue(_foreground));
8659 if(_background[threadid] == DW_RGB_TRANSPARENT) 8628 if(background == DW_RGB_TRANSPARENT)
8660 SetBkMode(hdc, TRANSPARENT); 8629 SetBkMode(hdc, TRANSPARENT);
8661 else 8630 else
8662 { 8631 {
8663 SetBkMode(hdc, OPAQUE); 8632 SetBkMode(hdc, OPAQUE);
8664 SetBkColor(hdc, _background[threadid]); 8633 SetBkColor(hdc, background);
8665 } 8634 }
8666 TextOut(hdc, x, y, text, strlen(text)); 8635 TextOut(hdc, x, y, text, strlen(text));
8667 if(oldFont) 8636 if(oldFont)
8668 SelectObject(hdc, oldFont); 8637 SelectObject(hdc, oldFont);
8669 if(mustdelete) 8638 if(mustdelete)
9432 CloseHandle(handle); 9401 CloseHandle(handle);
9433 return 0; 9402 return 0;
9434 } 9403 }
9435 9404
9436 /* 9405 /*
9406 * Encapsulate thread creation on Win32.
9407 */
9408 void _dwthreadstart(void *data)
9409 {
9410 void (* threadfunc)(void *) = NULL;
9411 void **tmp = (void **)data;
9412
9413 _init_thread();
9414
9415 threadfunc = (void (*)(void *))tmp[0];
9416 threadfunc(tmp[1]);
9417
9418 free(tmp);
9419 }
9420
9421 /*
9437 * Creates a new thread with a starting point of func. 9422 * Creates a new thread with a starting point of func.
9438 * Parameters: 9423 * Parameters:
9439 * func: Function which will be run in the new thread. 9424 * func: Function which will be run in the new thread.
9440 * data: Parameter(s) passed to the function. 9425 * data: Parameter(s) passed to the function.
9441 * stack: Stack size of new thread (OS/2 and Windows only). 9426 * stack: Stack size of new thread (OS/2 and Windows only).
9443 DWTID API dw_thread_new(void *func, void *data, int stack) 9428 DWTID API dw_thread_new(void *func, void *data, int stack)
9444 { 9429 {
9445 #if defined(__CYGWIN__) 9430 #if defined(__CYGWIN__)
9446 return 0; 9431 return 0;
9447 #else 9432 #else
9448 return (DWTID)_beginthread((void(*)(void *))func, stack, data); 9433 void **tmp = malloc(sizeof(void *) * 2);
9434
9435 tmp[0] = func;
9436 tmp[1] = data;
9437
9438 return (DWTID)_beginthread((void(*)(void *))_dwthreadstart, stack, tmp);
9449 #endif 9439 #endif
9450 } 9440 }
9451 9441
9452 /* 9442 /*
9453 * Ends execution of current thread immediately. 9443 * Ends execution of current thread immediately.
9801 * be converted to text. 9791 * be converted to text.
9802 */ 9792 */
9803 char *dw_clipboard_get_text() 9793 char *dw_clipboard_get_text()
9804 { 9794 {
9805 HANDLE handle; 9795 HANDLE handle;
9806 int threadid = dw_thread_id(); 9796 char *tmp, *ret = NULL;
9807 long len;
9808 9797
9809 if ( !OpenClipboard( NULL ) ) 9798 if ( !OpenClipboard( NULL ) )
9810 return NULL; 9799 return ret;
9811 9800
9812 if ( ( handle = GetClipboardData( CF_TEXT) ) == NULL ) 9801 if ( ( handle = GetClipboardData( CF_TEXT) ) == NULL )
9813 { 9802 {
9814 CloseClipboard(); 9803 CloseClipboard();
9815 return NULL; 9804 return ret;
9816 } 9805 }
9817 9806
9818 len = strlen( (char *)handle ); 9807 if ( (tmp = GlobalLock(handle)) && strlen(tmp) )
9819 9808 {
9820 if ( threadid < 0 || threadid >= THREAD_LIMIT ) 9809 ret = strdup(tmp);
9821 threadid = 0; 9810 GlobalUnlock(handle);
9822 9811 }
9823 if ( _clipboard_contents[threadid] != NULL )
9824 {
9825 GlobalFree( _clipboard_contents[threadid] );
9826 }
9827 _clipboard_contents[threadid] = (char *)GlobalAlloc(GMEM_FIXED, len + 1);
9828 if ( !_clipboard_contents[threadid] )
9829 {
9830 CloseClipboard();
9831 return NULL;
9832 }
9833
9834 strcpy( (char *)_clipboard_contents[threadid], (char *)handle );
9835 CloseClipboard(); 9812 CloseClipboard();
9836 9813 return ret;
9837 return _clipboard_contents[threadid];
9838 } 9814 }
9839 9815
9840 /* 9816 /*
9841 * Sets the contents of the default clipboard to the supplied text. 9817 * Sets the contents of the default clipboard to the supplied text.
9842 * Parameters: 9818 * Parameters:
9859 9835
9860 memcpy( (char *)ptr2, str, len + 1); 9836 memcpy( (char *)ptr2, str, len + 1);
9861 GlobalUnlock( ptr1 ); 9837 GlobalUnlock( ptr1 );
9862 EmptyClipboard(); 9838 EmptyClipboard();
9863 9839
9864 if ( !SetClipboardData( CF_TEXT, ptr1 ) ) 9840 SetClipboardData( CF_TEXT, ptr1 );
9865 {
9866 GlobalFree( ptr1 );
9867 return;
9868 }
9869 9841
9870 CloseClipboard(); 9842 CloseClipboard();
9871 GlobalFree( ptr1 ); 9843 GlobalFree( ptr1 );
9872 9844
9873 return; 9845 return;