libs-back/Tools/win32pbs.m
Nicola Pero de05f167ad Fixed compilation with new mingw/msys packages
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@24716 72102866-910b-0410-8b05-ffd578937521
2007-02-28 06:48:08 +00:00

359 lines
7.5 KiB
Objective-C
Executable file

/*
win32pbs.m
GNUstep pasteboard server - Win32 extension
Copyright (C) 2003 Free Software Foundation, Inc.
Author: Fred Kiefer <fredkiefer@gmx.de>
Date: December 2003
This file is part of the GNUstep Project
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
You should have received a copy of the GNU General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Access Windows 2000 (and later) API. Required for HWND_MESSAGE. */
#define WINVER 0x500
#include <Foundation/Foundation.h>
#include <Foundation/NSUserDefaults.h>
#include <AppKit/NSPasteboard.h>
#include <windows.h>
@interface Win32PbOwner : NSObject
{
NSPasteboard *_pb;
HINSTANCE _hinstance;
HWND _hwnd;
BOOL _ignore;
}
- (id) initWithOSPb: (NSPasteboard*) ospb;
- (void) clipboardHasData;
- (void) setClipboardData;
- (void) grapClipboard;
- (void) setupRunLoopInputSourcesForMode: (NSString*)mode;
@end
static Win32PbOwner *wpb = nil;
static HWND hwndNextViewer = NULL;
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam);
@implementation Win32PbOwner
+ (BOOL) initializePasteboard
{
if (self == [Win32PbOwner class])
{
wpb = [[Win32PbOwner alloc] initWithOSPb:
[NSPasteboard generalPasteboard]];
[wpb clipboardHasData];
}
return YES;
}
+ (id) ownerByOsPb: (NSString*)p
{
if ([p isEqual: [NSPasteboard generalPasteboard]])
{
return wpb;
}
else
{
return nil;
}
}
- (id) initWithOSPb: (NSPasteboard*) ospb
{
WNDCLASSEX wc;
_ignore = NO;
_hinstance = (HINSTANCE)GetModuleHandle(NULL);
// Register the main window class.
wc.cbSize = sizeof(wc);
//wc.style = CS_OWNDC;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = _hinstance;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "GNUstepClipboardClass";
wc.hIconSm = NULL;
if (RegisterClassEx(&wc))
{
_hwnd = CreateWindowEx(0, "GNUstepClipboardClass", "GNUstepClipboard",
0, 0, 0, 10, 10,
HWND_MESSAGE, (HMENU)NULL, _hinstance, NULL);
}
ASSIGN(_pb, ospb);
[self setupRunLoopInputSourcesForMode: NSDefaultRunLoopMode];
return self;
}
- (void) dealloc
{
RELEASE(_pb);
DestroyWindow(_hwnd);
UnregisterClass("GNUstepClipboardClass", _hinstance);
[super dealloc];
}
- (void) clipboardHasString
{
if ((_hwnd != GetClipboardOwner()) &&
IsClipboardFormatAvailable(CF_UNICODETEXT))
{
[_pb declareTypes: [NSArray arrayWithObject: NSStringPboardType]
owner: self];
}
}
/*
The owner of the Windows clipboard did change. Check if this
results in some action for us.
*/
- (void) clipboardHasData
{
if (!_ignore)
{
_ignore = YES;
[self clipboardHasString];
_ignore = NO;
}
}
- (void) setClipboardString
{
HGLOBAL hglb;
LPWSTR lpwstr;
NSString *s;
unsigned int len;
s = [_pb stringForType: NSStringPboardType];
if (s == nil)
{
return;
}
len = [s length];
hglb = GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(WCHAR));
if (hglb == NULL)
{
return;
}
// Lock the handle and copy the text to the buffer.
lpwstr = GlobalLock(hglb);
[s getCharacters: lpwstr];
lpwstr[len] = (WCHAR)0;
GlobalUnlock(hglb);
SetClipboardData(CF_UNICODETEXT, hglb);
}
/*
Data is requested from the Windows clipboard. We are already the
owner of the clipboard.
*/
- (void) setClipboardData
{
if (!_ignore)
{
_ignore = YES;
[self setClipboardString];
_ignore = NO;;
}
}
/*
Take over the ownership of the Windows clipboard, but don't provide data
*/
- (void) grapClipboard
{
if (!OpenClipboard(_hwnd))
{
NSLog(@"Failed to get the Win32 clipboard. %d", GetLastError());
return;
}
if (!EmptyClipboard())
{
NSLog(@"Failed to get the Win32 clipboard. %d", GetLastError());
CloseClipboard();
return;
}
SetClipboardData(CF_UNICODETEXT, NULL);
CloseClipboard();
}
/*
* If this gets called, a GNUstep object has grabbed the pasteboard
* or has changed the types of data available from the pasteboard
* so we must tell the Windows system, that we have the current selection.
*/
- (void) pasteboardChangedOwner: (NSPasteboard*)sender
{
if (!_ignore)
{
_ignore = YES;
[self grapClipboard];
_ignore = NO;;
}
}
- (void) provideStringTo: (NSPasteboard*)pb
{
HGLOBAL hglb;
if (!IsClipboardFormatAvailable(CF_UNICODETEXT) ||
!OpenClipboard(_hwnd))
{
return;
}
hglb = GetClipboardData(CF_UNICODETEXT);
if (hglb != NULL)
{
LPWSTR lpwstr;
lpwstr = GlobalLock(hglb);
if (lpwstr != NULL)
{
unsigned int len;
NSString *s;
len = lstrlenW(lpwstr);
s = [NSString stringWithCharacters: lpwstr
length: len];
[pb setString: s forType: NSStringPboardType];
GlobalUnlock(hglb);
}
}
CloseClipboard();
}
- (void) pasteboard: (NSPasteboard*)pb provideDataForType: (NSString*)type
{
if (!_ignore)
{
if ([type isEqual: NSStringPboardType])
{
_ignore = YES;
[self provideStringTo: pb];
_ignore = NO;;
}
}
}
- (void) callback: (id) sender
{
MSG msg;
WINBOOL bRet;
while ((bRet = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) != 0)
{
if (msg.message == WM_QUIT)
{
// Exit the program
return;
}
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
// Don't translate messages, as this would give extra character messages.
DispatchMessage(&msg);
}
}
}
- (void) setupRunLoopInputSourcesForMode: (NSString*)mode
{
// FIXME
NSTimer *timer;
timer = [NSTimer timerWithTimeInterval: 0.1
target: self
selector: @selector(callback:)
userInfo: nil
repeats: YES];
[[NSRunLoop currentRunLoop] addTimer: timer forMode: mode];
}
@end
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
// Add the window to the clipboard viewer chain.
hwndNextViewer = SetClipboardViewer(hwnd);
break;
case WM_CHANGECBCHAIN:
// If the next window is closing, repair the chain.
if ((HWND) wParam == hwndNextViewer)
hwndNextViewer = (HWND) lParam;
// Otherwise, pass the message to the next link.
else if (hwndNextViewer != NULL)
SendMessage(hwndNextViewer, uMsg, wParam, lParam);
break;
case WM_DESTROY:
ChangeClipboardChain(hwnd, hwndNextViewer);
PostQuitMessage(0);
break;
case WM_DRAWCLIPBOARD:
// clipboard contents changed.
if (wpb != nil)
[wpb clipboardHasData];
// Pass the message to the next window in clipboard
// viewer chain.
if (hwndNextViewer != NULL)
SendMessage(hwndNextViewer, uMsg, wParam, lParam);
break;
case WM_RENDERFORMAT:
[wpb setClipboardData];
break;
case WM_RENDERALLFORMATS:
[wpb setClipboardData];
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return (LRESULT) NULL;
}