_INTRINSICS OF THE X TOOLKIT_ by Todd Lainhart [LISTING ONE] ! ! Resource specifications for simple text editor ! *textEdit.rows: 24 *textEdit.columns: 80 *textEdit.resizeWidth: False *textEdit.resizeHeight: False *textEdit.translations: #override \n\ CtrlRight: forward-word() \n\ CtrlLeft: backward-word() \n\ Ctrla: beginning-of-line() \n\ Ctrle: end-of-line() \n\ Ctrla, Ctrla: beginning-of-file() \n\ Ctrle, Ctrle: end-of-file() [LISTING TWO] /*~PKG************************************************************************* * Package Name: xm_main.c * Synopsis: Implements a simple text editor using the Motif toolkit. * Features Supported: Not much. * References: Xt Programming and Apps by Doug Young. * Xm Programming Reference and Guide by OSF. * Xt Programming Reference and Guide by O'Reilly. * Usage: Bind this with a couple of other support objs. * Known Bugs/Deficiencies: * Modification History: 11/01/90 twl original */ /****************************************************************************** * Header files included. */ #include #include #include #include #include #include #include #include #include "xm_callbacks.h" /****************************************************************************** * Constants and variables local to this package. */ /* These widgets are the popup menu items, externalized here so that * functions within this package can have access (for the setting/unsetting * of selectability. */ static Widget CopyMenuItem; static Widget CutMenuItem; static Widget PasteMenuItem; static Widget PasteFileMenuItem; static Widget WriteFileMenuItem; static void ExitApp(); /* The actions table for declaring new translations. */ static XtActionsRec actionTable[] = { { "exit", ExitApp }, }; /****************************************************************************** * Procedure: ExitApp * Synopsis: Action procedure for exiting application * Assumptions: None. * Features Supported: * Known Bugs/Deficiencies: We're not interested in checking state of the editor before going down. * Regardless of the circumstances, down we go. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static void ExitApp( Widget parent, XEvent *event, String *actionArgs, Cardinal argNdx ) { XtCloseDisplay( XtDisplay( parent ) ); exit( 0 ); } /****************************************************************************** * Procedure: DisplayTextEditMenu * Synopsis: Event handler to display the text body popup menu. * Assumptions: The parent is a Text Widget. * Features Supported: * Known Bugs/Deficiencies: External resources should be considered. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static void DisplayTextEditMenu( textBody, popupMenu, xEvent ) Widget textBody; /* Owner of the event handler */ Widget popupMenu; /* Data passed by the registering procedure */ XEvent *xEvent; /* Passed to all event handlers */ { Arg argList[25]; /* Resource argument list */ int argNdx; /* Index into resource list */ int menuButton; /* MENU button assigned to popup */ char *selectedText; /* The text selected for the widget invoking /* We're assuming that the owning widget of this event handler is of * type XmCText. If not, get out. */ if ( !XmIsText( textBody ) ) { printf( "DisplayTextEditMenu: Not Text\n" ); exit( 1 ); } /* We're also assuming that the the data passed by the event handler * is a popup menu widget. If not, get out. */ if ( !XmIsRowColumn( popupMenu ) ) { printf( "DisplayTextEditMenu: Not RowColumn\n" ); exit( 1 ); } /* Check to see if the button that caused this event is the menu * button. If not, get out. */ argNdx = 0; XtSetArg( argList[argNdx], XmNwhichButton, &menuButton ); argNdx++; XtGetValues( popupMenu, argList, argNdx ); if ( xEvent->xbutton.button != menuButton ) { return; } /* We need to set the selectability of the menu items here. For most menu * items, that involves checking to see if any text has been selected. */ selectedText = XmTextGetSelection( textBody ); /* The Copy menu item. */ if ( selectedText != NULL ) { XtSetSensitive( CopyMenuItem, TRUE ); } else { XtSetSensitive( CopyMenuItem, FALSE ); } /* The Cut menu item. */ if ( selectedText != NULL ) { XtSetSensitive( CutMenuItem, TRUE ); } else { XtSetSensitive( CutMenuItem, FALSE ); } /* The Paste menu item. See if there's something in the clipboard, * and set sensitivity accordingly. */ if ( selectedText == NULL ) { if ( ClipboardIsEmpty( textBody ) ) { XtSetSensitive( PasteMenuItem, FALSE ); } else { XtSetSensitive( PasteMenuItem, TRUE ); } } else { XtSetSensitive( PasteMenuItem, FALSE ); } /* The PasteFile menu item. Let's say that we can only paste from a file * if no text has been selected. */ if ( selectedText == NULL ) { XtSetSensitive( PasteFileMenuItem, TRUE ); } else { XtSetSensitive( PasteFileMenuItem, FALSE ); } /* The WriteFile menu item. */ if ( selectedText != NULL ) { XtSetSensitive( WriteFileMenuItem, TRUE ); } else { XtSetSensitive( WriteFileMenuItem, FALSE ); } XmMenuPosition( popupMenu, xEvent ); XtManageChild( popupMenu ); } /*~PROC************************************************************************ * Procedure: CreateTextEditPopup * Synopsis: Creates the Popup menu displayed over the text edit area. * Callbacks are also defined here. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: External resources should perhaps be considered. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static Widget CreateTextEditPopup( Widget parent ) { Widget textPopup; /* Created popup returned */ Arg argList[25]; /* Resource argument list */ int argNdx; /* Index into argument list */ Widget fileDialog; /* File selection dialog box */ Widget promptDialog; /* Text input prompt */ /* We assume a text edit widget as parent. If not, get out. */ if ( !XmIsText( parent ) ) { printf( "CreateTextEditPopup: Not Text\n" ); exit( 1 ); } /* Create the popup menu. We'll tell Xt to manage it at the time that * it needs to be displayed. */ textPopup = XmCreatePopupMenu( parent, "textPopup", NULL, 0 ); /* Add the menu items (buttons). */ argNdx = 0; XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Copy", XmSTRING_DEFAULT_CHARSET ) ); argNdx++; CopyMenuItem = XmCreatePushButtonGadget( textPopup, "copyMenuItem", argList, argNdx ); XtManageChild( CopyMenuItem ); argNdx = 0; XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Cut", XmSTRING_DEFAULT_CHARSET ) ); argNdx++; CutMenuItem = XmCreatePushButtonGadget( textPopup, "cutMenuItem", argList, argNdx ); XtManageChild( CutMenuItem ); argNdx = 0; XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Paste", XmSTRING_DEFAULT_CHARSET ) ); argNdx++; PasteMenuItem = XmCreatePushButtonGadget( textPopup, "pasteMenuItem", argList, argNdx ); XtManageChild( PasteMenuItem ); argNdx = 0; XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Paste From File...", XmSTRING_DEFAULT_CHARSET ) ); argNdx++; PasteFileMenuItem = XmCreatePushButtonGadget( textPopup, "pasteFileMenuItem", argList, argNdx ); XtManageChild( PasteFileMenuItem ); argNdx = 0; XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Write To File...", XmSTRING_DEFAULT_CHARSET ) ); argNdx++; WriteFileMenuItem = XmCreatePushButtonGadget( textPopup, "writeFileMenuItem", argList, argNdx ); XtManageChild( WriteFileMenuItem ); /* Add the File Selection dialog, to be invoked by PasteFileMenu button. */ argNdx = 0; XtSetArg( argList[argNdx], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL ); argNdx++; XtSetArg( argList[argNdx], XmNdialogTitle, XmStringCreateLtoR( "Paste From File", XmSTRING_DEFAULT_CHARSET ) ); argNdx++; XtSetArg( argList[argNdx], XmNselectionLabelString, XmStringCreateLtoR( "Directory", XmSTRING_DEFAULT_CHARSET ) ); argNdx++ ; XtSetArg( argList[argNdx], XmNautoUnmanage, True ); argNdx++; fileDialog = XmCreateFileSelectionDialog( parent, "fileDialog", argList, argNdx ); /* Add a selection dialog, to be invoked by the WriteFileMenu button. */ argNdx = 0; XtSetArg( argList[argNdx], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL ); argNdx++; XtSetArg( argList[argNdx], XmNdialogTitle, XmStringCreateLtoR( "Write To File", XmSTRING_DEFAULT_CHARSET ) ); argNdx++; XtSetArg( argList[argNdx], XmNselectionLabelString, XmStringCreateLtoR( "File", XmSTRING_DEFAULT_CHARSET ) ); argNdx++ ; XtSetArg( argList[argNdx], XmNtextColumns, 32 ); argNdx++; promptDialog = XmCreatePromptDialog( parent, "promptDialog", argList, argNdx ); /* Add callbacks for the menu buttons. */ XtAddCallback( CopyMenuItem, XmNactivateCallback, CopyCB, parent ); XtAddCallback( CutMenuItem, XmNactivateCallback, CutCB, parent ); XtAddCallback( PasteMenuItem, XmNactivateCallback, PasteCB, parent ); XtAddCallback( PasteFileMenuItem, XmNactivateCallback, PasteFileCB, fileDialog ); XtAddCallback( WriteFileMenuItem, XmNactivateCallback, WriteFileCB, promptDialog ); /* Add callbacks for the dialog box buttons. */ XtAddCallback( fileDialog, XmNokCallback, FileDialogOKCB, parent ); XtAddCallback( fileDialog, XmNcancelCallback, UnMapDialogCB, fileDialog ); XtAddCallback( fileDialog, XmNhelpCallback, UnMapDialogCB, fileDialog ); XtAddCallback( promptDialog, XmNokCallback, PromptDialogOKCB, parent ); XtAddCallback( promptDialog, XmNcancelCallback, UnMapDialogCB, promptDialog ); XtAddCallback( promptDialog, XmNhelpCallback, UnMapDialogCB, promptDialog ); return( textPopup ); } /*~PROC************************************************************************ * Procedure: main * Synopsis: Initializes the Intrinsics, creates all of the higher-level widgets * necessary to make the application happen, and enters the main loop. * Assumptions: * Usage: Command-line arguments are ignored (for now). * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main( int argc, char *argv[] ) { Widget topShell; /* Top level shell created by the Intrinsics */ Widget textEdit; /* Main edit Text Widget */ Widget textMenu; /* Popup menu associated with the text editor */ Arg argList[25]; /* Resource argument list */ int argNdx; /* Index into resource list */ /* Initialize the Intrinsics. */ topShell = XtInitialize( argv[0], "Editor", NULL, 0, &argc, argv ); /* Create the scrolled Text Widget */ argNdx = 0; XtSetArg(argList[argNdx], XmNscrollVertical, True ); argNdx++; XtSetArg(argList[argNdx], XmNscrollHorizontal, True ); argNdx++; XtSetArg(argList[argNdx], XmNeditMode, XmMULTI_LINE_EDIT ); argNdx++; textEdit = XmCreateScrolledText( topShell, "textEdit", argList, argNdx ); XtManageChild( textEdit ); /* Create the context-sensitive popup menu for this Widget */ textMenu = CreateTextEditPopup( textEdit ); /* Add the event handler to the Text Widget, invoking the popup menu. */ XtAddEventHandler( textEdit, ButtonPressMask, FALSE, DisplayTextEditMenu, textMenu ); /* Register new actions to be associated with our app. */ XtAddActions( actionTable, XtNumber( actionTable ) ); /* Map the editor, and enter the event dispatch loop. */ XtRealizeWidget( topShell ); XtMainLoop(); } [LISTING THREE] /*~PKG************************************************************************* * Package Name: xm_callbacks.c * Synopsis: Common text manipulation callbacks. * Features Supported: * References: Xt Programming and Apps by Doug Young. * Xm Programming Reference and Guide by OSF. * Xt Programming Reference and Guide by O'Reilly. * Usage: Include "xm_callbacks.h" * Known Bugs/Deficiencies: * Modification History: 11/01/90 twl original */ /*~HDR************************************************************************* * Header files included. */ #include #include #include #include #include #include #include #include #include #include #include "xm_clipboard.h" /*~PROC************************************************************************ * Procedure: MapDialogCB * Synopsis: Maps the referenced dialog box. * Assumptions: The parent has been realized. * The widget passed to this callback is a subclass of dialogshell. * Features Supported: * Known Bugs/Deficiencies: * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void MapDialogCB( source, dialog, callbackData ) Widget source; /* Source of the callback */ Widget dialog; /* Data passed to the callback by the register procedure */ XmAnyCallbackStruct *callbackData; /* Generic data passed to all callback procedures */ { XtManageChild( dialog ); } /*~PROC************************************************************************ * Procedure: UnMapDialogCB * Synopsis: Unmaps the referenced dialog box. * Assumptions: The parent has been realized. * The widget passed to this callback is a subclass of dialogshell. * Features Supported: * Known Bugs/Deficiencies: * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void UnMapDialogCB( source, dialog, callbackData ) Widget source; /* Source of the callback */ Widget dialog; /* Data passed to the callback by the register procedure */ XmAnyCallbackStruct *callbackData; /* Generic data passed to all callback procedures */ { XtUnmanageChild( dialog ); } /*~PROC************************************************************************ * Procedure: CutCB * Synopsis: Callback procedure for cutting text from the referenced text * widget to the clipboard. Callback for the "Cut" menu item. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: Cursor should change to a wait state. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void CutCB( source, textID, callbackData ) Widget source; /* Source of the callback */ Widget textID; /* Data passed to the callback by the register procedure */ XmAnyCallbackStruct *callbackData; /* Generic data passed to all callback procedures */ { XClientMessageEvent clientMessage; /* X client message structure */ Time timestamp; /* X Event time */ int clipStat; /* Return status of clipboard call */ /* Get the event timestamp */ timestamp = ((XButtonEvent *)callbackData->event)->time; /* Copy the selected text to the clipboard. */ clipStat = CopyToClipboard( textID, timestamp ); /* Delete the selected text from the Text Widget */ if ( clipStat == True ) { clientMessage.type = ClientMessage; clientMessage.display = XtDisplay( textID ); clientMessage.message_type = XmInternAtom( XtDisplay( textID ), "KILL_SELECTION", FALSE ); clientMessage.window = XtWindow( textID ); clientMessage.format = 32; clientMessage.data.l[0] = XA_PRIMARY; XSendEvent( XtDisplay( textID ), clientMessage.window, TRUE, NoEventMask, &clientMessage ); } } /*~PROC************************************************************************ * Procedure: CopyCB * Synopsis: Callback procedure for copying text from the referenced text * widget to the clipboard. Callback for the "Copy" menu item. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: The cursor should change into a waiting cursor. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void CopyCB( source, textID, clientData ) Widget source; /* Source of the callback */ Widget textID; /* Data passed to the callback as defined by the registering procedure */ XmAnyCallbackStruct *clientData; /* Generic data passed to all callback procedures */ { Time eventTime; /* Time stamp for the clipboard */ /* Get the time the event occurred */ eventTime = ((XButtonEvent *)clientData->event)->time; /* Copy the selected text (if any) to the clipboard */ CopyToClipboard( textID, eventTime ); } /*~PROC************************************************************************ * Procedure: PasteCB * Synopsis: Callback procedure for pasting text from the referenced text widget * to the clipboard. Callback for the "Paste" menu item. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: External resources should be considered. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void PasteCB( source, textID, callbackData ) Widget source; /* Owner of the callback */ Widget textID; /* Data passed to the callback routine by */ /* the registering procedure */ XmAnyCallbackStruct *callbackData; /* Data passed to all callbacks */ { char *pasteText; /* That text which is to be retrieved from the paste buffer */ Time eventTime; /* Time stamp for the clipboard routines */ Arg argList[25]; /* Resource retrieval array */ int argNdx; /* Index into resource array */ XmTextPosition textCursorPos; /* Position of Text Widget insertion cursor */ /* Get the time the event occurred (for transaction timestamping) */ eventTime = ((XButtonEvent *)callbackData->event)->time; /* Get the latest text from the clipboard. */ pasteText = RetrieveFromClipboard( textID, eventTime ); /* See if we have a hit. If not, get out. */ if ( pasteText == NULL ) { return; } /* Get the insertion point of the text Widget */ argNdx = 0; XtSetArg( argList[argNdx], XmNcursorPosition, &textCursorPos ); argNdx++; XtGetValues( textID, argList, argNdx ); /* ...and insert the text */ XmTextReplace( textID, textCursorPos, textCursorPos, pasteText ); XtFree( pasteText ); } /*~PROC************************************************************************ * Procedure: PasteFileCB * Synopsis: Callback procedure for the Paste from File... menu item. * Currently, just the dialog box is displayed. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: External resources should be considered. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void PasteFileCB( source, dialog, callbackData ) Widget source; /* Owner of the callback */ Widget dialog; /* Data passed to the callback routine by */ /* the registering procedure */ XmAnyCallbackStruct *callbackData; /* Data passed to all callbacks */ { XtManageChild( dialog ); } /*~PROC************************************************************************ * Procedure: WriteFileCB * Synopsis: Callback procedure for the Write to File... menu item. * Currently, just the dialog box is displayed. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: External resources should be considered. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void WriteFileCB( source, dialog, callbackData ) Widget source; /* Owner of the callback */ Widget dialog; /* Data passed to the callback routine by */ /* the registering procedure */ XmAnyCallbackStruct *callbackData; /* Data passed to all callbacks */ { XtManageChild( dialog ); } /*~PROC************************************************************************ * Procedure: FileDialogOKCB * Synopsis: Callback procedure for the activation of the OK button on the file selection * dialog box. * Assumptions: The file to be pasted is ASCII. * The source of the callback is a file selection dialog box. * Features Supported: * Known Bugs/Deficiencies: External resources should be considered. * The file to be pasted is not checked for type (should be ASCII). * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void FileDialogOKCB( source, textID, callbackData ) Widget source; /* Owner of the callback */ Widget textID; /* Data passed to the callback routine */ XmFileSelectionBoxCallbackStruct *callbackData; /* Data passed to all file selection callbacks */ { char *pasteFile; /* Filename returned from the dialog */ int pasteFileLen; /* Length of referenced file */ char *pasteText; /* Contents of reference file */ struct stat statBuf; /* Buffer for stat() results */ FILE *fileDesc; /* UNIX file descriptor */ Arg argList[25]; /* Resource retrieval array */ int argNdx; /* Index into resource array */ XmTextPosition textCursorPos; /* Position of Text Widget insertion cursor */ if ( !XmIsText( textID ) ) { printf( "FileDialogOKCB: Not Text Widget\n" ); exit( 1 ); } if ( !XmIsFileSelectionBox( source ) ) { printf( "FileDialogOKCB: Not dialog box\n" ); exit( 1 ); } /* Get the filename */ XmStringGetLtoR( callbackData->value, XmSTRING_DEFAULT_CHARSET, &pasteFile ); /* Open the file */ fileDesc = fopen( pasteFile, "r" ); if ( fileDesc == NULL ) { /* Display an error prompt, and get out */ printf( "FileDialogOKCB: File not available for read\n" ); exit( 1 ); } /* Get its length, read the contents, and close it up. */ stat( pasteFile, &statBuf ); pasteFileLen = statBuf.st_size; pasteText = XtMalloc( pasteFileLen ); fread( pasteText, sizeof( char ), pasteFileLen, fileDesc ); fclose( fileDesc ); /* Paste the contents at the current insertion point. */ argNdx = 0; XtSetArg( argList[argNdx], XmNcursorPosition, &textCursorPos ); argNdx++; XtGetValues( textID, argList, argNdx ); XmTextReplace( textID, textCursorPos, textCursorPos, pasteText ); /* Free up resources */ XtFree( pasteFile ); XtFree( pasteText ); /* Bring down the dialog box */ XtUnmanageChild( source ); } /*~PROC************************************************************************ * Procedure: PromptDialogOKCB * Synopsis: Callback procedure for the activation of the OK button on the prompt * dialog box. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: External resources should be considered. * Minimal error checking on file creation and write. * Modification History: 08/20/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void PromptDialogOKCB( source, textID, callbackData ) Widget source; /* Owner of the callback */ Widget textID; /* Data passed to the callback routine */ XmSelectionBoxCallbackStruct *callbackData; /* Data passed to all selection callbacks */ { char *writeFile; /* Filename returned from the dialog */ int writeFileLen; /* Length of referenced file */ char *writeText; /* Contents of reference file */ struct stat statBuf; /* Buffer for stat() results */ FILE *fileDesc; /* UNIX file descriptor */ char *selectedText; /* That text which is marked as selected in textID */ if ( !XmIsText( textID ) ) { printf( "PromptDialogOKCB: Not Text Widget\n" ); exit( 1 ); } /* If no text selected, we can leave. */ selectedText = XmTextGetSelection( textID ); if ( selectedText == NULL ) { return; } /* Get the filename */ XmStringGetLtoR( callbackData->value, XmSTRING_DEFAULT_CHARSET, &writeFile ); /* Open the file */ fileDesc = fopen( writeFile, "w" ); if ( fileDesc == NULL ) { /* Display an error, and get out */ printf( "PromptDialogOKCB: Error on file creation\n" ); exit( 1 ); } /* Write the file, and close it up */ fwrite( selectedText, sizeof( char ), strlen( selectedText ), fileDesc ); if ( fclose( fileDesc ) != NULL ) { /* Display an error, and get out */ printf( "PromptDialogOKCB: Error on file close\n" ); exit( 1 ); } } [LISTING FOUR] /*~PKG************************************************************************* * Package Name: xm_clipboard.c * Synopsis: Implements clipboard store and retrieve procedures. * Features Supported: * References: Xt Programming and Apps by Doug Young. * Xm Programming Reference and Guide by OSF. * Xt Programming Reference and Guide by O'Reilly. * Usage: Include "xm_clipboard.h" * Known Bugs/Deficiencies: * Modification History: 11/01/90 twl original */ /*~HDR************************************************************************* * Header files included. */ #include #include #include #include #include /*~LOC*DATA******************************************************************** * Constants and variables local to this package. */ #define CBLABEL "TextEdit" /*~PROC************************************************************************ * Procedure: CopyToClipboard * Synopsis: Retrieve selected text from reference textID, and copy it to the system * clipboard. Returns True if successful, False if not. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: Text only supported. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int CopyToClipboard( Widget textID, Time timestamp ) { char *selectedText; /* That text which is marked as selected in textID */ int clipStat; /* Return value from XmClipboard routines */ XmString clipLabel; /* The label used to identify the clipboard string */ long clipID, copyID; /* The handles used in identifying clipboard transactions */ /* Sanity check. */ if ( !XmIsText( textID ) ) { printf( "CopyToClipboard: Not Text Widget\n" ); exit( 1 ); } /* If no text selected, we can leave. */ selectedText = XmTextGetSelection( textID ); if ( selectedText == NULL ) { return( False ); } /* Create the label that appears in the clipboard. */ clipLabel = XmStringCreateLtoR( CBLABEL, XmSTRING_DEFAULT_CHARSET ); /* Poll the clipboard, asking for permission to start. */ clipStat = ClipboardLocked; while( clipStat == ClipboardLocked ) { clipStat = XmClipboardStartCopy( XtDisplay( textID ), XtWindow( textID ), clipLabel, timestamp, textID, NULL, &clipID ); } /* Copy the data to the clipboard until successful. */ clipStat = ClipboardLocked; while( clipStat == ClipboardLocked ) { clipStat = XmClipboardCopy( XtDisplay( textID ), XtWindow( textID ), clipID, XtRString, selectedText, (long)strlen( selectedText ), 0 ©ID ); } /* End the transaction... */ clipStat = ClipboardLocked; while( clipStat == ClipboardLocked ) { clipStat = XmClipboardEndCopy( XtDisplay( textID ), XtWindow( textID ), clipID ); } /* ... cleanup, and leave. */ XtFree( selectedText ); XmStringFree( clipLabel ); return( True ); } /*~PROC************************************************************************ * Procedure: RetrieveFromClipboard * Synopsis: Return text from the clipboard. * Assumptions: The caller assumes responsibility for freeing returned string. * Features Supported: * Known Bugs/Deficiencies: Text only supported. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ char * RetrieveFromClipboard( Widget textID, Time timestamp ) { char *pasteText; /* That text which is to be retrieved from the paste buffer */ int pasteTextLen; /* Length of text in clipboard */ int clipStat; /* Return value from XmClipboard routines */ XmString clipLabel; /* The label used to identify the clipboard string */ long clipID, privateID; /* The handles used in identifying clipboard transactions */ long outlen; /* Length of data retrieved from clipboard */ /* Check to be sure that we have a text Widget */ if ( !XmIsText( textID ) ) { printf( "RetrieveFromClipboard: Widget not Text\n" ); exit( 1 ); } /* Start our clipboard transaction */ clipStat = ClipboardLocked; while( clipStat == ClipboardLocked ) { clipStat = XmClipboardStartRetrieve( XtDisplay( textID ), XtWindow( textID ), timestamp ); } /* Get the length of the clipboard contents */ clipStat = ClipboardLocked; pasteTextLen = 0; while( clipStat == ClipboardLocked ) { clipStat = XmClipboardInquireLength( XtDisplay( textID ), XtWindow( textID ), XmRString, &pasteTextLen ); if ( clipStat == ClipboardNoData ) { return( NULL ); } } /* Retrieve the data (allocating a string buffer) */ pasteText = XtMalloc( pasteTextLen + 1 ); clipStat = ClipboardLocked; while( clipStat == ClipboardLocked ) { clipStat = XmClipboardRetrieve( XtDisplay( textID ), XtWindow( textID ), XmRString, pasteText, pasteTextLen, &outlen, &privateID ); } /* End the clipboard session... */ clipStat = ClipboardLocked; while( clipStat == ClipboardLocked ) { clipStat = XmClipboardEndRetrieve( XtDisplay( textID ), XtWindow( textID ) ); } /* ... and return the clipboard contents. */ return( pasteText ); } /*~PROC************************************************************************ * Procedure: ClipboardIsEmpty * Synopsis: Returns FALSE, if no items in the clipboard. * Assumptions: * Features Supported: * Known Bugs/Deficiencies: Text only supported. Returns False (no data) if clipboard is locked. * Modification History: 11/01/90 twl original * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int ClipboardIsEmpty( Widget w ) { int clipStat; /* Clipboard status value */ int textLength; /* Length of text in clipboard */ clipStat = XmClipboardInquireLength( XtDisplay( w ), XtWindow( w ), XmRString, &textLength ); if ( clipStat == ClipboardSuccess ) { return( False ); } else { return( True ); } } [LISTING FIVE] #ifndef XM_CALLBACKS_H #define XM_CALLBACKS_H /***************************************************************************** * Include File Name: xm_callbacks.h * Contents: Interface to the callbacks package. * This include file is dependent on the following include file(s): * None. * Modification History: 11/01/90 twl original */ /*~EXP*PROC******************************************************************** * Procedures and functions exported by this package. */ extern void MapDialogCB( Widget source, Widget dialog, XmAnyCallbackStruct *callbackData ); extern void UnMapDialogCB( Widget source, Widget dialog, XmAnyCallbackStruct *callbackData ); extern void CutCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData ); extern void CopyCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData ); extern void PasteCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData ); extern void PasteFileCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData ); extern void WriteFileCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData ); extern void FileDialogOKCB( Widget source, Widget textID, XmFileSelectionBoxCallbackStruct *callbackData ); extern void PromptDialogOKCB( Widget source, Widget textID, XmSelectionBoxCallbackStruct *callbackData ); #endif [LISTING SIX] #ifndef XM_CLIPBOARD_H #define XM_CLIPBOARD_H /***************************************************************************** * * Include File Name: xm_clipboard.h * * Contents: * Interface to the Clipboard package. * * This include file is dependent on the following include file(s): * None. * * Modification History: * 11/01/90 twl original */ /*~EXP*PROC******************************************************************** * * Procedures and functions exported by this package. */ extern int CopyToClipboard( Widget textID, Time timestamp ); extern char * RetrieveFromClipboard( Widget textID, Time timestamp ); extern int ClipboardIsEmpty( Widget w ); #endif [LISTING SEVEN] # # Makefile to build textedit # # # Macros # CC=/bin/cc DEBUG=-g INCLUDE_DIRS=-I /usr/include/Xm -I /usr/include/X11 SYS_DEFS=$(SYS_T) $(RUN_T) -DSYSV CC_SWITCHES= -c $(SYS_DEFS) $(INCLUDE_DIRS) $(DEBUG) LD=/bin/ld LIBDIRS=-L/usr/X11/lib LIBS=-lXm -lXtm -lXaw -lX11 LD_SWITCHES=$(LIBDIRS) $(LIBS) # # Inference rules # .SUFFIXES: .c .o .ln .c.o: $(CC) $(CC_SWITCHES) $< OBJS=\ xm_main.o\ xm_clipboard.o\ xm_callbacks.o # # Targets # all: textedit textedit: $(OBJS) $(LD) -o $@ $(OBJS) $(LD_SWITCHES) xm_main.o: xm_callbacks.h xm_callbacks.o: xm_clipboard.h #------------------------- # Misc targets #------------------------- clean: -rm *.bak *.o lint: lint $(INCLUDE_DIRS) -DSYSV *.c