Common Desktop Environment: ToolTalk Messaging Overview

Appendix D Examples

Example Ttdt_contract_cb

Example D-1 is an example of a typical algorithm of a Ttdt_contract_cb callback for an application that handles its own Pause/Resume/Quit requests but allows the toolkit to handle the X11-related requests.


Note -

This example callback deals with the case when the contract parameter has a value other than zero and can, therefore, also be used as the Ttdt_contract_cb callback passed to ttdt_message_accept.



Example D-1 Typical Algorithm of Ttdt_contract_cb

Tt_message myContractCB(
         Tt_message      msg,
         void           *clientdata,
         Tt_message      contract 
) 
{
         char *opString = tt_message_op( msg );
         Tttk_op op = tttk_string_op( opString );
         tt_free( opString );
         int silent = 0;
         int force  = 0;
         Boolean cancel = False;
         Boolean sensitive = True;
         char *status, command;
         switch (op) {
             case TTDT_QUIT:
                 tt_message_arg_ival( msg, 0, &silent );
                 tt_message_arg_ival( msg, 1, &force );
                 if (contract == 0) {
                         /* Quit entire application */
                         cancel = ! myQuitWholeApp( silent, force );
                 } else {
                         /* Quit just the specified request being worked on */
                         cancel = ! myCancelThisRequest(contract, silent, force);
                 }
                 if (cancel) {
                         /* User canceled Quit; fail the Quit request */
                         tttk_message_fail( msg, TT_DESKTOP_ECANCELED, 0, 1 );
                 } else {
                         tt_message_reply( msg );
                         tttk_message_destroy( msg );
                 }
                 return 0;
             case TTDT_PAUSE:
                 sensitive = False;
             case TTDT_RESUME:
                 if (contract == 0) {
                         int already = 1;
                         if (XtIsSensitive( myTopShell ) != sensitive) {
                                 already = 0;
                                 XtSetSensitive( myTopShell, sensitive );
                         }
                         if (already) {
                                 tt_message_status_set(msg,TT_DESKTOP_EALREADY);
                         }
                 } else {
                         if (XtIsSensitive( thisShell ) == sensitive) {
                                 tt_message_status_set(msg,TT_DESKTOP_EALREADY);
                         } else {
                                 XtSetSensitive( thisShell, sensitive );
                        }
                 }
                 tt_message_reply( msg );
                 tttk_message_destroy( msg );
                 return 0;
             case TTDT_GET_STATUS:
                 if (contract == 0) {
                         status = "Message about status of entire app";
                 } else {
                         status = "Message about status of this request";
                 }
                 tt_message_arg_val_set( msg, 0, status );
                 tt_message_reply( msg );
                 tttk_message_destroy( msg );
                 return 0;
             case TTDT_DO_COMMAND:
                 if (! haveExtensionLanguage) {
                         tttk_message_fail( msg, TT_DESKTOP_ENOTSUP, 0, 1 );
                         return 0;
                 }
                 command = tt_message_arg_val( msg, 0 );
                 result = myEval( command );
                 tt_free( command );
                 tt_message_status_set( msg, result );
                 if (tt_is_err( result )) {
                         tttk_message_fail( msg, result, 0, 1 );
                 } else {
                         tt_message_reply( msg );
                        tttk_message_destroy( msg );
                 }
                 return 0;
         }
         /* Unrecognized message; do not consume it */
         return msg; 
}

Example Ttdt_file_cb

Example D-2 is an example of a typical algorithm of this callback.


Example D-2 Typical Algorithm of Ttdt_file_cb

