home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 02 / xwindow.asc < prev   
Text File  |  1990-12-26  |  38KB  |  1,048 lines

  1. _INTRINSICS OF THE X TOOLKIT_
  2. by Todd Lainhart
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. !
  8. ! Resource specifications for simple text editor
  9. !
  10. *textEdit.rows: 24
  11. *textEdit.columns:  80
  12. *textEdit.resizeWidth:  False
  13. *textEdit.resizeHeight: False
  14. *textEdit.translations: #override \n\
  15.                         Ctrl<Key>Right: forward-word()  \n\
  16.                         Ctrl<Key>Left:  backward-word() \n\
  17.                         Ctrl<Key>a:     beginning-of-line() \n\
  18.                         Ctrl<Key>e:     end-of-line() \n\
  19.                         Ctrl<Key>a, Ctrl<Key>a:  beginning-of-file() \n\
  20.                         Ctrl<Key>e, Ctrl<Key>e:  end-of-file()
  21.  
  22.  
  23.  
  24. [LISTING TWO]
  25.  
  26.  
  27. /*~PKG*************************************************************************
  28.  *  Package Name: xm_main.c
  29.  *  Synopsis: Implements a simple text editor using the Motif toolkit.
  30.  *  Features Supported: Not much.
  31.  *  References: Xt Programming and Apps by Doug Young.
  32.  *  Xm Programming Reference and Guide by OSF.
  33.  *  Xt Programming Reference and Guide by O'Reilly.
  34.  *  Usage: Bind this with a couple of other support objs.
  35.  *  Known Bugs/Deficiencies:
  36.  *  Modification History: 11/01/90    twl  original
  37.  */
  38.  
  39. /******************************************************************************
  40.  *  Header files included. */
  41. #include <X11/Intrinsic.h>
  42. #include <X11/StringDefs.h>
  43. #include <Xm/Xm.h>
  44. #include <Xm/Text.h> 
  45. #include <Xm/RowColumn.h>
  46. #include <Xm/PushBG.h>
  47. #include <Xm/FileSB.h>
  48. #include <Xm/SelectioB.h>
  49. #include "xm_callbacks.h"
  50.       
  51. /******************************************************************************
  52.  *  Constants and variables local to this package. */
  53.    
  54. /* These widgets are the popup menu items, externalized here so that
  55.  * functions within this package can have access (for the setting/unsetting
  56.  * of selectability.  */
  57. static Widget CopyMenuItem;
  58. static Widget CutMenuItem;
  59. static Widget PasteMenuItem;
  60. static Widget PasteFileMenuItem;
  61. static Widget WriteFileMenuItem;
  62.  
  63. static void   ExitApp();
  64.                    
  65. /* The actions table for declaring new translations. */
  66. static
  67. XtActionsRec actionTable[] = 
  68. {
  69.     { "exit", ExitApp },
  70. };
  71.  
  72. /******************************************************************************
  73.  *  Procedure:  ExitApp
  74.  *  Synopsis: Action procedure for exiting application
  75.  *  Assumptions: None.
  76.  *  Features Supported:
  77.  *  Known Bugs/Deficiencies: We're not interested in checking state of the editor before going down.
  78.  *      Regardless of the circumstances, down we go.
  79.  *  Modification History: 11/01/90  twl     original
  80.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  81. static void
  82. ExitApp( Widget parent, XEvent *event, String *actionArgs, Cardinal argNdx )
  83. {
  84.  
  85.     XtCloseDisplay( XtDisplay( parent ) );
  86.     exit( 0 );
  87. }
  88.  
  89. /******************************************************************************
  90.  *  Procedure:  DisplayTextEditMenu
  91.  *  Synopsis: Event handler to display the text body popup menu.
  92.  *  Assumptions:  The parent is a Text Widget.
  93.  *  Features Supported:
  94.  *  Known Bugs/Deficiencies: External resources should be considered.
  95.  *  Modification History: 11/01/90  twl     original
  96.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  97. static void
  98. DisplayTextEditMenu( textBody, popupMenu, xEvent ) 
  99.   
  100.     Widget  textBody;           /* Owner of the event handler */
  101.     Widget  popupMenu;          /* Data passed by the registering procedure */
  102.     XEvent *xEvent;             /* Passed to all event handlers */
  103. {
  104.   
  105.     Arg     argList[25];        /* Resource argument list */
  106.     int     argNdx;             /* Index into resource list */
  107.  
  108.     int     menuButton;         /* MENU button assigned to popup */
  109.     char   *selectedText;       /* The text selected for the widget invoking
  110.     
  111.                    
  112.     /* We're assuming that the owning widget of this event handler is of 
  113.      * type XmCText. If not, get out. */
  114.     if ( !XmIsText( textBody ) )
  115.     {
  116.         printf( "DisplayTextEditMenu: Not Text\n" ); 
  117.         exit( 1 );
  118.     }
  119.  
  120.     /* We're also assuming that the the data passed by the event handler
  121.      * is a popup menu widget.  If not, get out. */
  122.     if ( !XmIsRowColumn( popupMenu ) )
  123.     {
  124.         printf( "DisplayTextEditMenu: Not RowColumn\n" );
  125.         exit( 1 );
  126.     }
  127.    
  128.     /* Check to see if the button that caused this event is the menu 
  129.      * button.  If not, get out. */ 
  130.     argNdx = 0;
  131.     XtSetArg( argList[argNdx], XmNwhichButton, &menuButton ); argNdx++;
  132.     XtGetValues( popupMenu, argList, argNdx ); 
  133.     if ( xEvent->xbutton.button != menuButton )
  134.     {
  135.         return;
  136.     } 
  137.     
  138.     /* We need to set the selectability of the menu items here. For most menu 
  139.      * items, that involves checking to see if any text has been selected. */
  140.     selectedText = XmTextGetSelection( textBody );
  141.    
  142.     /* The Copy menu item. */
  143.     if ( selectedText != NULL )
  144.     {
  145.         XtSetSensitive( CopyMenuItem, TRUE );
  146.     }
  147.     else
  148.     {
  149.         XtSetSensitive( CopyMenuItem, FALSE );
  150.     }
  151.        
  152.     /* The Cut menu item. */
  153.     if ( selectedText != NULL )
  154.     {      
  155.         XtSetSensitive( CutMenuItem, TRUE );
  156.     }
  157.     else
  158.     {
  159.         XtSetSensitive( CutMenuItem, FALSE );
  160.     }
  161.        
  162.     /* The Paste menu item.  See if there's something in the clipboard, 
  163.      * and set sensitivity accordingly. */
  164.     if ( selectedText == NULL )
  165.     {                            
  166.         if ( ClipboardIsEmpty( textBody ) )
  167.         {
  168.             XtSetSensitive( PasteMenuItem, FALSE );
  169.         }
  170.         else
  171.         {
  172.             XtSetSensitive( PasteMenuItem, TRUE );
  173.         }
  174.     }
  175.     else
  176.     {
  177.         XtSetSensitive( PasteMenuItem, FALSE );
  178.     }
  179.      
  180.     /* The PasteFile menu item.  Let's say that we can only paste from a file 
  181.      *  if no text has been selected. */
  182.     if ( selectedText == NULL )
  183.     {                            
  184.         XtSetSensitive( PasteFileMenuItem, TRUE );
  185.     }
  186.     else
  187.     {
  188.         XtSetSensitive( PasteFileMenuItem, FALSE );
  189.     }
  190.      
  191.     /* The WriteFile menu item. */
  192.     if ( selectedText != NULL )
  193.     {      
  194.         XtSetSensitive( WriteFileMenuItem, TRUE );
  195.     }
  196.     else
  197.     {
  198.         XtSetSensitive( WriteFileMenuItem, FALSE );
  199.     } 
  200.  
  201.     XmMenuPosition( popupMenu, xEvent );
  202.     XtManageChild( popupMenu );
  203.  
  204. }
  205.  
  206. /*~PROC************************************************************************
  207.  *  Procedure: CreateTextEditPopup
  208.  *  Synopsis: Creates the Popup menu displayed over the text edit area.
  209.  *      Callbacks are also defined here.
  210.  *  Assumptions: 
  211.  *  Features Supported:
  212.  *  Known Bugs/Deficiencies: External resources should perhaps be considered.
  213.  *  Modification History: 11/01/90  twl     original
  214.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  215. static Widget
  216. CreateTextEditPopup( Widget parent )
  217. {
  218.  
  219.     Widget  textPopup;      /* Created popup returned */
  220.     Arg     argList[25];    /* Resource argument list */
  221.     int     argNdx;         /* Index into argument list */ 
  222.  
  223.     Widget  fileDialog;     /* File selection dialog box */
  224.     Widget  promptDialog;   /* Text input prompt */
  225.        
  226.     /* We assume a text edit widget as parent.  If not, get out. */
  227.     if ( !XmIsText( parent ) )
  228.     {
  229.         printf( "CreateTextEditPopup: Not Text\n" );
  230.         exit( 1 );
  231.     }
  232.  
  233.     /* Create the popup menu.  We'll tell Xt to manage it at the time that 
  234.      * it needs to be displayed. */
  235.     textPopup = XmCreatePopupMenu( parent, "textPopup", NULL, 0 ); 
  236.  
  237.     /* Add the menu items (buttons). */  
  238.     argNdx = 0;
  239.     XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Copy", XmSTRING_DEFAULT_CHARSET ) ); argNdx++;
  240.     CopyMenuItem = XmCreatePushButtonGadget( textPopup, "copyMenuItem", argList, argNdx );
  241.     XtManageChild( CopyMenuItem );
  242.  
  243.     argNdx = 0;
  244.     XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Cut", XmSTRING_DEFAULT_CHARSET ) ); argNdx++;
  245.     CutMenuItem = XmCreatePushButtonGadget( textPopup, "cutMenuItem", argList, argNdx );
  246.     XtManageChild( CutMenuItem );
  247.  
  248.     argNdx = 0;
  249.     XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Paste", XmSTRING_DEFAULT_CHARSET ) ); argNdx++;
  250.     PasteMenuItem = XmCreatePushButtonGadget( textPopup, "pasteMenuItem", argList, argNdx );
  251.     XtManageChild( PasteMenuItem );
  252.  
  253.     argNdx = 0;
  254.     XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Paste From File...", XmSTRING_DEFAULT_CHARSET ) ); argNdx++;
  255.     PasteFileMenuItem = XmCreatePushButtonGadget( textPopup, "pasteFileMenuItem", argList, argNdx );
  256.     XtManageChild( PasteFileMenuItem );
  257.       
  258.     argNdx = 0;
  259.     XtSetArg( argList[argNdx], XmNlabelString, XmStringCreateLtoR( "Write To File...", XmSTRING_DEFAULT_CHARSET ) ); argNdx++;
  260.     WriteFileMenuItem = XmCreatePushButtonGadget( textPopup, "writeFileMenuItem", argList, argNdx );
  261.     XtManageChild( WriteFileMenuItem );
  262.                         
  263.     /* Add the File Selection dialog, to be invoked by PasteFileMenu button. */  
  264.     argNdx = 0;
  265.     XtSetArg( argList[argNdx], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL ); argNdx++;
  266.     XtSetArg( argList[argNdx], XmNdialogTitle, XmStringCreateLtoR( "Paste From File", XmSTRING_DEFAULT_CHARSET ) ); argNdx++;
  267.     XtSetArg( argList[argNdx], XmNselectionLabelString, XmStringCreateLtoR( "Directory", XmSTRING_DEFAULT_CHARSET ) ); argNdx++ ;
  268.     XtSetArg( argList[argNdx], XmNautoUnmanage, True ); argNdx++;
  269.     fileDialog = XmCreateFileSelectionDialog( parent, "fileDialog", argList, argNdx );
  270.  
  271.     /* Add a selection dialog, to be invoked by the WriteFileMenu button. */ 
  272.     argNdx = 0;
  273.     XtSetArg( argList[argNdx], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL ); argNdx++;
  274.     XtSetArg( argList[argNdx], XmNdialogTitle, XmStringCreateLtoR( "Write To File", XmSTRING_DEFAULT_CHARSET ) ); argNdx++;
  275.     XtSetArg( argList[argNdx], XmNselectionLabelString, XmStringCreateLtoR( "File", XmSTRING_DEFAULT_CHARSET ) ); argNdx++ ;
  276.     XtSetArg( argList[argNdx], XmNtextColumns, 32 ); argNdx++;
  277.     promptDialog = XmCreatePromptDialog( parent, "promptDialog", argList, argNdx );
  278.  
  279.     /* Add callbacks for the menu buttons. */
  280.     XtAddCallback( CopyMenuItem,      XmNactivateCallback, CopyCB,      parent );
  281.     XtAddCallback( CutMenuItem,       XmNactivateCallback, CutCB,       parent );
  282.     XtAddCallback( PasteMenuItem,     XmNactivateCallback, PasteCB,     parent );
  283.     XtAddCallback( PasteFileMenuItem, XmNactivateCallback, PasteFileCB, fileDialog );
  284.     XtAddCallback( WriteFileMenuItem, XmNactivateCallback, WriteFileCB, promptDialog );
  285.  
  286.     /* Add callbacks for the dialog box buttons. */
  287.     XtAddCallback( fileDialog,   XmNokCallback,     FileDialogOKCB,   parent ); 
  288.     XtAddCallback( fileDialog,   XmNcancelCallback, UnMapDialogCB,    fileDialog );
  289.     XtAddCallback( fileDialog,   XmNhelpCallback,   UnMapDialogCB,    fileDialog );
  290.     XtAddCallback( promptDialog, XmNokCallback,     PromptDialogOKCB, parent );
  291.     XtAddCallback( promptDialog, XmNcancelCallback, UnMapDialogCB,    promptDialog );
  292.     XtAddCallback( promptDialog, XmNhelpCallback,   UnMapDialogCB,    promptDialog );
  293.  
  294.     return( textPopup );
  295.  
  296. }
  297.  
  298. /*~PROC************************************************************************
  299.  *  Procedure: main
  300.  *  Synopsis: Initializes the Intrinsics, creates all of the higher-level widgets
  301.  *  necessary to make the application happen, and enters the main loop.
  302.  *  Assumptions:
  303.  *  Usage: Command-line arguments are ignored (for now).
  304.  *  Modification History: 11/01/90  twl     original
  305.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  306. void
  307. main( int argc, char *argv[] )
  308. {
  309.  
  310.     Widget  topShell;         /* Top level shell created by the Intrinsics */
  311.     Widget  textEdit;         /* Main edit Text Widget */
  312.     Widget  textMenu;         /* Popup menu associated with the text editor */
  313.                                       
  314.     Arg     argList[25];        /* Resource argument list */
  315.     int     argNdx;             /* Index into resource list */
  316.  
  317.     /* Initialize the Intrinsics. */
  318.     topShell = XtInitialize( argv[0], "Editor", NULL, 0, &argc, argv );
  319.     
  320.     /* Create the scrolled Text Widget */
  321.     argNdx = 0;
  322.     XtSetArg(argList[argNdx], XmNscrollVertical,   True );              argNdx++;
  323.     XtSetArg(argList[argNdx], XmNscrollHorizontal, True );              argNdx++;
  324.     XtSetArg(argList[argNdx], XmNeditMode,         XmMULTI_LINE_EDIT ); argNdx++;
  325.  
  326.     textEdit = XmCreateScrolledText( topShell, "textEdit", argList, argNdx );
  327.     XtManageChild( textEdit );
  328.                  
  329.     /* Create the context-sensitive popup menu for this Widget */
  330.     textMenu = CreateTextEditPopup( textEdit ); 
  331.  
  332.     /* Add the event handler to the Text Widget, invoking the popup menu. */
  333.     XtAddEventHandler( textEdit, ButtonPressMask, FALSE, DisplayTextEditMenu, textMenu );
  334.      
  335.     /* Register new actions to be associated with our app. */
  336.     XtAddActions( actionTable, XtNumber( actionTable ) );
  337.  
  338.     /* Map the editor, and enter the event dispatch loop. */
  339.     XtRealizeWidget( topShell );
  340.     XtMainLoop();
  341.  
  342. }
  343.  
  344.  
  345. [LISTING THREE]
  346.  
  347. /*~PKG*************************************************************************
  348.  *  Package Name: xm_callbacks.c
  349.  *  Synopsis: Common text manipulation callbacks.
  350.  *  Features Supported:
  351.  *  References: Xt Programming and Apps by Doug Young.
  352.  *          Xm Programming Reference and Guide by OSF.
  353.  *          Xt Programming Reference and Guide by O'Reilly.
  354.  *  Usage: Include "xm_callbacks.h"
  355.  *  Known Bugs/Deficiencies:
  356.  *  Modification History: 11/01/90    twl  original
  357.  */
  358.  
  359. /*~HDR*************************************************************************
  360.  *  Header files included.
  361.  */ 
  362. #include <stdio.h>
  363. #include <fcntl.h>
  364. #include <sys/types.h>
  365. #include <sys/stat.h>
  366.  
  367. #include <X11/Xatom.h>
  368. #include <X11/StringDefs.h>
  369. #include <X11/Intrinsic.h>
  370. #include <Xm/Xm.h>
  371. #include <Xm/Text.h>
  372. #include <Xm/FileSB.h> 
  373.  
  374. #include "xm_clipboard.h"
  375.  
  376. /*~PROC************************************************************************
  377.  *  Procedure:  MapDialogCB
  378.  *  Synopsis: Maps the referenced dialog box.
  379.  *  Assumptions: The parent has been realized.
  380.  *      The widget passed to this callback is a subclass of dialogshell.
  381.  *  Features Supported:
  382.  *  Known Bugs/Deficiencies:
  383.  *  Modification History: 11/01/90  twl     original
  384.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  385. void
  386. MapDialogCB( source, dialog, callbackData )
  387.     
  388.     Widget source;                      /* Source of the callback */
  389.     Widget dialog;                      /* Data passed to the callback by the register procedure */
  390.     XmAnyCallbackStruct *callbackData;  /* Generic data passed to all callback procedures */
  391. {  
  392.  
  393.     XtManageChild( dialog );
  394.  
  395. }
  396.  
  397. /*~PROC************************************************************************
  398.  *  Procedure:  UnMapDialogCB
  399.  *  Synopsis: Unmaps the referenced dialog box.
  400.  *  Assumptions:  The parent has been realized.
  401.  *      The widget passed to this callback is a subclass of dialogshell.
  402.  *  Features Supported:
  403.  *  Known Bugs/Deficiencies:
  404.  *  Modification History: 11/01/90  twl     original
  405.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  406. void
  407. UnMapDialogCB( source, dialog, callbackData )
  408.     
  409.     Widget source;                      /* Source of the callback */
  410.     Widget dialog;                      /* Data passed to the callback by the register procedure */
  411.     XmAnyCallbackStruct *callbackData;  /* Generic data passed to all callback procedures */
  412. {  
  413.  
  414.     XtUnmanageChild( dialog );
  415.  
  416. }
  417.  
  418. /*~PROC************************************************************************
  419.  *  Procedure:  CutCB
  420.  *  Synopsis: Callback procedure for cutting text from the referenced text 
  421.  *  widget to the clipboard.  Callback for the "Cut" menu item.
  422.  *  Assumptions: 
  423.  *  Features Supported:
  424.  *  Known Bugs/Deficiencies: Cursor should change to a wait state.
  425.  *  Modification History: 11/01/90  twl     original
  426.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  427. void
  428. CutCB( source, textID, callbackData )
  429.     
  430.     Widget source;                      /* Source of the callback */
  431.     Widget textID;                      /* Data passed to the callback by the register procedure */
  432.     XmAnyCallbackStruct *callbackData;  /* Generic data passed to all callback procedures */
  433.   
  434.     XClientMessageEvent clientMessage;  /* X client message structure */
  435.     Time                timestamp;      /* X Event time */
  436.     int                 clipStat;       /* Return status of clipboard call */
  437.  
  438.     /* Get the event timestamp */ 
  439.     timestamp = ((XButtonEvent *)callbackData->event)->time;
  440.  
  441.     /* Copy the selected text to the clipboard. */
  442.     clipStat = CopyToClipboard( textID, timestamp );
  443.  
  444.     /* Delete the selected text from the Text Widget */ 
  445.     if ( clipStat == True )
  446.     {
  447.         clientMessage.type         = ClientMessage;
  448.         clientMessage.display      = XtDisplay( textID );
  449.         clientMessage.message_type = XmInternAtom( XtDisplay( textID ), "KILL_SELECTION", FALSE );
  450.         clientMessage.window       = XtWindow( textID );
  451.         clientMessage.format       = 32;
  452.         clientMessage.data.l[0]    = XA_PRIMARY;
  453.         XSendEvent( XtDisplay( textID ), clientMessage.window, TRUE, NoEventMask, &clientMessage ); 
  454.     }
  455.  
  456.  
  457. /*~PROC************************************************************************
  458.  *  Procedure:  CopyCB
  459.  *  Synopsis: Callback procedure for copying text from the referenced text 
  460.  *  widget to the clipboard.  Callback for the "Copy" menu item.
  461.  *  Assumptions: 
  462.  *  Features Supported:
  463.  *  Known Bugs/Deficiencies: The cursor should change into a waiting cursor.
  464.  *  Modification History: 11/01/90  twl     original
  465.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  466. void
  467. CopyCB( source, textID, clientData ) 
  468.  
  469.     Widget source;                      /* Source of the callback */
  470.     Widget textID;                      /* Data passed to the callback as defined by the registering procedure */
  471.     XmAnyCallbackStruct *clientData;    /* Generic data passed to all callback procedures */
  472.  
  473. {
  474.     Time     eventTime;                 /* Time stamp for the clipboard */
  475.          
  476.     /* Get the time the event occurred */
  477.     eventTime = ((XButtonEvent *)clientData->event)->time;
  478.  
  479.     /* Copy the selected text (if any) to the clipboard */
  480.     CopyToClipboard( textID, eventTime );
  481.  
  482. }
  483.  
  484. /*~PROC************************************************************************
  485.  *  Procedure:  PasteCB
  486.  *  Synopsis: Callback procedure for pasting text from the referenced text widget
  487.  *      to the clipboard.  Callback for the "Paste" menu item.
  488.  *  Assumptions: 
  489.  *  Features Supported:
  490.  *  Known Bugs/Deficiencies: External resources should be considered.
  491.  *  Modification History: 11/01/90  twl     original
  492.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  493. void
  494. PasteCB( source, textID, callbackData )
  495.  
  496.     Widget  source;                     /* Owner of the callback */
  497.     Widget  textID;                     /* Data passed to the callback routine by */
  498.                                         /* the registering procedure */
  499.     XmAnyCallbackStruct *callbackData;  /* Data passed to all callbacks */ 
  500.  
  501. {
  502.     char    *pasteText;         /* That text which is to be retrieved from the paste buffer */
  503.     Time     eventTime;         /* Time stamp for the clipboard routines */
  504.     Arg      argList[25];       /* Resource retrieval array */
  505.     int      argNdx;            /* Index into resource array */
  506.  
  507.     XmTextPosition textCursorPos; /* Position of Text Widget insertion cursor */
  508.       
  509.     /* Get the time the event occurred (for transaction timestamping) */
  510.     eventTime = ((XButtonEvent *)callbackData->event)->time;
  511.      
  512.     /* Get the latest text from the clipboard. */
  513.     pasteText = RetrieveFromClipboard( textID, eventTime );
  514.  
  515.     /* See if we have a hit.  If not, get out. */
  516.     if ( pasteText == NULL )
  517.     {
  518.         return;
  519.     }
  520.  
  521.     /* Get the insertion point of the text Widget */
  522.     argNdx = 0;
  523.     XtSetArg( argList[argNdx], XmNcursorPosition, &textCursorPos ); argNdx++;
  524.     XtGetValues( textID, argList, argNdx );
  525.  
  526.     /* ...and insert the text */
  527.     XmTextReplace( textID, textCursorPos, textCursorPos, pasteText );
  528.  
  529.     XtFree( pasteText );
  530.  
  531. }
  532.  
  533. /*~PROC************************************************************************
  534.  *  Procedure:  PasteFileCB
  535.  *  Synopsis: Callback procedure for the Paste from File... menu item.
  536.  *      Currently, just the dialog box is displayed.
  537.  *  Assumptions: 
  538.  *  Features Supported:
  539.  *  Known Bugs/Deficiencies: External resources should be considered.
  540.  *  Modification History: 11/01/90  twl     original
  541.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  542. void
  543. PasteFileCB( source, dialog, callbackData )
  544.  
  545.     Widget  source;                     /* Owner of the callback */
  546.     Widget  dialog;                     /* Data passed to the callback routine by */
  547.                                         /* the registering procedure */
  548.     XmAnyCallbackStruct *callbackData;  /* Data passed to all callbacks */ 
  549.  
  550.     XtManageChild( dialog );
  551. }    
  552.  
  553. /*~PROC************************************************************************
  554.  *  Procedure:  WriteFileCB
  555.  *  Synopsis: Callback procedure for the Write to File... menu item.
  556.  *      Currently, just the dialog box is displayed.
  557.  *  Assumptions: 
  558.  *  Features Supported:
  559.  *  Known Bugs/Deficiencies: External resources should be considered.
  560.  *  Modification History: 11/01/90  twl     original
  561.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  562. void
  563. WriteFileCB( source, dialog, callbackData )
  564.  
  565.     Widget  source;                     /* Owner of the callback */
  566.     Widget  dialog;                     /* Data passed to the callback routine by */
  567.                                         /* the registering procedure */
  568.     XmAnyCallbackStruct *callbackData;  /* Data passed to all callbacks */ 
  569.  
  570. {   
  571.     XtManageChild( dialog );
  572. }
  573.  
  574. /*~PROC************************************************************************
  575.  *  Procedure:  FileDialogOKCB
  576.  *  Synopsis: Callback procedure for the activation of the OK button on the file selection
  577.  *      dialog box.
  578.  *  Assumptions: The file to be pasted is ASCII.
  579.  *      The source of the callback is a file selection dialog box.
  580.  *  Features Supported:
  581.  *  Known Bugs/Deficiencies: External resources should be considered.
  582.  *      The file to be pasted is not checked for type (should be ASCII).
  583.  *  Modification History: 11/01/90  twl     original
  584.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  585. void
  586. FileDialogOKCB( source, textID, callbackData )
  587.  
  588.     Widget                            source;       /* Owner of the callback */
  589.     Widget                            textID;       /* Data passed to the callback routine */
  590.     XmFileSelectionBoxCallbackStruct *callbackData; /* Data passed to all file selection callbacks */
  591. {  
  592.     char       *pasteFile;              /* Filename returned from the dialog */
  593.     int         pasteFileLen;           /* Length of referenced file */
  594.     char       *pasteText;              /* Contents of reference file */
  595.     struct stat statBuf;                /* Buffer for stat() results */
  596.     FILE       *fileDesc;               /* UNIX file descriptor */
  597.    
  598.     Arg         argList[25];            /* Resource retrieval array */
  599.     int         argNdx;                 /* Index into resource array */
  600.  
  601.     XmTextPosition textCursorPos;    /* Position of Text Widget insertion cursor */
  602.  
  603.     if ( !XmIsText( textID ) )
  604.     {
  605.         printf( "FileDialogOKCB: Not Text Widget\n" );
  606.         exit( 1 );
  607.     }
  608.       
  609.     if ( !XmIsFileSelectionBox( source ) )
  610.     {
  611.         printf( "FileDialogOKCB: Not dialog box\n" );
  612.         exit( 1 );
  613.     }
  614.  
  615.     /* Get the filename */
  616.     XmStringGetLtoR( callbackData->value, XmSTRING_DEFAULT_CHARSET, &pasteFile );
  617.  
  618.     /* Open the file */ 
  619.     fileDesc = fopen( pasteFile, "r" );
  620.     if ( fileDesc == NULL )
  621.     {
  622.         /* Display an error prompt, and get out */
  623.         printf( "FileDialogOKCB: File not available for read\n" );
  624.         exit( 1 );
  625.     }
  626.  
  627.     /* Get its length, read the contents, and close it up. */
  628.     stat( pasteFile, &statBuf );
  629.     pasteFileLen = statBuf.st_size;
  630.     pasteText  = XtMalloc( pasteFileLen );
  631.     fread( pasteText, sizeof( char ), pasteFileLen, fileDesc );
  632.     fclose( fileDesc );
  633.  
  634.     /* Paste the contents at the current insertion point. */
  635.     argNdx = 0;
  636.     XtSetArg( argList[argNdx], XmNcursorPosition, &textCursorPos ); argNdx++;
  637.     XtGetValues( textID, argList, argNdx );
  638.     XmTextReplace( textID, textCursorPos, textCursorPos, pasteText ); 
  639.  
  640.     /* Free up resources */
  641.     XtFree( pasteFile );
  642.     XtFree( pasteText );
  643.     
  644.     /* Bring down the dialog box */
  645.     XtUnmanageChild( source );
  646.  
  647. }
  648.  
  649. /*~PROC************************************************************************
  650.  *  Procedure:  PromptDialogOKCB
  651.  *  Synopsis: Callback procedure for the activation of the OK button on the prompt
  652.  *      dialog box.
  653.  *  Assumptions: 
  654.  *  Features Supported:
  655.  *  Known Bugs/Deficiencies: External resources should be considered. 
  656.  *      Minimal error checking on file creation and write.
  657.  *  Modification History: 08/20/90  twl     original
  658.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
  659. void
  660. PromptDialogOKCB( source, textID, callbackData )
  661.  
  662.     Widget                        source;       /* Owner of the callback */
  663.     Widget                        textID;       /* Data passed to the callback routine */
  664.     XmSelectionBoxCallbackStruct *callbackData; /* Data passed to all selection callbacks */
  665. {
  666.           
  667.     char       *writeFile;              /* Filename returned from the dialog */
  668.     int         writeFileLen;           /* Length of referenced file */
  669.     char       *writeText;              /* Contents of reference file */
  670.     struct stat statBuf;                /* Buffer for stat() results */
  671.     FILE       *fileDesc;               /* UNIX file descriptor */
  672.          
  673.     char       *selectedText;           /* That text which is marked as selected in textID */
  674.  
  675.     if ( !XmIsText( textID ) )
  676.     {
  677.         printf( "PromptDialogOKCB: Not Text Widget\n" );
  678.         exit( 1 );
  679.     }
  680.        
  681.     /* If no text selected, we can leave. */
  682.     selectedText = XmTextGetSelection( textID );
  683.     if ( selectedText == NULL )
  684.     {
  685.         return;
  686.     }
  687.  
  688.     /* Get the filename */
  689.     XmStringGetLtoR( callbackData->value, XmSTRING_DEFAULT_CHARSET, &writeFile );
  690.         
  691.     /* Open the file */ 
  692.     fileDesc = fopen( writeFile, "w" );
  693.     if ( fileDesc == NULL )
  694.     {
  695.         /* Display an error, and get out */
  696.         printf( "PromptDialogOKCB: Error on file creation\n" );
  697.         exit( 1 );
  698.     }
  699.       
  700.     /* Write the file, and close it up */
  701.     fwrite( selectedText, sizeof( char ), strlen( selectedText ), fileDesc );
  702.     if ( fclose( fileDesc ) != NULL )
  703.     {
  704.         /* Display an error, and get out */
  705.         printf( "PromptDialogOKCB: Error on file close\n" );
  706.         exit( 1 ); 
  707.     } 
  708.  
  709. }
  710.  
  711.  
  712. [LISTING FOUR]
  713.  
  714. /*~PKG*************************************************************************
  715.  *  Package Name: xm_clipboard.c
  716.  *  Synopsis: Implements clipboard store and retrieve procedures.
  717.  *  Features Supported:
  718.  *  References: Xt Programming and Apps by Doug Young.
  719.  *      Xm Programming Reference and Guide by OSF.
  720.  *      Xt Programming Reference and Guide by O'Reilly.
  721.  *  Usage: Include "xm_clipboard.h"
  722.  *  Known Bugs/Deficiencies:
  723.  *  Modification History: 11/01/90    twl  original
  724.  */
  725.  
  726. /*~HDR*************************************************************************
  727.  *  Header files included.  */
  728. #include <X11/StringDefs.h>
  729. #include <X11/Intrinsic.h>
  730. #include <Xm/Xm.h>
  731. #include <Xm/Text.h>
  732. #include <Xm/CutPaste.h>
  733.  
  734. /*~LOC*DATA********************************************************************
  735.  *  Constants and variables local to this package.  */
  736.    
  737. #define CBLABEL "TextEdit"
  738.  
  739. /*~PROC************************************************************************
  740.  *  Procedure:  CopyToClipboard
  741.  *  Synopsis: Retrieve selected text from reference textID, and copy it to the system
  742.  *      clipboard.  Returns True if successful, False if not.
  743.  *  Assumptions: 
  744.  *  Features Supported:
  745.  *  Known Bugs/Deficiencies: Text only supported.
  746.  *  Modification History: 11/01/90  twl     original
  747.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  748. int
  749. CopyToClipboard( Widget textID, Time timestamp )
  750. {    
  751.  
  752.     char    *selectedText;      /* That text which is marked as selected in textID */
  753.     int      clipStat;          /* Return value from XmClipboard routines */
  754.     XmString clipLabel;         /* The label used to identify the clipboard string */
  755.     long     clipID, copyID;    /* The handles used in identifying clipboard transactions */
  756.  
  757.     /* Sanity check. */
  758.     if ( !XmIsText( textID ) )
  759.     {
  760.         printf( "CopyToClipboard: Not Text Widget\n" );
  761.         exit( 1 );
  762.     }
  763.  
  764.     /* If no text selected, we can leave. */
  765.     selectedText = XmTextGetSelection( textID );
  766.     if ( selectedText == NULL )
  767.     {
  768.         return( False );
  769.     }
  770.                                       
  771.     /* Create the label that appears in the clipboard. */
  772.     clipLabel = XmStringCreateLtoR( CBLABEL, XmSTRING_DEFAULT_CHARSET );
  773.        
  774.     /* Poll the clipboard, asking for permission to start. */ 
  775.     clipStat = ClipboardLocked;
  776.     while( clipStat == ClipboardLocked )
  777.     {
  778.         clipStat = XmClipboardStartCopy( XtDisplay( textID ), XtWindow( textID ),
  779.                                          clipLabel, timestamp, textID, NULL,
  780.                                          &clipID );
  781.     }
  782.   
  783.     /* Copy the data to the clipboard until successful. */
  784.     clipStat = ClipboardLocked;
  785.     while( clipStat == ClipboardLocked )
  786.     {
  787.         clipStat = XmClipboardCopy( XtDisplay( textID ), XtWindow( textID ), clipID,
  788.                                     XtRString, selectedText, (long)strlen( selectedText ), 0
  789.                                     ©ID );
  790.  
  791.     }
  792.  
  793.     /* End the transaction... */
  794.     clipStat = ClipboardLocked;
  795.     while( clipStat == ClipboardLocked )
  796.     {
  797.         clipStat = XmClipboardEndCopy( XtDisplay( textID ), XtWindow( textID ), clipID );
  798.  
  799.     }
  800.     
  801.     /* ... cleanup, and leave. */  
  802.     XtFree( selectedText );
  803.     XmStringFree( clipLabel );
  804.  
  805.     return( True );
  806. }
  807.  
  808. /*~PROC************************************************************************
  809.  *  Procedure:  RetrieveFromClipboard
  810.  *  Synopsis: Return text from the clipboard.
  811.  *  Assumptions: The caller assumes responsibility for freeing returned string.
  812.  *  Features Supported:
  813.  *  Known Bugs/Deficiencies: Text only supported.
  814.  *  Modification History: 11/01/90  twl     original
  815.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  816. char *
  817. RetrieveFromClipboard( Widget textID, Time timestamp )
  818. {
  819.  
  820.     char    *pasteText;         /* That text which is to be retrieved from the paste buffer */
  821.     int      pasteTextLen;      /* Length of text in clipboard */
  822.     int      clipStat;          /* Return value from XmClipboard routines */
  823.     XmString clipLabel;         /* The label used to identify the clipboard string */
  824.     long     clipID, privateID; /* The handles used in identifying clipboard transactions */
  825.     long     outlen;            /* Length of data retrieved from clipboard */
  826.  
  827.     /* Check to be sure that we have a text Widget */
  828.     if ( !XmIsText( textID ) )
  829.     {
  830.         printf( "RetrieveFromClipboard: Widget not Text\n" );
  831.         exit( 1 );
  832.     }                 
  833.       
  834.     /* Start our clipboard transaction */
  835.     clipStat = ClipboardLocked;
  836.     while( clipStat == ClipboardLocked )
  837.     {
  838.         clipStat = XmClipboardStartRetrieve( XtDisplay( textID ), XtWindow( textID ),
  839.                                              timestamp );
  840.     }  
  841.     
  842.     /* Get the length of the clipboard contents */
  843.     clipStat     = ClipboardLocked;
  844.     pasteTextLen = 0;
  845.     while( clipStat == ClipboardLocked )
  846.     {
  847.         clipStat = XmClipboardInquireLength( XtDisplay( textID ), XtWindow( textID ),
  848.                                              XmRString, &pasteTextLen ); 
  849.         if ( clipStat == ClipboardNoData )
  850.         {
  851.             return( NULL );
  852.         }
  853.     }
  854.                  
  855.     /* Retrieve the data (allocating a string buffer) */
  856.     pasteText = XtMalloc( pasteTextLen + 1 );
  857.  
  858.     clipStat = ClipboardLocked;
  859.     while( clipStat == ClipboardLocked )
  860.     {
  861.         clipStat = XmClipboardRetrieve( XtDisplay( textID ), XtWindow( textID ),
  862.                                         XmRString, pasteText, pasteTextLen,
  863.                                         &outlen, &privateID );
  864.     }
  865.      
  866.     /* End the clipboard session... */
  867.     clipStat = ClipboardLocked;
  868.     while( clipStat == ClipboardLocked )
  869.     {
  870.         clipStat = XmClipboardEndRetrieve( XtDisplay( textID ), XtWindow( textID ) );
  871.     }
  872.            
  873.     /* ... and return the clipboard contents. */
  874.     return( pasteText );
  875.  
  876. }
  877.  
  878. /*~PROC************************************************************************
  879.  *  Procedure:  ClipboardIsEmpty
  880.  *  Synopsis: Returns FALSE, if no items in the clipboard.
  881.  *  Assumptions:
  882.  *  Features Supported:
  883.  *  Known Bugs/Deficiencies: Text only supported.  Returns False (no data) if clipboard is locked.
  884.  *  Modification History: 11/01/90  twl     original
  885.  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  886. int
  887. ClipboardIsEmpty( Widget w )
  888. {
  889.  
  890.     int clipStat;       /* Clipboard status value */
  891.     int textLength;     /* Length of text in clipboard */
  892.  
  893.     clipStat = XmClipboardInquireLength( XtDisplay( w ), XtWindow( w ), XmRString,
  894.                                          &textLength );
  895.  
  896.     if ( clipStat == ClipboardSuccess )
  897.     {
  898.         return( False );
  899.     }
  900.     else
  901.     {
  902.         return( True );
  903.     }
  904. }
  905.  
  906.  
  907. [LISTING FIVE]
  908.  
  909. #ifndef XM_CALLBACKS_H
  910. #define XM_CALLBACKS_H
  911. /*****************************************************************************
  912.  *  Include File Name: xm_callbacks.h
  913.  *  Contents: Interface to the callbacks package.
  914.  *  This include file is dependent on the following include file(s):
  915.  *    None.
  916.  *  Modification History: 11/01/90  twl     original
  917.  */
  918.  
  919.  
  920. /*~EXP*PROC********************************************************************
  921.  *  Procedures and functions exported by this package. */  
  922. extern void
  923. MapDialogCB( Widget source, Widget dialog, XmAnyCallbackStruct *callbackData );
  924.  
  925. extern void
  926. UnMapDialogCB( Widget source, Widget dialog, XmAnyCallbackStruct *callbackData );
  927.  
  928. extern void
  929. CutCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData );
  930.  
  931. extern void
  932. CopyCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData );
  933.  
  934. extern void
  935. PasteCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData );
  936.  
  937. extern void
  938. PasteFileCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData );
  939.  
  940. extern void
  941. WriteFileCB( Widget source, Widget textID, XmAnyCallbackStruct *callbackData );
  942.       
  943. extern void
  944. FileDialogOKCB( Widget source, Widget textID, XmFileSelectionBoxCallbackStruct *callbackData );
  945.  
  946. extern void
  947. PromptDialogOKCB( Widget source, Widget textID, XmSelectionBoxCallbackStruct *callbackData );
  948.  
  949. #endif
  950.  
  951.  
  952. [LISTING SIX]
  953.  
  954.  
  955. #ifndef XM_CLIPBOARD_H
  956. #define XM_CLIPBOARD_H
  957. /*****************************************************************************
  958.  *
  959.  *  Include File Name: xm_clipboard.h
  960.  *
  961.  *  Contents:
  962.  *    Interface to the Clipboard package.
  963.  *
  964.  *  This include file is dependent on the following include file(s):
  965.  *    None.
  966.  *
  967.  *  Modification History:
  968.  *    11/01/90  twl     original
  969.  */
  970.  
  971.  
  972. /*~EXP*PROC********************************************************************
  973.  *
  974.  *  Procedures and functions exported by this package.
  975.  */  
  976. extern int
  977. CopyToClipboard( Widget textID, Time timestamp );
  978.  
  979. extern char *
  980. RetrieveFromClipboard( Widget textID, Time timestamp );
  981.         
  982. extern int
  983. ClipboardIsEmpty( Widget w );
  984.  
  985. #endif
  986.  
  987.  
  988. [LISTING SEVEN]
  989.  
  990. #
  991. # Makefile to build textedit
  992. #
  993.  
  994. #
  995. # Macros
  996.  
  997. CC=/bin/cc 
  998. DEBUG=-g
  999. INCLUDE_DIRS=-I /usr/include/Xm -I /usr/include/X11
  1000. SYS_DEFS=$(SYS_T) $(RUN_T) -DSYSV
  1001. CC_SWITCHES= -c $(SYS_DEFS) $(INCLUDE_DIRS) $(DEBUG)
  1002.  
  1003. LD=/bin/ld
  1004. LIBDIRS=-L/usr/X11/lib
  1005. LIBS=-lXm -lXtm -lXaw -lX11
  1006. LD_SWITCHES=$(LIBDIRS) $(LIBS)
  1007.   
  1008. # Inference rules
  1009. #
  1010. .SUFFIXES: .c .o .ln
  1011.  
  1012. .c.o:
  1013.     $(CC) $(CC_SWITCHES) $<
  1014.  
  1015. OBJS=\
  1016.     xm_main.o\
  1017.     xm_clipboard.o\
  1018.     xm_callbacks.o
  1019.  
  1020. #
  1021. # Targets
  1022. #
  1023.  
  1024. all:    textedit
  1025.      
  1026. textedit:  $(OBJS)
  1027.     $(LD) -o $@ $(OBJS) $(LD_SWITCHES)
  1028.  
  1029. xm_main.o:      xm_callbacks.h
  1030.  
  1031. xm_callbacks.o: xm_clipboard.h
  1032.  
  1033. #-------------------------
  1034. #   Misc targets
  1035. #-------------------------
  1036. clean:
  1037.     -rm *.bak *.o
  1038.                
  1039. lint:
  1040.     lint $(INCLUDE_DIRS) -DSYSV *.c
  1041.  
  1042.  
  1043.