newlib/winsup/cygwin/fhandler_clipboard.cc
Christopher Faylor ec98d19a08 * wininfo.h (wininfo::timer_active): Delete.
(wininfo::itv): Ditto.
(wininfo::start_time): Ditto.
(wininfo::window_started): Ditto.
(wininfo::getitimer): Ditto.
(wininfo::setitimer): Ditto.
(wininfo::wininfo): Ditto.
(wininfo::lock): New method.
(wininfo::release): Ditto.
* window.cc: Use new lock/acquire wininfo methods throughout.
(wininfo::wininfo): Delete
(wininfo::getitimer): Ditto.
(wininfo::setitimer): Ditto.
(getitimer): Ditto.
(setitimer): Ditto.
(ualarm): Ditto.
(alarm): Ditto.
(wininfo::lock): Define new function.
(wininfo::release): Ditto.
(wininfo::process): Delete WM_TIMER handling.
* timer.cc (struct timetracker): Delete it, flags.  Add it_interval,
interval_us, sleepto_us, running, init_muto(), syncthread, and gettime().
(ttstart): Make NO_COPY.
(lock_timer_tracker): New class.
(timer_tracker::timer_tracker): Distinguish ttstart case.
(timer_tracker::~timer_tracker): New destructor.  Clean out events, and reset
magic.
(timer_tracker::init_muto): New method.
(to_us): Round up as per POSIX.
(timer_thread): Reorganize to match timer_tracker::settime and
timer_tracker::gettime.  Call sig_send without wait.  Call auto_release.
(timer_tracker::settime): Reorganize logic to avoid race.  Call gettime to
recover old value.
(timer_tracker::gettime): New method.
(timer_create): Properly set errno on invalid timerid.  Use new
lock_timer_tracker method.
(timer_delete): Ditto.  Simplify code slightly.
(timer_gettime): New function.
(fixup_timers_after_fork): Reinit ttstart.
(getitimer): New implementation.
(setitimer): Ditto.
(ualarm): Ditto.
(alarm): Ditto.
* cygwin.din: Export timer_gettime.
* winsup.h: Remove has has_visible_window_station declaration.
* Makefile.in (DLL_OFILES): Add lsearch.o.
* cygthread.h (cygthread::notify_detached): New element.
(cygthread::cygthread): Take optional fourth argument signifying event to
signal on thread completion.
* cygthread.cc (cygthread::stub): Signal notify_detached event, if it exists.
(cygthread::cygthread): Initialize notify_detached from fourth argument.
(cygthread::detach): Wait for notify_detached field is present.
* lsearch.cc: New file.
* search.h: Ditto.
* include/cygwin/version.h: Bump API minor number to 126.
* cygwin.din: Export lsearch, lfind.
2005-03-27 01:57:38 +00:00

275 lines
6.4 KiB
C++

