#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "textSel.h"
#include "textP.h"
#include "text.h"
#include "textDisp.h"
#include "textBuf.h"
#include "../util/misc.h"
#include "../util/nedit_malloc.h"
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <Xm/Xm.h>
#include <Xm/CutPaste.h>
#include <Xm/Text.h>
#include <X11/Xatom.h>
#if XmVersion >=
1002
#include <Xm/PrimitiveP.h>
#endif
#ifdef HAVE_DEBUG_H
#include "../debug.h"
#endif
static Time selectionTime =
0;
#define N_SELECT_TARGETS 8
#define N_ATOMS 12
enum atomIndex {
A_TEXT,
A_TARGETS,
A_MULTIPLE,
A_TIMESTAMP,
A_INSERT_SELECTION,
A_DELETE,
A_CLIPBOARD,
A_INSERT_INFO,
A_ATOM_PAIR,
A_MOTIF_DESTINATION,
A_COMPOUND_TEXT,
A_UTF8_STRING};
enum insertResultFlags {
INSERT_WAITING,
UNSUCCESSFUL_INSERT,
SUCCESSFUL_INSERT};
enum selectNotifyActions {
UNSELECT_SECONDARY,
REMOVE_SECONDARY,
EXCHANGE_SECONDARY};
typedef struct {
int action;
XtIntervalId timeoutProcID;
Time timeStamp;
Widget widget;
char *actionText;
int length;
} selectNotifyInfo;
typedef struct {
char *utf8String;
char *string;
size_t utf8slen;
size_t slen;
int isColFlag;
int cbCount;
} stringSelection;
static void modifiedCB(
int pos,
int nInserted,
int nDeleted,
int nRestyled,
const char *deletedText,
void *cbArg);
static void sendSecondary(Widget w, Time time, Atom sel,
int action,
char *actionText,
int actionTextLen);
static void getSelectionCB(Widget w, XtPointer clientData, Atom *selType,
Atom *type, XtPointer value,
unsigned long *length,
int *format);
static void getInsertSelectionCB(Widget w, XtPointer clientData,Atom *selType,
Atom *type, XtPointer value,
unsigned long *length,
int *format);
static void getExchSelCB(Widget w, XtPointer clientData, Atom *selType,
Atom *type, XtPointer value,
unsigned long *length,
int *format);
static Boolean convertSelectionCB(Widget w, Atom *selType, Atom *target,
Atom *type, XtPointer *value,
unsigned long *length,
int *format);
static void loseSelectionCB(Widget w, Atom *selType);
static Boolean convertSecondaryCB(Widget w, Atom *selType, Atom *target,
Atom *type, XtPointer *value,
unsigned long *length,
int *format);
static void loseSecondaryCB(Widget w, Atom *selType);
static Boolean convertMotifDestCB(Widget w, Atom *selType, Atom *target,
Atom *type, XtPointer *value,
unsigned long *length,
int *format);
static void loseMotifDestCB(Widget w, Atom *selType);
static void selectNotifyEH(Widget w, XtPointer data, XEvent *event,
Boolean *continueDispatch);
static void selectNotifyTimerProc(XtPointer clientData, XtIntervalId *id);
static Atom getAtom(Display *display,
int atomNum);
void HandleXSelections(Widget w)
{
int i;
textBuffer *buf = ((TextWidget)w)->text.textD->buffer;
for (i=
0; i<buf->nModifyProcs; i++) {
if (buf->modifyProcs[i] == modifiedCB) {
BufRemoveModifyCB(buf, modifiedCB, buf->cbArgs[i]);
break;
}
}
BufAddModifyCB(((TextWidget)w)->text.textD->buffer, modifiedCB, w);
}
void StopHandlingXSelections(Widget w)
{
int i;
textBuffer *buf = ((TextWidget)w)->text.textD->buffer;
for (i=
0; i<buf->nModifyProcs; i++) {
if (buf->modifyProcs[i] == modifiedCB && buf->cbArgs[i] == w) {
BufRemoveModifyCB(buf, modifiedCB, buf->cbArgs[i]);
return;
}
}
}
void CopyStringToClipboard(Widget w, Time time,
const char *text,
size_t length) {
long itemID =
0;
XmString s;
int stat;
int res;
if(!text || text[
0] ==
'\0')
{
return;
}
char *locale_text =
NULL;
if(!IsUtf8Locale()) {
locale_text = ConvertEncodingLen(text, length, GetLocaleEncoding(),
"UTF-8");
}
if (SpinClipboardLock(XtDisplay(w), XtWindow(w)) != ClipboardSuccess) {
if(locale_text) NEditFree(locale_text);
return;
}
s = XmStringCreateSimple(
"NEdit");
stat = SpinClipboardStartCopy(XtDisplay(w), XtWindow(w), s,
time, w,
NULL, &itemID);
XmStringFree(s);
if (stat != ClipboardSuccess) {
SpinClipboardUnlock(XtDisplay(w), XtWindow(w));
return;
}
res = SpinClipboardCopy(XtDisplay(w), XtWindow(w), itemID,
"UTF8_STRING",
(
char*)text, length,
0,
NULL);
if(res == ClipboardSuccess) {
int l_length = length;
const char *l_text = text;
if(locale_text) {
l_text = locale_text;
l_length = strlen(locale_text);
}
res = SpinClipboardCopy(XtDisplay(w), XtWindow(w), itemID,
"STRING",
(
char*)l_text, l_length,
0,
NULL);
}
if(locale_text) {
NEditFree(locale_text);
}
SpinClipboardEndCopy(XtDisplay(w), XtWindow(w), itemID);
SpinClipboardUnlock(XtDisplay(w), XtWindow(w));
}
void CopyToClipboard(Widget w, Time time)
{
char *text = BufGetSelectionText(((TextWidget)w)->text.textD->buffer);
size_t length = strlen(text);
BufUnsubstituteNullChars(text, ((TextWidget)w)->text.textD->buffer);
CopyStringToClipboard(w, time, text, length);
NEditFree(text);
}
void InsertPrimarySelection(Widget w, Time time,
int isColumnar)
{
stringSelection *sel = NEditMalloc(
sizeof(stringSelection));
sel->utf8String =
NULL;
sel->string =
NULL;
sel->utf8slen =
0;
sel->slen =
0;
sel->cbCount =
0;
sel->isColFlag = isColumnar;
Atom targets[
2] = {
XA_STRING, getAtom(XtDisplay(w),
A_UTF8_STRING)};
selectionTime = time;
XtGetSelectionValue(w,
XA_PRIMARY, targets[
1], getSelectionCB, sel, time);
XtGetSelectionValue(w,
XA_PRIMARY, targets[
0], getSelectionCB, sel, time);
}
void SendSecondarySelection(Widget w, Time time,
int removeAfter)
{
sendSecondary(w, time, getAtom(XtDisplay(w),
A_MOTIF_DESTINATION),
removeAfter ?
REMOVE_SECONDARY :
UNSELECT_SECONDARY,
NULL,
0);
}
void ExchangeSelections(Widget w, Time time)
{
if (!((TextWidget)w)->text.textD->buffer->secondary.selected)
return;
XtGetSelectionValue(w,
XA_PRIMARY,
XA_STRING, getExchSelCB,
NULL, time);
}
void MovePrimarySelection(Widget w, Time time,
int isColumnar)
{
stringSelection *sel = NEditMalloc(
sizeof(stringSelection));
sel->utf8String =
NULL;
sel->string =
NULL;
sel->cbCount =
0;
sel->isColFlag = isColumnar;
Atom targets[
3] = {
XA_STRING,
getAtom(XtDisplay(w),
A_UTF8_STRING),
getAtom(XtDisplay(w),
A_DELETE)};
void *data[
3] = { sel, sel, sel};
selectionTime = time;
XtGetSelectionValues(w,
XA_PRIMARY, targets,
3, getSelectionCB, data, time);
}
char* GetClipboard(Widget w) {
unsigned long length, retLength;
int res;
char *string;
char *type =
"UTF8_STRING";
long id =
0;
int convert =
FALSE;
res = SpinClipboardInquireLength(XtDisplay(w), XtWindow(w),
type, &length);
if(res != ClipboardSuccess || length ==
0) {
type =
"STRING";
res = SpinClipboardInquireLength(XtDisplay(w), XtWindow(w),
type, &length);
if(!IsUtf8Locale()) {
convert =
TRUE;
}
}
if (res != ClipboardSuccess || length ==
0) {
SpinClipboardUnlock(XtDisplay(w), XtWindow(w));
return NULL;
}
string = (
char*)NEditMalloc(length+
1);
if (SpinClipboardRetrieve(XtDisplay(w), XtWindow(w), type, string,
length, &retLength, &id) != ClipboardSuccess || retLength ==
0) {
NEditFree(string);
SpinClipboardUnlock(XtDisplay(w), XtWindow(w));
return NULL;
}
string[retLength] =
'\0';
if(convert) {
char *c_string = ConvertEncoding(string,
"UTF-8", GetLocaleEncoding());
if(c_string) {
NEditFree(string);
string = c_string;
retLength = strlen(c_string);
}
}
return string;
}
void InsertClipboard(Widget w,
int isColumnar)
{
unsigned long retLength;
textDisp *textD = ((TextWidget)w)->text.textD;
textBuffer *buf = ((TextWidget)w)->text.textD->buffer;
int cursorLineStart, column, cursorPos;
char *string = GetClipboard(w);
if(!string) {
return;
}
retLength = strlen(string);
if (!BufSubstituteNullChars(string, retLength, buf)) {
fprintf(stderr,
"Too much binary data, text not pasted\n");
NEditFree(string);
return;
}
if (isColumnar && !buf->primary.selected) {
cursorPos = TextDGetInsertPosition(textD);
cursorLineStart = BufStartOfLine(buf, cursorPos);
column = BufCountDispChars(buf, cursorLineStart, cursorPos);
if (((TextWidget)w)->text.overstrike) {
BufOverlayRect(buf, cursorLineStart, column, -
1, string,
NULL,
NULL);
}
else {
BufInsertCol(buf, column, cursorLineStart, string,
NULL,
NULL);
}
TextDSetInsertPosition(textD,
BufCountForwardDispChars(buf, cursorLineStart, column));
if (((TextWidget)w)->text.autoShowInsertPos)
TextDMakeInsertPosVisible(textD);
}
else
TextInsertAtCursor(w, string,
NULL, True,
((TextWidget)w)->text.autoWrapPastedText);
NEditFree(string);
}
void TakeMotifDestination(Widget w, Time time)
{
if (((TextWidget)w)->text.motifDestOwner || ((TextWidget)w)->text.readOnly)
return;
if (!XtOwnSelection(w, getAtom(XtDisplay(w),
A_MOTIF_DESTINATION), time,
convertMotifDestCB, loseMotifDestCB,
NULL)) {
return;
}
((TextWidget)w)->text.motifDestOwner = True;
}
static void modifiedCB(
int pos,
int nInserted,
int nDeleted,
int nRestyled,
const char *deletedText,
void *cbArg)
{
TextWidget w = (TextWidget)cbArg;
Time time = XtLastTimestampProcessed(XtDisplay((Widget)w));
int selected = w->text.textD->buffer->primary.selected;
int isOwner = w->text.selectionOwner;
if ((isOwner && selected) || (!isOwner && !selected))
return;
if (!XtOwnSelection((Widget)w,
XA_PRIMARY, time, convertSelectionCB,
loseSelectionCB,
NULL))
BufUnselect(w->text.textD->buffer);
else
w->text.selectionOwner = True;
}
static void sendSecondary(Widget w, Time time, Atom sel,
int action,
char *actionText,
int actionTextLen)
{
static Atom selInfoProp[
2] = {
XA_SECONDARY,
XA_STRING};
Display *disp = XtDisplay(w);
selectNotifyInfo *cbInfo;
XtAppContext context = XtWidgetToApplicationContext((Widget)w);
if (!XtOwnSelection(w,
XA_SECONDARY, time, convertSecondaryCB,
loseSecondaryCB,
NULL)) {
BufSecondaryUnselect(((TextWidget)w)->text.textD->buffer);
return;
}
XChangeProperty(disp, XtWindow(w), getAtom(disp,
A_INSERT_INFO),
getAtom(disp,
A_ATOM_PAIR),
32, PropModeReplace,
(
unsigned char *)selInfoProp,
2 );
XConvertSelection(XtDisplay(w), sel, getAtom(disp,
A_INSERT_SELECTION),
getAtom(disp,
A_INSERT_INFO), XtWindow(w), time);
cbInfo = (selectNotifyInfo *)NEditMalloc(
sizeof(selectNotifyInfo));
cbInfo->action = action;
cbInfo->timeStamp = time;
cbInfo->widget = (Widget)w;
cbInfo->actionText = actionText;
cbInfo->length = actionTextLen;
XtAddEventHandler(w,
0, True, selectNotifyEH, (XtPointer)cbInfo);
cbInfo->timeoutProcID = XtAppAddTimeOut(context,
XtAppGetSelectionTimeout(context),
selectNotifyTimerProc, (XtPointer)cbInfo);
}
static void selectionSetValue(
Widget w,
stringSelection *selection,
Atom selType,
Atom type,
XtPointer value,
unsigned long length,
int format)
{
selection->cbCount++;
Atom utf8 = getAtom(XtDisplay(w),
A_UTF8_STRING);
if(value && (type ==
XA_STRING || type == utf8) && format ==
8) {
char *string = NEditMalloc(length+
1);
memcpy(string, value, length);
string[length] =
'\0';
if(type ==
XA_STRING) {
selection->string = string;
selection->slen = length;
}
else {
selection->utf8String = string;
selection->utf8slen = length;
}
}
XtFree(value);
if(selection->cbCount ==
2) {
char *insertStr;
size_t insertStrLen;
if(selection->utf8String) {
insertStr = selection->utf8String;
insertStrLen = selection->utf8slen;
}
else {
insertStr = selection->string;
insertStrLen = selection->slen;
}
if(insertStr) {
textDisp *textD = ((TextWidget)w)->text.textD;
if (!BufSubstituteNullChars(insertStr, insertStrLen, textD->buffer)) {
fprintf(stderr,
"Too much binary data, giving up\n");
}
if (selection->isColFlag) {
int cursorPos = TextDGetInsertPosition(textD);
int cursorLineStart = BufStartOfLine(textD->buffer, cursorPos);
int row, column;
TextDXYToUnconstrainedPosition(textD, ((TextWidget)w)->text.btnDownX,
((TextWidget)w)->text.btnDownY, &row, &column);
BufInsertCol(textD->buffer, column, cursorLineStart, insertStr,
NULL,
NULL);
TextDSetInsertPosition(textD, textD->buffer->cursorPosHint);
}
else {
TextInsertAtCursor(w, insertStr,
NULL, False,
((TextWidget)w)->text.autoWrapPastedText);
}
}
if(selection->utf8String) {
NEditFree(selection->utf8String);
}
if(selection->string) {
NEditFree(selection->string);
}
NEditFree(selection);
}
}
static void getSelectionCB(Widget w, XtPointer clientData, Atom *selType,
Atom *type, XtPointer value,
unsigned long *length,
int *format)
{
selectionSetValue(w, clientData, *selType, *type, value, *length, *format);
}
static void getInsertSelectionCB(Widget w, XtPointer clientData,Atom *selType,
Atom *type, XtPointer value,
unsigned long *length,
int *format)
{
textBuffer *buf = ((TextWidget)w)->text.textD->buffer;
char *string;
int *resultFlag = (
int *)clientData;
if (*type !=
XA_STRING || *format !=
8 || value ==
NULL) {
NEditFree(value);
*resultFlag =
UNSUCCESSFUL_INSERT;
return;
}
string = (
char*)NEditMalloc(*length +
1);
memcpy(string, (
char *)value, *length);
string[*length] =
'\0';
if (!BufSubstituteNullChars(string, *length, buf)) {
fprintf(stderr,
"Too much binary data, giving up\n");
NEditFree(string);
NEditFree(value);
return;
}
TextInsertAtCursor(w, string,
NULL, True,
((TextWidget)w)->text.autoWrapPastedText);
NEditFree(string);
*resultFlag =
SUCCESSFUL_INSERT;
NEditFree(value);
}
static void getExchSelCB(Widget w, XtPointer clientData, Atom *selType,
Atom *type, XtPointer value,
unsigned long *length,
int *format)
{
if (*length ==
0 || value ==
NULL || *type !=
XA_STRING || *format !=
8) {
NEditFree(value);
XBell(XtDisplay(w),
0);
BufSecondaryUnselect(((TextWidget)w)->text.textD->buffer);
return;
}
sendSecondary(w, XtLastTimestampProcessed(XtDisplay(w)),
XA_PRIMARY,
EXCHANGE_SECONDARY, (
char *)value, *length);
}
static Boolean convertSelectionCB(Widget w, Atom *selType, Atom *target,
Atom *type, XtPointer *value,
unsigned long *length,
int *format)
{
XSelectionRequestEvent *event = XtGetSelectionRequest(w, *selType,
0);
textBuffer *buf = ((TextWidget)w)->text.textD->buffer;
Display *display = XtDisplay(w);
Atom *targets, dummyAtom;
unsigned long nItems, dummyULong;
Atom *reqAtoms;
int getFmt, result =
INSERT_WAITING;
XEvent nextEvent;
Atom utf8 = getAtom(display,
A_UTF8_STRING);
if (*target ==
XA_STRING || *target == getAtom(display,
A_TEXT) ||
*target == getAtom(display,
A_COMPOUND_TEXT) || *target == utf8) {
*type = *target == utf8 ? utf8 :
XA_STRING;
*value = (XtPointer)BufGetSelectionText(buf);
*length = strlen((
char *)*value);
*format =
8;
BufUnsubstituteNullChars(*value, buf);
return True;
}
if (*target == getAtom(display,
A_TARGETS)) {
targets = (Atom *)NEditMalloc(
sizeof(Atom) *
N_SELECT_TARGETS);
targets[
0] =
XA_STRING;
targets[
1] = utf8;
targets[
2] = getAtom(display,
A_TEXT);
targets[
3] = getAtom(display,
A_TARGETS);
targets[
4] = getAtom(display,
A_MULTIPLE);
targets[
5] = getAtom(display,
A_TIMESTAMP);
targets[
6] = getAtom(display,
A_INSERT_SELECTION);
targets[
7] = getAtom(display,
A_DELETE);
*type =
XA_ATOM;
*value = (XtPointer)targets;
*length =
N_SELECT_TARGETS;
*format =
32;
return True;
}
if (*target == getAtom(display,
A_INSERT_SELECTION)) {
if (((TextWidget)w)->text.readOnly)
return False;
if (XGetWindowProperty(event->display, event->requestor,
event->property,
0,
2, False, AnyPropertyType, &dummyAtom,
&getFmt, &nItems, &dummyULong,
(
unsigned char **)&reqAtoms) != Success ||
getFmt !=
32 || nItems !=
2)
return False;
if (reqAtoms[
1] !=
XA_STRING)
return False;
XtGetSelectionValue(w, reqAtoms[
0], reqAtoms[
1],
getInsertSelectionCB, &result, event->time);
XFree((
char *)reqAtoms);
while (result ==
INSERT_WAITING) {
XtAppNextEvent(XtWidgetToApplicationContext(w), &nextEvent);
XtDispatchEvent(&nextEvent);
}
*type = getAtom(display,
A_INSERT_SELECTION);
*format =
8;
*value =
NULL;
*length =
0;
return result ==
SUCCESSFUL_INSERT;
}
if (*target == getAtom(display,
A_DELETE)) {
BufRemoveSelected(buf);
*length =
0;
*format =
8;
*type = getAtom(display,
A_DELETE);
*value =
NULL;
return True;
}
return False;
}
static void loseSelectionCB(Widget w, Atom *selType)
{
TextWidget tw = (TextWidget)w;
selection *sel = &tw->text.textD->buffer->primary;
char zeroWidth = sel->rectangular ? sel->zeroWidth :
0;
tw->text.selectionOwner = False;
BufUnselect(tw->text.textD->buffer);
sel->zeroWidth = zeroWidth;
}
static Boolean convertSecondaryCB(Widget w, Atom *selType, Atom *target,
Atom *type, XtPointer *value,
unsigned long *length,
int *format)
{
textBuffer *buf = ((TextWidget)w)->text.textD->buffer;
if (*target !=
XA_STRING && *target != getAtom(XtDisplay(w),
A_TEXT))
return False;
*type =
XA_STRING;
*value = (XtPointer)BufGetSecSelectText(buf);
*length = strlen((
char *)*value);
*format =
8;
BufUnsubstituteNullChars(*value, buf);
return True;
}
static void loseSecondaryCB(Widget w, Atom *selType)
{
}
static Boolean convertMotifDestCB(Widget w, Atom *selType, Atom *target,
Atom *type, XtPointer *value,
unsigned long *length,
int *format)
{
XSelectionRequestEvent *event = XtGetSelectionRequest(w, *selType,
0);
Display *display = XtDisplay(w);
Atom *targets, dummyAtom;
unsigned long nItems, dummyULong;
Atom *reqAtoms;
int getFmt, result =
INSERT_WAITING;
XEvent nextEvent;
if (*target == getAtom(display,
A_TARGETS)) {
targets = (Atom *)NEditMalloc(
sizeof(Atom) *
3);
targets[
0] = getAtom(display,
A_TARGETS);
targets[
1] = getAtom(display,
A_TIMESTAMP);
targets[
2] = getAtom(display,
A_INSERT_SELECTION);
*type =
XA_ATOM;
*value = (XtPointer)targets;
*length =
3;
*format =
32;
return True;
}
if (*target == getAtom(display,
A_INSERT_SELECTION)) {
if (((TextWidget)w)->text.readOnly)
return False;
if (XGetWindowProperty(event->display, event->requestor,
event->property,
0,
2, False, AnyPropertyType, &dummyAtom,
&getFmt, &nItems, &dummyULong,
(
unsigned char **)&reqAtoms) != Success ||
getFmt !=
32 || nItems !=
2)
return False;
if (reqAtoms[
1] !=
XA_STRING)
return False;
XtGetSelectionValue(w, reqAtoms[
0], reqAtoms[
1],
getInsertSelectionCB, &result, event->time);
XFree((
char *)reqAtoms);
while (result ==
INSERT_WAITING) {
XtAppNextEvent(XtWidgetToApplicationContext(w), &nextEvent);
XtDispatchEvent(&nextEvent);
}
*type = getAtom(display,
A_INSERT_SELECTION);
*format =
8;
*value =
NULL;
*length =
0;
return result ==
SUCCESSFUL_INSERT;
}
return False;
}
static void loseMotifDestCB(Widget w, Atom *selType)
{
((TextWidget)w)->text.motifDestOwner = False;
if (((TextWidget)w)->text.textD->cursorStyle ==
CARET_CURSOR)
TextDSetCursorStyle(((TextWidget)w)->text.textD,
DIM_CURSOR);
}
static void selectNotifyEH(Widget w, XtPointer data, XEvent *event,
Boolean *continueDispatch)
{
textBuffer *buf = ((TextWidget)w)->text.textD->buffer;
XSelectionEvent *e = (XSelectionEvent *)event;
selectNotifyInfo *cbInfo = (selectNotifyInfo *)data;
int selStart, selEnd;
char *string;
if (event->type != SelectionNotify || e->time != cbInfo->timeStamp)
return;
XtRemoveEventHandler(w,
0, True, selectNotifyEH, data);
XtRemoveTimeOut(cbInfo->timeoutProcID);
if (e->property == None) {
XBell(XtDisplay(w),
0);
BufSecondaryUnselect(buf);
XtDisownSelection(w,
XA_SECONDARY, e->time);
NEditFree(cbInfo->actionText);
NEditFree(cbInfo);
return;
}
if (cbInfo->action ==
REMOVE_SECONDARY) {
BufRemoveSecSelect(buf);
}
else if (cbInfo->action ==
EXCHANGE_SECONDARY) {
string = (
char*)NEditMalloc(cbInfo->length +
1);
memcpy(string, cbInfo->actionText, cbInfo->length);
string[cbInfo->length] =
'\0';
selStart = buf->secondary.start;
if (BufSubstituteNullChars(string, cbInfo->length, buf)) {
BufReplaceSecSelect(buf, string);
if (buf->secondary.rectangular) {
TextDSetInsertPosition(((TextWidget)w)->text.textD,
buf->cursorPosHint);
}
else {
selEnd = selStart + cbInfo->length;
BufSelect(buf, selStart, selEnd);
TextDSetInsertPosition(((TextWidget)w)->text.textD, selEnd);
}
}
else
fprintf(stderr,
"Too much binary data\n");
NEditFree(string);
}
BufSecondaryUnselect(buf);
XtDisownSelection(w,
XA_SECONDARY, e->time);
NEditFree(cbInfo->actionText);
NEditFree(cbInfo);
}
static void selectNotifyTimerProc(XtPointer clientData, XtIntervalId *id)
{
selectNotifyInfo *cbInfo = (selectNotifyInfo *)clientData;
textBuffer *buf = ((TextWidget)cbInfo->widget)->text.textD->buffer;
fprintf(stderr,
"NEdit: timeout on selection request\n");
XtRemoveEventHandler(cbInfo->widget,
0, True, selectNotifyEH, cbInfo);
BufSecondaryUnselect(buf);
XtDisownSelection(cbInfo->widget,
XA_SECONDARY, cbInfo->timeStamp);
NEditFree(cbInfo->actionText);
NEditFree(cbInfo);
}
static Atom getAtom(Display *display,
int atomNum)
{
static Atom atomList[
N_ATOMS] = {
0};
static char *atomNames[
N_ATOMS] = {
"TEXT",
"TARGETS",
"MULTIPLE",
"TIMESTAMP",
"INSERT_SELECTION",
"DELETE",
"CLIPBOARD",
"INSERT_INFO",
"ATOM_PAIR",
"MOTIF_DESTINATION",
"COMPOUND_TEXT",
"UTF8_STRING"};
if (atomList[atomNum] ==
0)
atomList[atomNum] = XInternAtom(display, atomNames[atomNum], False);
return atomList[atomNum];
}