Common Desktop Environment: ToolTalk Messaging Overview

Appendix D
Examples


Contents of Appendix:
Example Ttdt_contract_cb
Example Ttdt_file_cb
Example Ttmedia_load_msg_cb
Example Ttmedia_load_pat_cb
Example Ptype Signature for Ttmedia_ptype_declare Function
Example for Xt Input Handler Function

Example Ttdt_contract_cb

Code 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.

Code 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

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

Code 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

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

Code Example D-3 Typical Algorithm of Ttmedia_load_msg_cb

Tt_message 
myLoadMsgCB( 
    Tt_message msg, 
    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

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

Code 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

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

Code 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

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

Code 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 );



Generated with CERN WebMaker