mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 22:25:30 +00:00
1700 lines
39 KiB
C
1700 lines
39 KiB
C
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#include "selection.h"
|
|
#include <libi18n.h>
|
|
#include <layers.h>
|
|
#include <sys/utsname.h>
|
|
#include <pwd.h>
|
|
#include <Xm/CutPaste.h> /* for PasteQuote clipboard hackery */
|
|
/*#include <Xm/AtomMgr.h>*/
|
|
|
|
#include "intl_csi.h"
|
|
#include "felocale.h"
|
|
|
|
static char *fe_clipboard_text = NULL;
|
|
static char *fe_clipboard_html = NULL;
|
|
static char *fe_clipboard_data = NULL;
|
|
static unsigned long fe_clipboard_dlen = 0;
|
|
static Time fe_clipboard_time = 0;
|
|
static Widget fe_clipboard_widget = NULL;
|
|
static XP_Bool fe_clipboard_motif = False;
|
|
static XP_Bool fe_clipboard_empty = True;
|
|
|
|
static char *fe_selection_text = NULL;
|
|
static char *fe_selection_html = NULL;
|
|
static char *fe_selection_data = NULL;
|
|
static unsigned long fe_selection_dlen = 0;
|
|
static Time fe_selection_time = 0;
|
|
static Widget fe_selection_widget = NULL;
|
|
static MWContext *fe_selection_ctx = NULL;
|
|
static MWContext *fe_selection_lost = NULL;
|
|
static XP_Bool fe_selection_empty = True;
|
|
|
|
static char fe_clipboard_data_name[] = "NETSCAPE_HTML";
|
|
static char fe_clipboard_html_name[] = "HTML";
|
|
static char fe_clipboard_text_name[] = "STRING";
|
|
static char fe_clipboard_app_name[] = "MOZILLA";
|
|
|
|
#define XFE_CCP_DATA (fe_clipboard_data_name)
|
|
#define XFE_CCP_HTML (fe_clipboard_html_name)
|
|
#define XFE_CCP_TEXT (fe_clipboard_text_name)
|
|
#define XFE_CCP_NAME (fe_clipboard_app_name)
|
|
|
|
/* Selections
|
|
*/
|
|
|
|
static Boolean
|
|
fe_selection_converter (Widget widget, Atom *selection, Atom *target,
|
|
Atom *type_ret, XtPointer *value_ret,
|
|
unsigned long *length_ret, int *format_ret)
|
|
{
|
|
Display *dpy = XtDisplay (widget);
|
|
XTextProperty tmp_prop;
|
|
int status;
|
|
MWContext *context = fe_WidgetToMWContext (widget);
|
|
|
|
Atom COMPOUND_TEXT = XmInternAtom(dpy, "COMPOUND_TEXT", False);
|
|
Atom XA_TARGETS = XmInternAtom (dpy, "TARGETS", False);
|
|
Atom XA_TIMESTAMP = XmInternAtom (dpy, "TIMESTAMP", False);
|
|
Atom XA_NETSCAPE = XmInternAtom (dpy, XFE_CCP_DATA, False);
|
|
Atom XA_HTML = XmInternAtom (dpy, XFE_CCP_HTML, False);
|
|
Atom XA_TEXT = XmInternAtom (dpy, "TEXT", False);
|
|
Atom XA_LENGTH = XmInternAtom (dpy, "LENGTH", False);
|
|
Atom XA_FILE_NAME = XmInternAtom (dpy, "FILE_NAME", False);
|
|
Atom XA_OWNER_OS = XmInternAtom (dpy, "OWNER_OS", False);
|
|
Atom XA_HOST_NAME = XmInternAtom (dpy, "HOST_NAME", False);
|
|
Atom XA_USER = XmInternAtom (dpy, "USER", False);
|
|
Atom XA_CLASS = XmInternAtom (dpy, "CLASS", False);
|
|
Atom XA_NAME = XmInternAtom (dpy, "NAME", False);
|
|
Atom XA_CLIENT_WINDOW = XmInternAtom (dpy, "CLIENT_WINDOW", False);
|
|
Atom XA_PROCESS = XmInternAtom (dpy, "PROCESS", False);
|
|
#if 0
|
|
Atom XA_CHARACTER_POSITION = XmInternAtom (dpy, "CHARACTER_POSITION", False);
|
|
#endif
|
|
|
|
char *text = 0;
|
|
char *html = 0;
|
|
char *data = 0;
|
|
unsigned long dlen = 0;
|
|
Time time = 0;
|
|
char *loc;
|
|
INTL_CharSetInfo c;
|
|
|
|
XP_ASSERT (context);
|
|
|
|
c = LO_GetDocumentCharacterSetInfo(context);
|
|
|
|
if (*selection == XA_PRIMARY) {
|
|
text = fe_selection_text;
|
|
html = fe_selection_html;
|
|
data = fe_selection_data;
|
|
dlen = fe_selection_dlen;
|
|
time = fe_selection_time;
|
|
}
|
|
else {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_selection_converter::[ CLIPBOARD ] -- NOT\n");
|
|
#endif
|
|
return False;
|
|
}
|
|
|
|
if (!text && !html && !data) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_selection_converter::[ NULL ]\n");
|
|
#endif
|
|
*value_ret = NULL;
|
|
*length_ret = 0;
|
|
*type_ret = None;
|
|
*format_ret = 0;
|
|
return False;
|
|
}
|
|
|
|
/* I can't believe the contortions we need to go through here!! */
|
|
|
|
if (*target == XA_TARGETS)
|
|
{
|
|
Atom *av = (Atom *) malloc (sizeof (Atom) * 20);
|
|
int ac = 0;
|
|
av [ac++] = XA_TARGETS;
|
|
av [ac++] = XA_TIMESTAMP;
|
|
av [ac++] = XA_NETSCAPE;
|
|
av [ac++] = XA_HTML;
|
|
av [ac++] = XA_TEXT;
|
|
av [ac++] = XA_STRING;
|
|
av [ac++] = XA_LENGTH;
|
|
#if 0
|
|
av [ac++] = XA_CHARACTER_POSITION;
|
|
#endif
|
|
av [ac++] = XA_FILE_NAME;
|
|
av [ac++] = XA_OWNER_OS;
|
|
av [ac++] = XA_HOST_NAME;
|
|
av [ac++] = XA_USER;
|
|
av [ac++] = XA_CLASS;
|
|
av [ac++] = XA_NAME;
|
|
av [ac++] = XA_CLIENT_WINDOW;
|
|
av [ac++] = XA_PROCESS;
|
|
av [ac++] = COMPOUND_TEXT;
|
|
|
|
/* Other types that might be interesting (from the R6 ICCCM):
|
|
|
|
XA_MULTIPLE (this is a pain and nobody uses it)
|
|
XA_LINE_NUMBER start and end lines of the selection
|
|
XA_COLUMN_NUMBER start and end column of the selection
|
|
XA_BACKGROUND a list of Pixel values
|
|
XA_FOREGROUND a list of Pixel values
|
|
XA_PIXMAP a list of pixmap IDs (of the images?)
|
|
XA_DRAWABLE a list of drawable IDs (?)
|
|
|
|
XA_COMPOUND_TEXT for text
|
|
|
|
Hairy Image Conversions:
|
|
XA_APPLE_PICT for images
|
|
XA_POSTSCRIPT
|
|
XA_ENCAPSULATED_POSTSCRIPT aka _ADOBE_EPS
|
|
XA_ENCAPSULATED_POSTSCRIPT_INTERCHANGE aka _ADOBE_EPSI
|
|
XA_ODIF ISO Office Document Interchange Format
|
|
*/
|
|
*value_ret = av;
|
|
*length_ret = ac;
|
|
*type_ret = XA_ATOM;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
else if (*target == XA_TIMESTAMP)
|
|
{
|
|
Time *timestamp;
|
|
timestamp = (Time *) malloc (sizeof (Time));
|
|
*timestamp = time;
|
|
*value_ret = (char *) timestamp;
|
|
*length_ret = 1;
|
|
*type_ret = XA_TIMESTAMP;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
else if (*target == XA_NETSCAPE)
|
|
{
|
|
if (dlen > 0) {
|
|
text = XP_ALLOC(dlen+1);
|
|
|
|
memcpy(text, data, dlen);
|
|
|
|
*value_ret = text;
|
|
*length_ret = dlen;
|
|
}
|
|
else {
|
|
*value_ret = NULL;
|
|
*length_ret = 0;
|
|
}
|
|
*type_ret = XA_NETSCAPE;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_HTML)
|
|
{
|
|
*value_ret = strdup (html);
|
|
*length_ret = strlen (html);
|
|
*type_ret = XA_HTML;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (((*target == XA_TEXT) && (INTL_GetCSIWinCSID(c) == CS_LATIN1)) ||
|
|
(*target == XA_STRING))
|
|
{
|
|
*value_ret = strdup (text);
|
|
*length_ret = strlen (text);
|
|
*type_ret = XA_STRING;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_TEXT)
|
|
{
|
|
loc = (char *) fe_ConvertToLocaleEncoding (INTL_GetCSIWinCSID(c),
|
|
(unsigned char *) text);
|
|
status = XmbTextListToTextProperty (dpy, &loc, 1, XStdICCTextStyle,
|
|
&tmp_prop);
|
|
if (loc != text)
|
|
{
|
|
XP_FREE (loc);
|
|
}
|
|
if (status == Success)
|
|
{
|
|
*value_ret = (XtPointer) tmp_prop.value;
|
|
*length_ret = tmp_prop.nitems;
|
|
*type_ret = tmp_prop.encoding; /* STRING or COMPOUND_TEXT */
|
|
*format_ret = tmp_prop.format;
|
|
}
|
|
else
|
|
{
|
|
*value_ret = NULL;
|
|
*length_ret = 0;
|
|
return False;
|
|
}
|
|
return True;
|
|
}
|
|
else if (*target == COMPOUND_TEXT)
|
|
{
|
|
loc = (char *) fe_ConvertToLocaleEncoding (INTL_GetCSIWinCSID(c),
|
|
(unsigned char *) text);
|
|
status = XmbTextListToTextProperty (dpy, &loc, 1, XCompoundTextStyle,
|
|
&tmp_prop);
|
|
if (loc != text)
|
|
{
|
|
XP_FREE (loc);
|
|
}
|
|
if (status == Success)
|
|
{
|
|
*value_ret = (XtPointer) tmp_prop.value;
|
|
*length_ret = tmp_prop.nitems;
|
|
*type_ret = COMPOUND_TEXT;
|
|
*format_ret = 8;
|
|
}
|
|
else
|
|
{
|
|
*value_ret = NULL;
|
|
*length_ret = 0;
|
|
return False;
|
|
}
|
|
return True;
|
|
}
|
|
else if (*target == XA_LENGTH)
|
|
{
|
|
int *len = (int *) malloc (sizeof (int));
|
|
*len = strlen (text);
|
|
*value_ret = len;
|
|
*length_ret = 1;
|
|
*type_ret = XA_INTEGER;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
#if 0
|
|
else if (*target == XA_CHARACTER_POSITION)
|
|
{
|
|
int32 *ends = (int32 *) malloc (sizeof (int32) * 2);
|
|
LO_Element *s, *e;
|
|
CL_Layer *layer;
|
|
|
|
/* oops, this doesn't actually give me character positions -
|
|
just LO_Elements and indexes into them. */
|
|
LO_GetSelectionEndpoints (context, &s, &e, &ends[0], &ends[1], &layer);
|
|
*value_ret = ends;
|
|
*length_ret = 2;
|
|
*type_ret = XA_INTEGER;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
#endif
|
|
else if (*target == XA_FILE_NAME)
|
|
{
|
|
History_entry *current = SHIST_GetCurrent (&context->hist);
|
|
if (!current || !current->address)
|
|
return False;
|
|
*value_ret = strdup (current->address);
|
|
*length_ret = strlen (current->address);
|
|
*type_ret = XA_STRING;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_OWNER_OS)
|
|
{
|
|
char *os;
|
|
struct utsname uts;
|
|
if (uname (&uts) < 0)
|
|
os = "uname failed";
|
|
else
|
|
os = uts.sysname;
|
|
*value_ret = strdup (os);
|
|
*length_ret = strlen (os);
|
|
*type_ret = XA_STRING;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_HOST_NAME)
|
|
{
|
|
char name [255];
|
|
if (gethostname (name, sizeof (name)))
|
|
return False;
|
|
*value_ret = strdup (name);
|
|
*length_ret = strlen (name);
|
|
*type_ret = XA_STRING;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_USER)
|
|
{
|
|
struct passwd *pw = getpwuid (geteuid ());
|
|
char *real_uid = (pw ? pw->pw_name : "");
|
|
char *user_uid = getenv ("LOGNAME");
|
|
if (! user_uid) user_uid = getenv ("USER");
|
|
if (! user_uid) user_uid = real_uid;
|
|
if (! user_uid)
|
|
return False;
|
|
*value_ret = strdup (user_uid);
|
|
*length_ret = strlen (user_uid);
|
|
*type_ret = XA_STRING;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_CLASS)
|
|
{
|
|
*value_ret = strdup (fe_progclass);
|
|
*length_ret = strlen (fe_progclass);
|
|
*type_ret = XA_STRING;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_NAME)
|
|
{
|
|
*value_ret = strdup (fe_progname);
|
|
*length_ret = strlen (fe_progname);
|
|
*type_ret = XA_STRING;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_CLIENT_WINDOW)
|
|
{
|
|
Window *window;
|
|
window = (Window *) malloc (sizeof (Window));
|
|
*window = XtWindow (CONTEXT_WIDGET (context));
|
|
*value_ret = window;
|
|
*length_ret = 1;
|
|
*type_ret = XA_WINDOW;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
else if (*target == XA_PROCESS)
|
|
{
|
|
pid_t *pid;
|
|
pid = (pid_t *) malloc (sizeof (pid_t));
|
|
*pid = getpid ();
|
|
*value_ret = pid;
|
|
*length_ret = 1;
|
|
*type_ret = XA_INTEGER;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
else if (*target == XA_COLORMAP)
|
|
{
|
|
Colormap *cmap;
|
|
cmap = (Colormap *) malloc (sizeof (Colormap));
|
|
*cmap = fe_cmap(context);
|
|
*value_ret = cmap;
|
|
*length_ret = 1;
|
|
*type_ret = XA_COLORMAP;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
static Boolean
|
|
fe_clipboard_converter (Widget widget, Atom *selection, Atom *target,
|
|
Atom *type_ret, XtPointer *value_ret,
|
|
unsigned long *length_ret, int *format_ret)
|
|
{
|
|
Display *dpy = XtDisplay (widget);
|
|
XTextProperty tmp_prop;
|
|
int status;
|
|
|
|
Atom XA_TARGETS = XmInternAtom (dpy, "TARGETS", False);
|
|
Atom XA_TIMESTAMP = XmInternAtom (dpy, "TIMESTAMP", False);
|
|
Atom XA_TEXT = XmInternAtom (dpy, "TEXT", False);
|
|
Atom XA_HTML = XmInternAtom (dpy, XFE_CCP_HTML, False);
|
|
Atom XA_NETSCAPE = XmInternAtom (dpy, XFE_CCP_DATA, False);
|
|
Atom XA_LENGTH = XmInternAtom (dpy, "LENGTH", False);
|
|
|
|
char *text = NULL;
|
|
char *html = NULL;
|
|
char *data = NULL;
|
|
unsigned long dlen = 0;
|
|
Time time = 0;
|
|
|
|
if (*selection == XmInternAtom (dpy, "CLIPBOARD", False)) {
|
|
text = fe_clipboard_text;
|
|
html = fe_clipboard_html;
|
|
data = fe_clipboard_data;
|
|
dlen = fe_clipboard_dlen;
|
|
time = fe_clipboard_time;
|
|
}
|
|
else {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_clipboard_converter::[ PRIMARY ] -- NOT\n");
|
|
#endif
|
|
return False;
|
|
}
|
|
|
|
if (!text && !html && !data) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_clipboard_converter::[ NULL ]\n");
|
|
#endif
|
|
return False;
|
|
}
|
|
|
|
if (*target == XA_TARGETS)
|
|
{
|
|
Atom *av = (Atom *) malloc (sizeof (Atom) * 20);
|
|
int ac = 0;
|
|
av [ac++] = XA_TARGETS;
|
|
av [ac++] = XA_TIMESTAMP;
|
|
av [ac++] = XA_TEXT;
|
|
av [ac++] = XA_HTML;
|
|
av [ac++] = XA_NETSCAPE;
|
|
av [ac++] = XA_STRING;
|
|
av [ac++] = XA_LENGTH;
|
|
|
|
*value_ret = av;
|
|
*length_ret = ac;
|
|
*type_ret = XA_ATOM;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
else if (*target == XA_TIMESTAMP)
|
|
{
|
|
Time *timestamp;
|
|
timestamp = (Time *) malloc (sizeof (Time));
|
|
*timestamp = time;
|
|
*value_ret = (char *) timestamp;
|
|
*length_ret = 1;
|
|
*type_ret = XA_TIMESTAMP;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
else if ((*target == XA_TEXT) ||
|
|
(*target == XA_STRING))
|
|
{
|
|
if (text) {
|
|
*value_ret = strdup (text);
|
|
*length_ret = strlen (text);
|
|
*type_ret = XA_STRING;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else {
|
|
return False;
|
|
}
|
|
}
|
|
else if (*target == XA_HTML)
|
|
{
|
|
if (html) {
|
|
*value_ret = strdup (html);
|
|
*length_ret = strlen (html);
|
|
*type_ret = XA_HTML;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else {
|
|
return False;
|
|
}
|
|
}
|
|
else if (*target == XA_NETSCAPE)
|
|
{
|
|
if (dlen > 0) {
|
|
text = XP_ALLOC(dlen+1);
|
|
|
|
memcpy(text, data, dlen);
|
|
|
|
*value_ret = text;
|
|
*length_ret = dlen;
|
|
}
|
|
else {
|
|
*value_ret = NULL;
|
|
*length_ret = 0;
|
|
}
|
|
*type_ret = XA_NETSCAPE;
|
|
*format_ret = 8;
|
|
return True;
|
|
}
|
|
else if (*target == XA_LENGTH)
|
|
{
|
|
int *len = (int *) malloc (sizeof (int));
|
|
|
|
if (text) {
|
|
*len = strlen(text);
|
|
*value_ret = len;
|
|
*length_ret = 1;
|
|
*type_ret = XA_INTEGER;
|
|
*format_ret = 32;
|
|
return True;
|
|
}
|
|
else {
|
|
return False;
|
|
}
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
Boolean
|
|
fe_own_selection_p (MWContext *context, Boolean clip_p)
|
|
{
|
|
Widget mainw = CONTEXT_WIDGET(context);
|
|
Display *dpy = XtDisplay (mainw);
|
|
|
|
if (clip_p) {
|
|
|
|
/* Is there an internal clipboard entry? */
|
|
if (fe_clipboard_text) {
|
|
return True;
|
|
} else {
|
|
Atom atom = XmInternAtom (dpy, "CLIPBOARD", False);
|
|
|
|
/* Is there an external clipboard owner? */
|
|
if (XGetSelectionOwner (dpy, atom)) {
|
|
return True;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* Do we own the internal selection entry? */
|
|
if (mainw == fe_selection_widget) {
|
|
return True;
|
|
} else {
|
|
Window window = XGetSelectionOwner (dpy, XA_PRIMARY);
|
|
Widget selection_widget = XtWindowToWidget(dpy, window);
|
|
|
|
/* Is there a selection widget? */
|
|
if (selection_widget) {
|
|
XmTextPosition left, right;
|
|
MWContext *ref;
|
|
|
|
ref = fe_WidgetToMWContext(selection_widget);
|
|
ref = XP_GetNonGridContext (ref);
|
|
|
|
/* Does the selection widget belong to us?
|
|
* and is there a true selection?
|
|
*/
|
|
if (ref == context
|
|
&& (XmIsText(selection_widget)
|
|
|| XmIsTextField(selection_widget))
|
|
&& XmTextGetSelectionPosition(selection_widget,
|
|
&left, &right)
|
|
&& ((right - left) > 0)) {
|
|
return True;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return False;
|
|
}
|
|
|
|
/* Used by XFE_HTMLView::isCommandEnabled() */
|
|
Boolean
|
|
fe_can_cut (MWContext *context)
|
|
{
|
|
return fe_own_selection_p(context, FALSE);
|
|
}
|
|
|
|
/* Used by XFE_HTMLView::isCommandEnabled() */
|
|
Boolean
|
|
fe_can_copy (MWContext *context)
|
|
{
|
|
return fe_own_selection_p(context, FALSE);
|
|
}
|
|
|
|
/* Used by XFE_HTMLView::isCommandEnabled() */
|
|
Boolean
|
|
fe_can_paste (MWContext *context)
|
|
{
|
|
return fe_own_selection_p(context, TRUE);
|
|
}
|
|
|
|
Window
|
|
xfe_GetClipboardWindow(Widget focus)
|
|
{
|
|
Window target = NULL;
|
|
|
|
if (fe_clipboard_widget)
|
|
target = XtWindow(fe_clipboard_widget);
|
|
else
|
|
target = XtWindow(focus);
|
|
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_GetClipboardWindow::[ %p ][ %p ]\n",
|
|
XtWindow(focus), target);
|
|
#endif
|
|
return target;
|
|
}
|
|
|
|
static void
|
|
fe_clipboard_loser (Widget widget, Atom *selection)
|
|
{
|
|
Display *dpy = XtDisplay (widget);
|
|
|
|
if (*selection == XmInternAtom (dpy, "CLIPBOARD", False)) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_clipboard_loser::[ ]\n");
|
|
#endif
|
|
fe_DisownClipboard (widget, 0);
|
|
}
|
|
else {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_clipboard_loser::[ invalid atom ]\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void
|
|
fe_selection_loser (Widget widget, Atom *selection)
|
|
{
|
|
Display *dpy = XtDisplay (widget);
|
|
MWContext *context = fe_WidgetToMWContext (widget);
|
|
|
|
if (! context) {
|
|
/* Are you talking to me? */
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_selection_loser::[ NULL ]\n");
|
|
#endif
|
|
}
|
|
else if (*selection == XA_PRIMARY) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_selection_loser::[ PRIMARY ]\n");
|
|
#endif
|
|
fe_DisownPrimarySelection(widget, 0);
|
|
}
|
|
else {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_selection_loser::[ ERROR ][ invalid target ]\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void
|
|
fe_set_clipboard(Widget focus, Time time,
|
|
char *text, char* html, char* data, unsigned long data_len,
|
|
XP_Bool motif_p)
|
|
{
|
|
if (fe_clipboard_text) {
|
|
XP_FREE(fe_clipboard_text);
|
|
fe_clipboard_text = NULL;
|
|
}
|
|
|
|
if (fe_clipboard_html) {
|
|
XP_FREE(fe_clipboard_html);
|
|
fe_clipboard_html = NULL;
|
|
}
|
|
|
|
if (fe_clipboard_data) {
|
|
XP_FREE(fe_clipboard_data);
|
|
fe_clipboard_data = NULL;
|
|
}
|
|
|
|
if (text) {
|
|
fe_clipboard_text = XP_STRDUP(text);
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"fe_set_clipboard::[ %d ] TEXT\n", strlen(text));
|
|
#endif
|
|
}
|
|
|
|
if (html) {
|
|
fe_clipboard_html = XP_STRDUP(html);
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"fe_set_clipboard::[ %d ] HTML\n", strlen(html));
|
|
#endif
|
|
}
|
|
|
|
if (data) {
|
|
fe_clipboard_data = XP_ALLOC(data_len+1);
|
|
memcpy(fe_clipboard_data, data, data_len);
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"fe_set_clipboard::[ %d ] DATA\n", data_len);
|
|
#endif
|
|
}
|
|
|
|
fe_clipboard_dlen = data_len;
|
|
fe_clipboard_time = time;
|
|
fe_clipboard_widget = focus;
|
|
fe_clipboard_motif = motif_p;
|
|
fe_clipboard_empty = False;
|
|
}
|
|
|
|
static void
|
|
fe_set_selection(Widget focus, Time time,
|
|
char *text, char* html, char* data, unsigned long data_len,
|
|
MWContext* ctx
|
|
)
|
|
{
|
|
if (fe_selection_text) {
|
|
XP_FREE(fe_selection_text);
|
|
fe_selection_text = NULL;
|
|
}
|
|
|
|
if (fe_selection_html) {
|
|
XP_FREE(fe_selection_html);
|
|
fe_selection_html = NULL;
|
|
}
|
|
|
|
if (fe_selection_data) {
|
|
XP_FREE(fe_selection_data);
|
|
fe_selection_data = NULL;
|
|
}
|
|
|
|
if (text) {
|
|
fe_selection_text = XP_STRDUP(text);
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"fe_set_selection::[ %d ] TEXT\n", strlen(text));
|
|
#endif
|
|
}
|
|
|
|
if (html) {
|
|
fe_selection_html = XP_STRDUP(html);
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"fe_set_selection::[ %d ] HTML\n", strlen(html));
|
|
#endif
|
|
}
|
|
|
|
if (data) {
|
|
fe_selection_data = XP_ALLOC(data_len+1);
|
|
memcpy(fe_selection_data, data, data_len);
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"fe_set_selection::[ %d ] DATA\n", data_len);
|
|
#endif
|
|
}
|
|
|
|
if (fe_selection_ctx) {
|
|
if (fe_selection_lost) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "WARNING... [ lost in fe_set_selection ][ %p ]\n",
|
|
fe_selection_lost);
|
|
#endif
|
|
}
|
|
fe_selection_lost = fe_selection_ctx;
|
|
}
|
|
|
|
fe_selection_ctx = ctx;
|
|
fe_selection_dlen = data_len;
|
|
fe_selection_time = time;
|
|
fe_selection_widget = focus;
|
|
fe_selection_empty = False;
|
|
}
|
|
|
|
static void
|
|
fe_clear_clipboard()
|
|
{
|
|
if (fe_clipboard_empty) {
|
|
}
|
|
else {
|
|
fe_clipboard_empty = True;
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_clear_clipboard::[ ]\n");
|
|
#endif
|
|
if (fe_clipboard_text) {
|
|
XP_FREE( fe_clipboard_text );
|
|
fe_clipboard_text = NULL;
|
|
}
|
|
|
|
if (fe_clipboard_html) {
|
|
XP_FREE( fe_clipboard_html );
|
|
fe_clipboard_html = NULL;
|
|
}
|
|
|
|
if (fe_clipboard_data) {
|
|
XP_FREE( fe_clipboard_data );
|
|
fe_clipboard_data = NULL;
|
|
}
|
|
|
|
fe_clipboard_dlen = 0;
|
|
fe_clipboard_time = 0;
|
|
fe_clipboard_widget = NULL;
|
|
fe_clipboard_motif = False;
|
|
}
|
|
}
|
|
|
|
static void
|
|
fe_clear_selection()
|
|
{
|
|
if (fe_selection_empty) {
|
|
}
|
|
else {
|
|
fe_selection_empty = True;
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_clear_selection::[ ]\n");
|
|
#endif
|
|
if (fe_selection_text) {
|
|
XP_FREE( fe_selection_text );
|
|
fe_selection_text = NULL;
|
|
}
|
|
|
|
if (fe_selection_html) {
|
|
XP_FREE( fe_selection_html );
|
|
fe_selection_html = NULL;
|
|
}
|
|
|
|
if (fe_selection_data) {
|
|
XP_FREE( fe_selection_data );
|
|
fe_selection_data = NULL;
|
|
}
|
|
|
|
if (fe_selection_ctx) {
|
|
if (fe_selection_lost) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"WARING... [ lost in fe_clear_selection ][ %p ]\n",
|
|
fe_selection_lost);
|
|
#endif
|
|
}
|
|
fe_selection_lost = fe_selection_ctx;
|
|
}
|
|
|
|
fe_selection_ctx = NULL;
|
|
fe_selection_dlen = 0;
|
|
fe_selection_time = 0;
|
|
fe_selection_widget = NULL;
|
|
}
|
|
}
|
|
|
|
#ifdef EDITOR
|
|
|
|
static void
|
|
fe_edt_selection_loser (Widget widget, Atom *selection)
|
|
{
|
|
Display *dpy = XtDisplay (widget);
|
|
MWContext *context = fe_WidgetToMWContext (widget);
|
|
|
|
if (! context) {
|
|
/* Are you talking to me? */
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_edt_selection_loser::[ NULL ]\n");
|
|
#endif
|
|
}
|
|
else if (*selection == XA_PRIMARY) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_edt_selection_loser::[ PRIMARY ]\n");
|
|
#endif
|
|
fe_EditorDisownSelection (context, 0, False);
|
|
}
|
|
else if (*selection == XmInternAtom (dpy, "CLIPBOARD", False)) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_edt_selection_loser::[ CLIPBOARD ]\n");
|
|
#endif
|
|
fe_EditorDisownSelection (context, 0, True);
|
|
}
|
|
}
|
|
|
|
void
|
|
fe_OwnEDTSelection (MWContext *context, Time time, Boolean clip_p,
|
|
char *text, char *html, char *data, unsigned long data_len)
|
|
{
|
|
Widget mainw = CONTEXT_WIDGET(context);
|
|
Display *dpy = XtDisplay (mainw);
|
|
Atom atom = (clip_p ? XmInternAtom (dpy, "CLIPBOARD", False) : XA_PRIMARY);
|
|
|
|
if (clip_p)
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_own_edt_selection::[ CLIPBOARD ]\n");
|
|
#endif
|
|
fe_clear_clipboard();
|
|
|
|
fe_set_clipboard(mainw, time,
|
|
text, html, data, data_len, False);
|
|
|
|
if (text) {
|
|
XtOwnSelection (mainw, atom, time,
|
|
fe_clipboard_converter, /* conversion proc */
|
|
fe_edt_selection_loser, /* lost proc */
|
|
0); /* ACK proc */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_own_edt_selection::[ PRIMARY ]\n");
|
|
#endif
|
|
fe_clear_selection();
|
|
|
|
fe_set_selection(mainw, time,
|
|
text, html, data, data_len, context);
|
|
|
|
if (text) {
|
|
XtOwnSelection (mainw, atom, time,
|
|
fe_selection_converter, /* conversion proc */
|
|
fe_edt_selection_loser, /* lost proc */
|
|
0); /* ACK proc */
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* EDITOR */
|
|
|
|
void
|
|
fe_OwnClipboard(Widget focus, Time time,
|
|
char* text, char* html, char* data, unsigned long data_len,
|
|
XP_Bool motif_p)
|
|
{
|
|
Display *dpy = XtDisplay (focus);
|
|
Atom atom = XmInternAtom (dpy, "CLIPBOARD", False);
|
|
|
|
if ((text && (strlen(text) > 0)) ||
|
|
(html && (strlen(html) > 0)) ||
|
|
(data && (data_len > 0))
|
|
) {
|
|
fe_clear_clipboard();
|
|
|
|
fe_set_clipboard(focus, time, text, html, data, data_len, motif_p);
|
|
|
|
#ifdef DEBUG_rhess
|
|
if (data) {
|
|
if (html) {
|
|
if (text) {
|
|
fprintf(stderr, "fe_OwnClipboard::[ %p ][ %d, %d, %d ]\n",
|
|
focus, strlen(text), strlen(html), data_len);
|
|
}
|
|
else {
|
|
fprintf(stderr, "fe_OwnClipboard::[ %p ][ NULL, %d, %d ]\n",
|
|
focus, strlen(html), data_len);
|
|
}
|
|
}
|
|
else {
|
|
if (text) {
|
|
fprintf(stderr, "fe_OwnClipboard::[ %p ][ %d, NULL, %d ]\n",
|
|
focus, strlen(text), data_len);
|
|
}
|
|
else {
|
|
fprintf(stderr,
|
|
"fe_OwnClipboard::[ %p ][ NULL, NULL, %d ]\n",
|
|
focus, data_len);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (html) {
|
|
if (text) {
|
|
fprintf(stderr, "fe_OwnClipboard::[ %p ][ %d, %d, NULL ]\n",
|
|
focus, strlen(text), strlen(html));
|
|
}
|
|
else {
|
|
fprintf(stderr,
|
|
"fe_OwnClipboard::[ %p ][ NULL, %d, NULL ]\n",
|
|
focus, strlen(html));
|
|
}
|
|
}
|
|
else {
|
|
if (text) {
|
|
fprintf(stderr,
|
|
"fe_OwnClipboard::[ %p ][ %d, NULL, NULL ]\n",
|
|
focus, strlen(text));
|
|
}
|
|
else {
|
|
fprintf(stderr,
|
|
"fe_OwnClipboard::[ %p ][ NULL, NULL, NULL ]\n",
|
|
focus);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
XtOwnSelection (focus, atom, time,
|
|
fe_clipboard_converter, /* conversion proc */
|
|
fe_clipboard_loser, /* lost proc */
|
|
0); /* ACK proc */
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
fe_DisownClipboard(Widget focus, Time time)
|
|
{
|
|
Display *dpy = XtDisplay (focus);
|
|
Atom atom = XmInternAtom (dpy, "CLIPBOARD", False);
|
|
XtDisownSelection (focus, atom, time);
|
|
|
|
if (focus == fe_clipboard_widget) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_DisownClipboard::[ %p ]\n", focus);
|
|
#endif
|
|
fe_clear_clipboard();
|
|
}
|
|
}
|
|
|
|
void
|
|
fe_OwnPrimarySelection(Widget focus, Time time,
|
|
char* text, char* html,
|
|
char* data, unsigned long data_len,
|
|
MWContext* context)
|
|
{
|
|
Display *dpy = XtDisplay (focus);
|
|
Atom atom = XA_PRIMARY;
|
|
|
|
if ((text && (strlen(text) > 0)) ||
|
|
(html && (strlen(html) > 0)) ||
|
|
(data && (data_len > 0))
|
|
) {
|
|
fe_clear_selection();
|
|
|
|
fe_set_selection(focus, time, text, html, data, data_len, context);
|
|
|
|
#ifdef DEBUG_rhess
|
|
if (text) {
|
|
if (html) {
|
|
fprintf(stderr,
|
|
"fe_OwnPrimarySelection::[ %p ][ %d, %d, %d ]\n",
|
|
focus, strlen(text), strlen(html), data_len);
|
|
}
|
|
else {
|
|
fprintf(stderr,
|
|
"fe_OwnPrimarySelection::[ %p ][ %d, 0, %d ]\n",
|
|
focus, strlen(text), data_len);
|
|
}
|
|
}
|
|
else {
|
|
if (html) {
|
|
fprintf(stderr, "fe_OwnPrimarySelection::[ %p ][ 0, %d, %d ]\n",
|
|
focus, strlen(html), data_len);
|
|
}
|
|
else {
|
|
fprintf(stderr, "fe_OwnPrimarySelection::[ %p ][ 0, 0, %d ]\n",
|
|
focus, data_len);
|
|
}
|
|
}
|
|
#endif
|
|
XtOwnSelection (focus, atom, time,
|
|
fe_selection_converter, /* conversion proc */
|
|
fe_selection_loser, /* lost proc */
|
|
0); /* ACK proc */
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
fe_DisownPrimarySelection(Widget focus, Time time)
|
|
{
|
|
Display *dpy = XtDisplay (focus);
|
|
Atom atom = XA_PRIMARY;
|
|
|
|
XtDisownSelection (focus, atom, time);
|
|
|
|
if (fe_selection_lost) {
|
|
LO_ClearSelection(fe_selection_lost);
|
|
fe_selection_lost = NULL;
|
|
}
|
|
else {
|
|
if (focus == fe_selection_widget) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_DisownPrimarySelection::[ %p ]\n", focus);
|
|
#endif
|
|
if (fe_selection_empty) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_DisownPrimarySelection::[ punt ]\n");
|
|
#endif
|
|
}
|
|
else {
|
|
if (fe_selection_ctx) {
|
|
#ifdef EDITOR
|
|
if ((fe_selection_ctx->type ==
|
|
MWContextMessageComposition) ||
|
|
(fe_selection_ctx->type == MWContextEditor)) {
|
|
if (!fe_ContextHasPopups(fe_selection_ctx)) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"fe_DisownPrimarySelection::[ %p ] EDT\n",
|
|
fe_selection_ctx);
|
|
#endif
|
|
EDT_ClearSelection(fe_selection_ctx);
|
|
}
|
|
}
|
|
else {
|
|
#endif /* EDITOR */
|
|
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr,
|
|
"fe_DisownPrimarySelection::[ %p ] LO\n",
|
|
fe_selection_ctx);
|
|
#endif
|
|
LO_ClearSelection(fe_selection_ctx);
|
|
#ifdef EDITOR
|
|
}
|
|
#endif
|
|
fe_selection_ctx = NULL;
|
|
}
|
|
fe_clear_selection();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
fe_OwnSelection (MWContext *context, Time time, Boolean clip_p)
|
|
{
|
|
Widget mainw = CONTEXT_WIDGET(context);
|
|
char *text = (char *) LO_GetSelectionText (context);
|
|
|
|
if (clip_p) {
|
|
fe_OwnClipboard(mainw, time,
|
|
text, NULL, NULL, 0, False);
|
|
}
|
|
else {
|
|
fe_OwnPrimarySelection(mainw, time,
|
|
text, NULL, NULL, 0, context);
|
|
}
|
|
|
|
if (text) XP_FREE(text);
|
|
}
|
|
|
|
void
|
|
fe_DisownSelection (MWContext *context, Time time, Boolean clip_p)
|
|
{
|
|
Widget mainw = CONTEXT_WIDGET(context);
|
|
|
|
if (clip_p) {
|
|
if (fe_clipboard_widget) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_DisownSelection::[ CLIPBOARD ]\n");
|
|
#endif
|
|
fe_DisownClipboard(mainw, time);
|
|
}
|
|
}
|
|
else {
|
|
if (fe_selection_widget) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "fe_DisownSelection::[ PRIMARY ]\n");
|
|
#endif
|
|
fe_DisownPrimarySelection(mainw, time);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
xfe_clipboard_retrieve_work(Widget focus,
|
|
char* name,
|
|
char** buf, unsigned long* buf_len_a,
|
|
Time timestamp)
|
|
{
|
|
Display* display = XtDisplay(focus);
|
|
Window window = xfe_GetClipboardWindow(focus);
|
|
int cb_result;
|
|
long private_id;
|
|
int i;
|
|
|
|
char *clip_data = NULL;
|
|
char work_data[512];
|
|
|
|
unsigned long length = 0;
|
|
unsigned long clip_len = 0;
|
|
|
|
cb_result = XmClipboardLock(display, window);
|
|
|
|
if (cb_result != ClipboardSuccess) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_clipboard_retrieve::[ FAILED LOCK ]\n");
|
|
#endif
|
|
*buf_len_a = 0;
|
|
*buf = NULL;
|
|
return cb_result;
|
|
}
|
|
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_clipboard_retrieve::[ LOCK ]\n");
|
|
#endif
|
|
|
|
cb_result = XmClipboardInquireLength(display, window,
|
|
name, &length);
|
|
|
|
if (cb_result != ClipboardSuccess) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_clipboard_retrieve::[ FAILED INQUIRE ]\n");
|
|
#endif
|
|
XmClipboardUnlock(display, window, TRUE);
|
|
|
|
*buf_len_a = 0;
|
|
*buf = NULL;
|
|
return cb_result;
|
|
}
|
|
|
|
clip_data = XP_ALLOC(length+1);
|
|
clip_len = 0;
|
|
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_clipboard_retrieve::[ %d ]\n", length);
|
|
#endif
|
|
|
|
cb_result = XmClipboardRetrieve(display, window,
|
|
name,
|
|
(XtPointer) clip_data,
|
|
length,
|
|
&clip_len,
|
|
&private_id);
|
|
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_clipboard_retrieve::[ %d ]\n", clip_len);
|
|
#endif
|
|
clip_data[clip_len] = '\0';
|
|
|
|
*buf_len_a = clip_len;
|
|
*buf = clip_data;
|
|
|
|
XmClipboardUnlock(display, window, TRUE);
|
|
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_clipboard_retrieve::[ UNLOCK ]\n");
|
|
#endif
|
|
|
|
return cb_result;
|
|
}
|
|
|
|
char *
|
|
xfe2_GetClipboardText (Widget focus, int32 *internal)
|
|
{
|
|
unsigned long length;
|
|
int cb_result;
|
|
|
|
Display* display = XtDisplay(focus);
|
|
Window window = xfe_GetClipboardWindow(focus);
|
|
Time timestamp = XtLastTimestampProcessed (display);
|
|
|
|
struct fe_MWContext_cons *rest;
|
|
|
|
char *clip_data = NULL;
|
|
char *clip_name = NULL;
|
|
int i;
|
|
|
|
if (fe_clipboard_motif || !fe_clipboard_widget) {
|
|
*internal = 0;
|
|
}
|
|
else {
|
|
MWContext *context = fe_WidgetToMWContext(fe_clipboard_widget);
|
|
|
|
*internal = (int) context;
|
|
}
|
|
|
|
/*
|
|
* NOTE: look in our "internal" clipboard cache...
|
|
* - [ shortcut for internal paste ]
|
|
*
|
|
*/
|
|
if (!clip_data) {
|
|
if (fe_clipboard_text) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe2_GetClipboardText::[ cache ]\n");
|
|
#endif
|
|
clip_data = XP_STRDUP(fe_clipboard_text);
|
|
}
|
|
}
|
|
|
|
if (!clip_data) { /* go look on real CLIPBOARD */
|
|
|
|
clip_name = XFE_CCP_TEXT;
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe2_GetClipboardText::[ retrieve ]\n");
|
|
#endif
|
|
cb_result = xfe_clipboard_retrieve_work(focus,
|
|
clip_name,
|
|
&clip_data, &length,
|
|
timestamp);
|
|
|
|
if (cb_result != ClipboardSuccess) {
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe2_GetClipboardText::[ failed ]\n");
|
|
#endif
|
|
XP_FREE(clip_data);
|
|
clip_data = NULL;
|
|
clip_name = NULL;
|
|
}
|
|
}
|
|
|
|
return clip_data;
|
|
}
|
|
|
|
static void
|
|
fe_text_insert (Widget text, const char *s, int16 charset)
|
|
{
|
|
/* Gee, I wonder what other gratuitous junk I need to worry about? */
|
|
Boolean pdel = True;
|
|
XtVaGetValues (text, XmNpendingDelete, &pdel, 0);
|
|
|
|
if (XmIsText (text))
|
|
{
|
|
char *s2 = strdup (s); /* This is nuts: it wants to modify the string! */
|
|
char *loc;
|
|
if (pdel) XmTextRemove (text);
|
|
loc = (char *) fe_ConvertToLocaleEncoding (charset,
|
|
(unsigned char *) s2);
|
|
XmTextInsert (text, XmTextGetInsertionPosition (text), loc);
|
|
if (loc != s2)
|
|
{
|
|
free (loc);
|
|
}
|
|
free (s2);
|
|
}
|
|
else if (XmIsTextField (text))
|
|
{
|
|
char *s2 = strdup (s); /* This is nuts: it wants to modify the string! */
|
|
char *loc;
|
|
if (pdel) XmTextFieldRemove (text);
|
|
loc = (char *) fe_ConvertToLocaleEncoding (charset,
|
|
(unsigned char *) s2);
|
|
XmTextFieldInsert (text, XmTextFieldGetInsertionPosition (text), loc);
|
|
if (loc != s2)
|
|
{
|
|
free (loc);
|
|
}
|
|
free (s2);
|
|
}
|
|
else
|
|
abort ();
|
|
}
|
|
|
|
XP_Bool
|
|
fe_InternalSelection(XP_Bool clip_p,
|
|
unsigned long *text_len,
|
|
unsigned long *html_len,
|
|
unsigned long *data_len)
|
|
{
|
|
XP_Bool gotcha = False;
|
|
char *text = NULL;
|
|
char *html = NULL;
|
|
char *data = NULL;
|
|
unsigned long dlen = 0;
|
|
|
|
if (clip_p) {
|
|
text = fe_clipboard_text;
|
|
html = fe_clipboard_html;
|
|
data = fe_clipboard_data;
|
|
dlen = fe_clipboard_dlen;
|
|
}
|
|
else {
|
|
text = fe_selection_text;
|
|
html = fe_selection_html;
|
|
data = fe_selection_data;
|
|
dlen = fe_selection_dlen;
|
|
}
|
|
|
|
if (text) {
|
|
*text_len = strlen(text);
|
|
gotcha = True;
|
|
}
|
|
else {
|
|
*text_len = 0;
|
|
}
|
|
|
|
if (html) {
|
|
*html_len = strlen(html);
|
|
gotcha = True;
|
|
}
|
|
else {
|
|
*html_len = 0;
|
|
}
|
|
|
|
if (dlen > 0) {
|
|
*data_len = dlen;
|
|
gotcha = True;
|
|
}
|
|
else {
|
|
*data_len = 0;
|
|
}
|
|
|
|
return gotcha;
|
|
}
|
|
|
|
char *
|
|
fe_GetPrimaryText(void)
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
if (fe_selection_text)
|
|
fprintf(stderr,
|
|
"fe_GetPrimaryText::[ %d ]\n", strlen(fe_selection_text));
|
|
else
|
|
fprintf(stderr,
|
|
"fe_GetPrimaryText::[ NULL ]\n");
|
|
#endif
|
|
return fe_selection_text;
|
|
}
|
|
|
|
char *
|
|
fe_GetPrimaryHtml(void)
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
if (fe_selection_html)
|
|
fprintf(stderr,
|
|
"fe_GetPrimaryHtml::[ %d ]\n", strlen(fe_selection_html));
|
|
else
|
|
fprintf(stderr,
|
|
"fe_GetPrimaryHtml::[ NULL ]\n");
|
|
#endif
|
|
return fe_selection_html;
|
|
}
|
|
|
|
char *
|
|
fe_GetPrimaryData(unsigned long *length)
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
if (fe_selection_data && (fe_selection_dlen > 0))
|
|
fprintf(stderr,
|
|
"fe_GetPrimaryData::[ %d ]\n", fe_selection_dlen);
|
|
else
|
|
fprintf(stderr,
|
|
"fe_GetPrimaryData::[ NULL ]\n");
|
|
#endif
|
|
*length = fe_selection_dlen;
|
|
|
|
if (fe_selection_dlen > 0) {
|
|
return fe_selection_data;
|
|
}
|
|
else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
char *
|
|
fe_GetInternalText(void)
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
if (fe_clipboard_text)
|
|
fprintf(stderr,
|
|
"fe_GetInternalText::[ %d ]\n", strlen(fe_clipboard_text));
|
|
else
|
|
fprintf(stderr,
|
|
"fe_GetInternalText::[ NULL ]\n");
|
|
#endif
|
|
return fe_clipboard_text;
|
|
}
|
|
|
|
char *
|
|
fe_GetInternalHtml(void)
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
if (fe_clipboard_html)
|
|
fprintf(stderr,
|
|
"fe_GetInternalHtml::[ %d ]\n", strlen(fe_clipboard_html));
|
|
else
|
|
fprintf(stderr,
|
|
"fe_GetInternalHtml::[ NULL ]\n");
|
|
#endif
|
|
return fe_clipboard_html;
|
|
}
|
|
|
|
char *
|
|
fe_GetInternalData(unsigned long *length)
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
if (fe_clipboard_data && (fe_clipboard_dlen > 0))
|
|
fprintf(stderr,
|
|
"fe_GetInternalData::[ %d ]\n", fe_clipboard_dlen);
|
|
else
|
|
fprintf(stderr,
|
|
"fe_GetInternalData::[ NULL ]\n");
|
|
#endif
|
|
*length = fe_clipboard_dlen;
|
|
|
|
if (fe_clipboard_dlen > 0) {
|
|
return fe_clipboard_data;
|
|
}
|
|
else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* NOTE: we need this to support the unified cut/copy/paste mechanism...
|
|
*
|
|
* - this allows translations to call cut/copy on a specific widget
|
|
*
|
|
*/
|
|
void
|
|
xfe_TextCopy(MWContext *context, Widget focus, XP_Bool cut)
|
|
{
|
|
XP_Bool text_wp = False;
|
|
XP_Bool text_fp = False;
|
|
char *clip = NULL;
|
|
Time time = 0;
|
|
|
|
if (!focus)
|
|
return;
|
|
|
|
text_wp = XmIsText(focus);
|
|
text_fp = XmIsTextField(focus);
|
|
|
|
if (text_wp || text_fp) {
|
|
|
|
clip = fe_GetTextSelection(focus);
|
|
if (clip) {
|
|
time = XtLastTimestampProcessed(XtDisplay(focus));
|
|
|
|
fe_OwnClipboard(focus, time,
|
|
clip, NULL, NULL, 0, True);
|
|
XP_FREE(clip);
|
|
|
|
if (cut) {
|
|
if (text_wp)
|
|
XmTextRemove(focus);
|
|
else
|
|
XmTextFieldRemove(focus);
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_TextCopy::[ CUT ]\n");
|
|
#endif
|
|
}
|
|
#ifdef DEBUG_rhess
|
|
else {
|
|
fprintf(stderr, "xfe_TextCopy::[ ]\n");
|
|
}
|
|
#endif
|
|
}
|
|
#ifdef DEBUG_rhess
|
|
else {
|
|
fprintf(stderr, "xfe_TextCopy::[ failed to get selection ]\n");
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* Motif sucks! XmTextPaste() gets stuck if you're pasting from one
|
|
widget to another in the same application! */
|
|
void
|
|
xfe_TextPaste (MWContext *context, Widget text, XP_Bool quote_p)
|
|
{
|
|
struct fe_MWContext_cons *rest;
|
|
char *clip = 0;
|
|
int16 charset = CS_LATIN1;
|
|
INTL_CharSetInfo csi;
|
|
|
|
int32 internal = 0;
|
|
MWContext *con = NULL;
|
|
|
|
clip = xfe2_GetClipboardText(text, &internal);
|
|
|
|
if (internal) {
|
|
con = (MWContext *) internal;
|
|
csi = LO_GetDocumentCharacterSetInfo(con);
|
|
charset = INTL_GetCSIWinCSID(csi);
|
|
}
|
|
else {
|
|
charset = INTL_DefaultWinCharSetID(NULL);
|
|
}
|
|
|
|
#ifdef MOZ_MAIL_NEWS
|
|
if (clip && quote_p)
|
|
{
|
|
char *n = MSG_ConvertToQuotation (clip);
|
|
XP_ASSERT(n);
|
|
XP_FREE(clip);
|
|
clip = n;
|
|
if (!clip) return;
|
|
}
|
|
#endif
|
|
|
|
if (clip)
|
|
{
|
|
#ifdef DEBUG_rhess
|
|
fprintf(stderr, "xfe_TextPaste::[ insert ][ %d ]--[ %d ] [ %s ]\n",
|
|
charset, CS_LATIN1, clip);
|
|
#endif
|
|
fe_text_insert (text, clip, charset);
|
|
XP_FREE(clip);
|
|
}
|
|
else
|
|
XBell (XtDisplay (text), 0);
|
|
}
|
|
|
|
|
|
typedef enum { fe_Cut, fe_Copy, fe_Paste, fe_PasteQuoted } fe_CCP;
|
|
|
|
static void
|
|
fe_ccp (MWContext *context, XEvent *event, fe_CCP ccp)
|
|
{
|
|
Widget focus = XmGetFocusWidget (CONTEXT_WIDGET (context));
|
|
char *clip = NULL;
|
|
Time time = (event && (event->type == KeyPress ||
|
|
event->type == KeyRelease)
|
|
? event->xkey.time :
|
|
event && (event->type == ButtonPress ||
|
|
event->type == ButtonRelease)
|
|
? event->xbutton.time :
|
|
XtLastTimestampProcessed (XtDisplay(CONTEXT_WIDGET (context))));
|
|
|
|
if ((CONTEXT_WIDGET(context) != fe_selection_widget
|
|
|| (ccp != fe_Cut && ccp != fe_Copy))
|
|
&& focus && (XmIsText (focus) || XmIsTextField (focus)))
|
|
switch (ccp)
|
|
{
|
|
case fe_Cut:
|
|
xfe_TextCopy (context, focus, TRUE);
|
|
break;
|
|
case fe_Copy:
|
|
xfe_TextCopy (context, focus, FALSE);
|
|
break;
|
|
case fe_Paste:
|
|
xfe_TextPaste (context, focus, FALSE);
|
|
break;
|
|
case fe_PasteQuoted:
|
|
xfe_TextPaste (context, focus, TRUE);
|
|
break;
|
|
default:
|
|
XP_ASSERT(0);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (ccp == fe_Copy) {
|
|
fe_OwnSelection(context, time, True);
|
|
}
|
|
else {
|
|
XBell (XtDisplay (CONTEXT_WIDGET (context)), 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
fe_cut_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
|
{
|
|
MWContext *context = (MWContext *) closure;
|
|
XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
|
|
fe_UserActivity (context);
|
|
|
|
fe_ccp (context, (cb ? cb->event : 0), fe_Cut);
|
|
}
|
|
|
|
void
|
|
fe_copy_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
|
{
|
|
MWContext *context = (MWContext *) closure;
|
|
XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
|
|
fe_UserActivity (context);
|
|
|
|
fe_ccp (context, (cb ? cb->event : 0), fe_Copy);
|
|
}
|
|
|
|
void
|
|
fe_paste_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
|
{
|
|
MWContext *context = (MWContext *) closure;
|
|
XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
|
|
fe_UserActivity (context);
|
|
|
|
fe_ccp (context, (cb ? cb->event : 0), fe_Paste);
|
|
}
|
|
|
|
void
|
|
fe_paste_quoted_cb (Widget widget, XtPointer closure, XtPointer call_data)
|
|
{
|
|
MWContext *context = (MWContext *) closure;
|
|
XmAnyCallbackStruct *cb = (XmAnyCallbackStruct *) call_data;
|
|
fe_UserActivity (context);
|
|
|
|
fe_ccp (context, (cb ? cb->event : 0), fe_PasteQuoted);
|
|
}
|