Tt_message myFileCB(
         Tt_message      msg,
         Tttk_op         op,
         char           *pathname,
         int             trust,
         int             isMe 
) 
{
         tt_free( pathname );
         Tt_status status = TT_OK;
         switch (op) {
             case TTDT_MODIFIED:
                 if ((_modifiedByMe) && (! isMe)) {
                         // Hmm, the other editor either does not know or
                         // does not care that we are already modifying the
                         // file, so the last saver will win.
                 } else {
                         // Interrogate user if she ever modifies the buffer
                         _modifiedByOther = 1;
                         XtAddCallback( myTextWidget, XmNmodifyVerifyCallback,
                                        myTextModifyCB, 0 );
                 }
                 break;
             case TTDT_GET_MODIFIED:
                 tt_message_arg_ival_set( msg, 1, _modifiedByMe );
                 tt_message_reply( msg );
                 break;
             case TTDT_SAVE:
                 status = mySave( trust );
                 if (status == TT_OK) {
                         tt_message_reply( msg );
                 } else {
                         tttk_message_fail( msg, status, 0, 0 );
                 }                 break;
             case TTDT_REVERT:
                 status = myRevert( trust );
                 if (status == TT_OK) {
                         tt_message_reply( msg );
                 } else {
                         tttk_message_fail( msg, status, 0, 0 );
                 }
                 break;
             case TTDT_REVERTED:
                 if (! isMe) {
                         _modifiedByOther = 0;
                 }
                 break;
             case TTDT_SAVED:
                 if (! isMe) {
                         _modifiedByOther = 0;
                         int choice = myUserChoice( myContext, myBaseFrame,
                                                  "Another tool has saved "
                                                  "this file.", 2, "Ignore",
                                                  "Revert" );
                         switch (choice) {
                             case 1:
                                 myRevert( 1 );
                                 break;
                         }
                 }
                 break;
             case TTDT_MOVED:
             case TTDT_DELETED:
                 // Do something appropriate
                 break;
         }
         tttk_message_destroy( msg );
         return 0; 
}

Example Ttmedia_load_msg_cb

Example D-3 is an example of a typical algorithm of this callback.


Example D-3 Typical Algorithm of Ttmedia_load_msg_cb

Tt_message 
myLoadMsgCB(
    Tt_messagemsg,
    void       *clientData,
    Tttk_op         op,
    unsigned char  *contents,
    int    len,
    char           *file
)
{
    if (len > 0) {
        // Replace data with len bytes in contents
    } else if (file != 0) {
        // Replace data with data read from file
    }
    if (op == TTME_DEPOSIT) {
        tt_message_reply( msg );
    }
    tttk_message_destroy( msg );
    return 0; 
}

Example Ttmedia_load_pat_cb

Example D-4 is an example of a typical algorithm of this callback.


Example D-4 Typical Algorithm of Ttmedia_load_pat_cb

Tt_message myAcmeSheetLoadCB(
         Tt_message      msg,
         void           *client_data,
         Tttk_op         op,
         Tt_status       diagnosis,
         unsigned char  *contents,
         int             len,
         char           *file,
         char           *docname 
) 
{
         Tt_status status = TT_OK;
         if (diagnosis != TT_OK) {
                 // toolkit detected an error
                 if (tt_message_status( msg ) == TT_WRN_START_MESSAGE) {
                         //
                         // Error is in start message!  We now have no
                         // reason to live, so tell main() to exit().
                         //
                         myAbortCode = 2;
                 }
                 // let toolkit handle the error
                 return msg;         }
         if ((op == TTME_COMPOSE) && (file == 0)) {
                 // open empty new buffer
         } else if (len > 0) {
                 // load contents into new buffer
         } else if (file != 0) {
                 if (ttdt_Get_Modified( msg, file, TT_BOTH, myCntxt, 5000 )) {
                         switch (myUserChoice( "Save, Revert, Ignore?" )) {
                             case 0:
                                 ttdt_Save( msg, file, TT_BOTH, myCntxt, 5000 );
                                 break;
                             case 1:
                                 ttdt_Revert( msg, file, TT_BOTH, myCntxt, 5000);
                                 break;
                         }
                 }
                 // load file into new buffer
         } else {
                 tttk_message_fail( msg, TT_DESKTOP_ENODATA, 0, 1 );
                 tt_free( contents ); tt_free( file ); tt_free( docname );
                 return 0;
         }
         int w, h, x, y = INT_MAX;
         ttdt_sender_imprint_on( 0, msg, 0, &w, &h, &x, &y, myCntxt, 5000 );
         positionMyWindowRelativeTo( w, h, x, y );
         if (maxBuffersAreNowOpen) {
                 // Un-volunteer to handle future requests until less busy
                 tt_ptype_undeclare( "Acme_Calc" );
         }
         if (tt_message_status( msg ) == TT_WRN_START_MESSAGE) {
                 //
                 // Join session before accepting start message,
                 // to prevent unnecessary starts of our ptype
                 // 
                ttdt_session_join( 0, myContractCB, myShell, 0, 1 );
         }
         ttdt_message_accept( msg, myContractCB, myShell, 0, 1, 1 );
         tt_free( contents ); tt_free( file ); tt_free( docname );
         return 0;
 }

