/* clipbrd.c - clipboard functions for Motif programs (cut/paste support) (C) A. Stochniol, 1991 - 1993 These functions are needed only for Motif 1.0. For Motif 1.1 and later I am using new standard clipboard functions (therefore this file is compiled conditionally; alternatively you may delete that file from the make specification) */ #include #include /* I have left the above declarations outside #if because some compilers complain about empty source files */ #if (XmVersion == 1000) /* conditional Motif 1.0 compilation **/ #include #include #include #include "clipbrd.h" #define AS_CLBOARD_FORMAT "STRING" extern Widget toplevel; /*------------------------------------------------------------- ** CopyStringToClipboard ** Copy the string str to the clipboard. ** Returns True when successful. ** ** Note for clipboard functions: those functions need display and window ** parameters and they are used to identify the clipboard owner. They should ** always be the same for one application. So to safeguard this we are using ** internally a top-level application shell obtained as a global variable (its ** name was assumed to be: "toplevel"). The display and the window are obtained ** using XtDisplay and XtWindow, respectively. ** */ #ifdef _NO_PROTO Boolean CopyStringToClipboard(str, time) char *str; Time time; #else /* _NO_PROTO */ Boolean CopyStringToClipboard(char *str, Time time) #endif { long item_id = 0; /* clipboard item id */ int data_id = 0; /* clipboard data id */ int status = 0; /* clipboard status */ int RETRY_COUNT = 1000; /* to avoid blocking infinitely if another client does not release the clipboard lock an upper bound for the re-tries is used */ char *clipboard_warning = "Warning: copy failed, clipboard locked !\n"; int retries; XmStringCharSet charset = (XmStringCharSet) XmSTRING_DEFAULT_CHARSET; /* use default */ XmString clip_label; /* using the clipboard facilities, copy the string str to the clipboard */ if (str != NULL) { clip_label = XmStringCreateLtoR ("AS_APPLICATION", charset); /* start copy to clipboard, and continue till a sucessful start copy is made */ retries = RETRY_COUNT; do { status = XmClipboardStartCopy (XtDisplay(toplevel), XtWindow(toplevel), clip_label, time, toplevel, NULL, &item_id); } while (status != ClipboardSuccess && (retries-- >= 0)); if(retries <= 0) { fprintf(stderr, clipboard_warning); return(False); } /* move the data to the clipboard, and continue till a sucessful copy is made */ retries = RETRY_COUNT; do { status = XmClipboardCopy (XtDisplay(toplevel), XtWindow(toplevel), item_id, AS_CLBOARD_FORMAT, str, (long)strlen(str)+1, 0, &data_id); } while (status != ClipboardSuccess && (retries-- >= 0)); if(retries <= 0) { fprintf(stderr, clipboard_warning); return(False); } /* end the copy to the clipboard and continue till a sucessful end copy is made */ retries = RETRY_COUNT; do { status = XmClipboardEndCopy (XtDisplay(toplevel), XtWindow(toplevel), item_id); } while (status != ClipboardSuccess && (retries-- >= 0)); if(retries <= 0) { fprintf(stderr, clipboard_warning); return(False); } return(True); /* copy was successful */ } else return(False); } /* CopyStringToClipboard */ /*------------------------------------------------------------- ** GetStringFromClipboard ** get string from the clipboard (returns string when successful) */ char * GetStringFromClipboard() { /* retrieve the current data from the clipboard */ char *buffer=NULL; int status = 0; /* clipboard status */ int RETRY_COUNT = 1000; /* to avoid blocking infinitely if another client does not release the clipboard lock an upper bound for the re-tries is used */ char *clipboard_warning = "Warning: paste failed, clipboard locked !\n"; int retries; unsigned long length; /* length of buffer */ unsigned long outlength = 0; /* length of bytes copied */ int private_id = 0; /* id of item on clipboard */ /* find the length of the paste item, continue till the length is found */ retries = RETRY_COUNT; do { status = XmClipboardInquireLength(XtDisplay(toplevel), XtWindow(toplevel), AS_CLBOARD_FORMAT, &length); if (status == ClipboardNoData) { length = 0; break; } } while (status != ClipboardSuccess && (retries-- >= 0)); if(retries <= 0) { fprintf(stderr, clipboard_warning); return(NULL); } if (length == 0) { fprintf(stderr, "Warning: paste failed, no items to paste.\n"); return(NULL); } /* malloc to necessary space */ buffer = XtMalloc(length); status = XmClipboardRetrieve (XtDisplay(toplevel), XtWindow(toplevel), AS_CLBOARD_FORMAT, buffer, length, &outlength, &private_id); /* !!!!! Dialogs need to be added to indicate errors in pasting */ if (status != ClipboardSuccess) { fprintf(stderr, "Warning: paste failed, status = %d\n", status); return(NULL); } return(buffer); } /* GetStringFromClipboard */ /*------------------------------------------------------------- ** DeletePrimarySelection ** Deletes the primary selection. */ #ifdef _NO_PROTO void DeletePrimarySelection(text) Widget text; #else /* _NO_PROTO */ void DeletePrimarySelection(Widget text) #endif { XClientMessageEvent cm; /* send a client message to the text widget to delete the current selection */ cm.type = ClientMessage; cm.display = XtDisplay(text); cm.message_type = XmInternAtom(XtDisplay(text), "KILL_SELECTION", FALSE); cm.window = XtWindow(text); cm.format = 32; cm.data.l[0] = XA_PRIMARY; XSendEvent(XtDisplay(text), cm.window, TRUE, NoEventMask, &cm); } /* DeletePrimarySelection */ /*------------------------------------------------------------- ** PasteItemFromClipboard ** paste item from the clipboard to the current cursor location */ #ifdef _NO_PROTO void PasteItemFromClipboard(text) Widget text; #else /* _NO_PROTO */ void PasteItemFromClipboard(Widget text) #endif { /* retrieve the current data from the clipboard and paste it at the current cursor position */ char *buffer; /* temporary text buffer */ XmTextPosition cursorPos; /* text cursor position */ Arg al[10]; /* arg list */ /* get the string from the clipboard; if successful paste it */ if( (buffer = GetStringFromClipboard()) != NULL ) { /* get cursor position for pasting */ XtSetArg(al[0], XmNcursorPosition, &cursorPos); XtGetValues(text, al, 1); /* add new text */ XmTextReplace(text, cursorPos, cursorPos, buffer); /****8.04.92* free the memory allocated (inside GetString...) for temporary text buffer */ XtFree(buffer); } } /* PasteItemFromClipboard */ /* end of conditional Motif 1.0 compilation */ #endif