1048 lines
37 KiB
Plaintext
1048 lines
37 KiB
Plaintext
_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\
|
|
Ctrl<Key>Right: forward-word() \n\
|
|
Ctrl<Key>Left: backward-word() \n\
|
|
Ctrl<Key>a: beginning-of-line() \n\
|
|
Ctrl<Key>e: end-of-line() \n\
|
|
Ctrl<Key>a, Ctrl<Key>a: beginning-of-file() \n\
|
|
Ctrl<Key>e, Ctrl<Key>e: 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 <X11/Intrinsic.h>
|
|
#include <X11/StringDefs.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/Text.h>
|
|
#include <Xm/RowColumn.h>
|
|
#include <Xm/PushBG.h>
|
|
#include <Xm/FileSB.h>
|
|
#include <Xm/SelectioB.h>
|
|
#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 <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
#include <X11/StringDefs.h>
|
|
#include <X11/Intrinsic.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/Text.h>
|
|
#include <Xm/FileSB.h>
|
|
|
|
#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 <X11/StringDefs.h>
|
|
#include <X11/Intrinsic.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/Text.h>
|
|
#include <Xm/CutPaste.h>
|
|
|
|
/*~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
|
|
|
|
|