Example Ptype Signature for Ttmedia_ptype_declare Function

Example D-5 is an example of the signature layout of a media ptype.


Example D-5 Example of Media Ptype Signature Layout

ptype Acme_Calc {
     start "acalc";
     handle:
        /*
          * Display Acme_Sheet
          * Include in tool's ptype if tool can display a document.
          */
         session Display( in    Acme_Sheet  contents     ) => start opnum = 1;
         session Display( in    Acme_Sheet  contents,
                          in    messageID   counterfoil  ) => start opnum = 2;
         session Display( in    Acme_Sheet  contents,
                          in    title       docName      ) => start opnum = 3;
         session Display( in    Acme_Sheet  contents,
                          in    messageID   counterfoil,
                          in    title       docName      ) => start opnum = 4;
         /*
          * Edit Acme_Sheet
          * Include in tool's ptype if tool can edit a document.
          */
         session Edit(    inout Acme_Sheet  contents     ) => start opnum = 101;
         session Edit(    inout Acme_Sheet  contents,
                          in    messageID   counterfoil  ) => start opnum = 102;
         session Edit(    inout Acme_Sheet  contents,
                          in    title       docName      ) => start opnum = 103;
         session Edit(    inout Acme_Sheet  contents,
                          in    messageID   counterfoil,
                          in    title       docName      ) => start opnum = 104;
         /*
          * Compose Acme_Sheet
          * Include in tool's ptype if tool can compose a document from scratch.
          */
         session Edit(    out   Acme_Sheet  contents     ) => start opnum = 201;
         session Edit(    out   Acme_Sheet  contents,
                          in    messageID   counterfoil  ) => start opnum = 202;
         session Edit(    out   Acme_Sheet  contents,
                          in    title       docName      ) => start opnum = 203;
         session Edit(    out   Acme_Sheet  contents,
                          in    messageID   counterfoil,
                          in    title       docName      ) => start opnum = 204;
         /*
          * Mail Acme_Sheet
          * Include in tool's ptype if tool can mail a document.
          */
         session Mail(    in    Acme_Sheet  contents     ) => start opnum = 301;
         session Mail(    inout Acme_Sheet  contents     ) => start opnum = 311;
         session Mail(    inout Acme_Sheet  contents,
                          in    title       docName      ) => start opnum = 313;
         session Mail(    out   Acme_Sheet  contents     ) => start opnum = 321;
         session Mail(    out   Acme_Sheet  contents,
                          in    messageID   counterfoil  ) => start opnum = 323; 
};

Example for Xt Input Handler Function

Example D-6 is an example for the Xt input handler function.


Example D-6 Xt Input Handler Function Example

int myTtFd; 
char *myProcID; 
myProcID = ttdt_open( &myTtFd, "WhizzyCalc", "Acme", "1.0", 1 );
 /* ... */ 
/* Process the message that started us, if any */ 
tttk_Xt_input_handler( myProcID, 0, 0 ); 
/* ... */ 
XtAppAddInput( myContext, myTtFd, (XtPointer)XtInputReadMask,
                tttk_Xt_input_handler, myProcID );