/* fhandler_dev_clipboard: code to access /dev/clipboard
Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc
Written by Charles Wilson (cwilson@ece.gatech.edu)
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <windows.h>
#include <wingdi.h>
#include <winuser.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
#include "fhandler.h"
/*
* Robert Collins:
* FIXME: should we use GetClipboardSequenceNumber to tell if the clipboard has
* changed? How does /dev/clipboard operate under (say) linux?
*/
static const NO_COPY char *CYGWIN_NATIVE = "CYGWIN_NATIVE_CLIPBOARD";
/* this is MT safe because windows format id's are atomic */
static int cygnativeformat;
fhandler_dev_clipboard::fhandler_dev_clipboard ()
: fhandler_base (), pos (0), membuffer (NULL), msize (0),
eof (true)
{
/* FIXME: check for errors and loop until we can open the clipboard */
OpenClipboard (NULL);
cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
CloseClipboard ();
}
/*
* Special clipboard dup to duplicate input and output
* handles.
*/
int
fhandler_dev_clipboard::dup (fhandler_base * child)
{
fhandler_dev_clipboard *fhc = (fhandler_dev_clipboard *) child;
if (!fhc->open (get_flags (), 0))
system_printf ("error opening clipboard, %E");
fhc->membuffer = membuffer;
fhc->pos = pos;
fhc->msize = msize;
return 0;
}
int
fhandler_dev_clipboard::open (int flags, mode_t)
{
set_flags (flags | O_TEXT);
eof = false;
pos = 0;
if (membuffer)
free (membuffer);
membuffer = NULL;
if (!cygnativeformat)
cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
nohandle (true);
set_open_status ();
return 1;
}
static int
set_clipboard (const void *buf, size_t len)
{
HGLOBAL hmem;
unsigned char *clipbuf;
/* Native CYGWIN format */
OpenClipboard (0);
hmem = GlobalAlloc (GMEM_MOVEABLE, len + sizeof (size_t));
if (!hmem)
{
system_printf ("Couldn't allocate global buffer for write");
return -1;
}
clipbuf = (unsigned char *) GlobalLock (hmem);
memcpy (clipbuf + sizeof (size_t), buf, len);
*(size_t *) (clipbuf) = len;
GlobalUnlock (hmem);
EmptyClipboard ();
if (!cygnativeformat)
cygnativeformat = RegisterClipboardFormat (CYGWIN_NATIVE);
if (!SetClipboardData (cygnativeformat, hmem))
{
system_printf
("Couldn't write native format to the clipboard %04x %x",
cygnativeformat, hmem);
/* FIXME: return an appriate error code &| set_errno(); */
return -1;
}
CloseClipboard ();
if (GlobalFree (hmem))
{
system_printf
("Couldn't free global buffer after write to the clipboard");
/* FIXME: return an appriate error code &| set_errno(); */
return 0;
}
/* CF_TEXT/CF_OEMTEXT for copying to wordpad and the like */
OpenClipboard (0);
hmem = GlobalAlloc (GMEM_MOVEABLE, len + 2);
if (!hmem)
{
system_printf ("Couldn't allocate global buffer for write");
return -1;
}
clipbuf = (unsigned char *) GlobalLock (hmem);
memcpy (clipbuf, buf, len);
*(clipbuf + len) = '\0';
*(clipbuf + len + 1) = '\0';
GlobalUnlock (hmem);
if (!SetClipboardData
((current_codepage == ansi_cp ? CF_TEXT : CF_OEMTEXT), hmem))
{
system_printf ("Couldn't write to the clipboard");
/* FIXME: return an appriate error code &| set_errno(); */
return -1;
}
CloseClipboard ();
if (GlobalFree (hmem))
{
system_printf
("Couldn't free global buffer after write to the clipboard");
/* FIXME: return an appriate error code &| set_errno(); */
}
return 0;
}
/* FIXME: arbitrary seeking is not handled */
int
fhandler_dev_clipboard::write (const void *buf, size_t len)
{
if (!eof)
{
/* write to our membuffer */
size_t cursize = msize;
void *tempbuffer = realloc (membuffer, cursize + len);
if (!tempbuffer)
{
system_printf ("Couldn't realloc() clipboard buffer for write");
return -1;
}
membuffer = tempbuffer;
msize = cursize + len;
memcpy ((unsigned char *) membuffer + cursize, buf, len);
/* now pass to windows */
if (set_clipboard (membuffer, msize))
{
/* FIXME: membuffer is now out of sync with pos, but msize is used above */
set_errno (ENOSPC);
return -1;
}
pos = msize;
eof = false;
return len;
}
else
{
/* FIXME: return 0 bytes written, file not open */
return 0;
}
}
void __stdcall
fhandler_dev_clipboard::read (void *ptr, size_t& len)
{
HGLOBAL hglb;
size_t ret;
UINT formatlist[2];
int format;
if (eof)
len = 0;
else
{
formatlist[0] = cygnativeformat;
formatlist[1] = current_codepage == ansi_cp ? CF_TEXT : CF_OEMTEXT;
OpenClipboard (0);
if ((format = GetPriorityClipboardFormat (formatlist, 2)) <= 0)
{
CloseClipboard ();
#if 0
system_printf ("a non-accepted format! %d", format);
#endif
len = 0;
}
else
{
hglb = GetClipboardData (format);
if (format == cygnativeformat)
{
unsigned char *buf = (unsigned char *) GlobalLock (hglb);
size_t buflen = (*(size_t *) buf);
ret = ((len > (buflen - pos)) ? (buflen - pos) : len);
memcpy (ptr, buf + sizeof (size_t)+ pos , ret);
pos += ret;
if (pos + len - ret >= buflen)
eof = true;
GlobalUnlock (hglb);
}
else
{
LPSTR lpstr;
lpstr = (LPSTR) GlobalLock (hglb);
ret = ((len > (strlen (lpstr) - pos)) ? (strlen (lpstr) - pos)
: len);
memcpy (ptr, lpstr + pos, ret);
//ret = snprintf((char *) ptr, len, "%s", lpstr);//+pos);
pos += ret;
if (pos + len - ret >= strlen (lpstr))
eof = true;
GlobalUnlock (hglb);
}
CloseClipboard ();
len = ret;
}
}
}
_off64_t
fhandler_dev_clipboard::lseek (_off64_t offset, int whence)
{
/* On reads we check this at read time, not seek time.
* On writes we use this to decide how to write - empty and write, or open, copy, empty
* and write
*/
pos = offset;
/* treat seek like rewind */
if (membuffer)
free (membuffer);
msize = 0;
return 0;
}
int
fhandler_dev_clipboard::close (void)
{
eof = true;
pos = 0;
if (membuffer)
free (membuffer);
msize = 0;
return 0;
}
void
fhandler_dev_clipboard::dump ()
{
paranoid_printf ("here, fhandler_dev_clipboard");
}