Common Desktop Environment: ToolTalk Messaging Overview

Chapter 2 How to Use ToolTalk Messaging


Note -

The code examples shown in this chapter are taken from a ToolTalk demo program called CoEd. See Appendix B, The CoEd Demonstration Program for a listing of the source code showing how ToolTalk-related code is included in the header and .c files for this program.


Telling Your Application About ToolTalk Functionality

Before your application can utilize the interoperability functionality provided by the ToolTalk service and the Messaging Toolkit, it needs to know where the ToolTalk libraries and toolkit reside.

Using the Messaging Toolkit and Including ToolTalk Commands

To use the ToolTalk service, an application calls ToolTalk functions from the ToolTalk API. The Messaging Toolkit provides functions such as functions to register with the ToolTalk service, to create message patterns, to send messages, to receive messages, and to examine message information. To modify your application to use the ToolTalk service and toolkit, you must include the appropriate header files in your application's .h file.

#include <Tt/tt_c.h>        // ToolTalk Header File 
#include <Tt/tttk.h>        // Messaging Toolkit Header file

Your application also needs to know about the new ToolTalk commands that are in its .c file. Place this information in your application's .h file, too.

Example 2-1 shows how the header file information is included in the CoEditor.h file.


Example 2-1 Including Messaging Information

#ifndef CoEditor_h 
#define CoEditor_h  

#include <X11/Intrinsic.h> 
#include <Tt/tt_c.h>             // ToolTalk Header 
#include <Tt/tttk.h>             // Messaging Toolkit Header

Using the ToolTalk Libraries

You need to change the makefile of your application so that it uses the ToolTalk libraries. To do this, add the -ltt option as follows:

LOCAL_LIBRARIES = -ltt $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)

Before You Start Coding

Before you can incorporate the Messaging Toolkit functionality into your application, you need to determine the way that your tool will work with other tools. There are several basic questions you need to ask:

  1. How will these tools work together?

  2. What kinds of operations can these tools perform?

  3. What kinds of operations can these tools ask other tools to perform?

  4. What events will these tools generate which may interest other tools? (What types of messages will these tools want to send?)

  5. What events generated by other tools will be of interest to these tools? (What types of messages will these tools want to receive?)

To best answer these questions, you need to understand the difference between events and operations, and how the ToolTalk service handles messages regarding each of these.

What Is the Difference Between an Event and an Operation?

An event is an announcement that something has happened. An event is simply a news bulletin. The sending process has no formal expectations as to whether any other process will hear about the event, or whether an action is taken as a consequence of the event. When a process uses the ToolTalk service to inform interested processes that an event has occurred, it sends a notice. Since the sending process does not expect a reply, an event cannot fail.

An operation is an inquiry or an action. The requesting process makes an inquiry or requests that an operation be performed. The requesting process expects a result to be returned and needs to be informed of the status of the inquiry or action. When a process uses the ToolTalk service to ask another tool to perform an operation, it sends a request. The ToolTalk service delivers the request to interested processes and informs the sending process of the status of the request.

Sending Notices

When your application sends a ToolTalk notice, it will not receive a reply or be informed about whether or not any tool pays attention to the notice. It is important to make the notice an impartial report of the event as it happens.

For example, if your tool sends the Desktop Services message Modified, it may expect any listening tools to react in a given way. However, your tool should not care, and does not need to be informed, about whether any or no other tool reacts to the message; it only wants to report the event:

THE_USER_HAS_MADE_CHANGES_TO_THIS.

Sending Requests

When your application sends a ToolTalk request, it expects one tool to perform the indicated operation, or to answer the inquiry, and return a reply message. For example, if your tool sends the Desktop Services message Get_Modified, it should expect notification that the message was delivered and the action performed. The ToolTalk service guarantees that either a reply will be returned by the receiving process or the sender will be informed of the request's failure.

You can identify requests in three ways:

  1. By identifying the operations requested by your tool that can fail

  2. By identifying the operations your tool can perform for other tools

  3. By identifying the operations your tool will want other tools to perform

A good method to use to identify these operations is to develop a scenario that outlines the order of events and operations that you expect your tool to perform and have performed.

Developing a Scenario

A scenario outlines the order of the events and operations that a tool will expect to perform and have performed. For example, the following scenario outlines the events that the ToolTalk demo program CoEd expects to perform and have performed:

  1. User double-clicks on a document icon in the File Manager.

    The file opens in the editor, which is started by the system if one is not already running.

    If another tool has modifications to the text pending for the document, User is asked whether the other tool should save the text changes or revert to the last saved version of the document.

  2. User inserts text.

  3. User saves the document.

    If another tool has modifications pending for the document, User is asked whether to modify the document.

  4. User exits the editor.

    If text has unsaved changes, User is asked whether to save or discard the changes before quitting the file.

Once the scenario is done, you can answer your basic questions.

How Will the Tools Work Together?

What Kinds of Operations Do the Tools Perform?

What Kinds of Operations Can the Tools Ask Other Tools to Perform?

What Events Will the Tools Generate That May Interest Other Tools?

What Events Generated by Other Tools Will Be of Interest to This Tool?

Preparing Your Application for Communication

The ToolTalk service provides you with a complete set of functions for application integration. Using the functionality provided with the ToolTalk Messaging Toolkit, your applications can be made to "speak" to other applications that are ToolTalk-compliant. This section describes how to add the kinds of ToolTalk functions you need to include in your application so that it can communicate with other ToolTalk-aware applications that follow the same protocols.

Creating a Ptype File

The ToolTalk types mechanism is designed to help the ToolTalk service route messages. When your tool declares a ptype, the message patterns listed in it are automatically registered; the ToolTalk service then matches messages it receives to these registered patterns. These static message patterns remain in effect until the tool closes communication with the ToolTalk service.

The ToolTalk Types Database already has installed ptypes for tools bundled with this release. You can extract a list of the installed ptypes from the ToolTalk Types Database, as follows:

% tt_type_comp -d user|system|network -P

The names of the ptypes will be printed out in source format.

For all other tools (that is, tools that are not included in this release), you need to first create a ptype file to define the ptype for your application, and then compile the ptype with the ToolTalk type compiler, tt_type_comp. To define a ptype, you need to include the following information in a file:

To create a ptype file, you can use any text editor (such as vi, emacs, or dtpad). Example 2-2 shows a snippet from the ptype file for the CoEd application.


Example 2-2 CoEd Ptype File

ptype DT_CoEd {                     /* Process type identifier */
    start "CoEd";                   /* Start string */
    handle:                         /* Receiving process */
    /*
     * Display ISO_Latin_1
     */
    session    Display( in    ISO_Latin_1 contents) => start opnum = 1;  /* Signature */
        /* NOTE: A signature is divided
         * into two parts by the => as follows:
         * Part 1 specifies how the message is to be matched;
         * Part 2 specifies what is to be taken when 
         * a match occurs.
         */

}

After you have created the ptype file, you need to install the ptype. To do this, run the ToolTalk type compiler. On the command line, type the following:

% tt_type_compCoEd.ptype

where CoEd.ptype is the name of the CoED ptype file.

Testing for Existing Ptypes in Current Session

The ToolTalk service provides a simple function to test if a given ptype is already registered in the current session.

// Test for existing ptype registered in current session
tt_ptype_exists(const char *ptid)

where ptid is the identifier of the session to test for registration.

Merging a Compiled Ptype File into a Currently Running ttsession

The ToolTalk service provides a function to merge a compiled ToolTalk type file into the currently running ttsession:

// Merge new compiled ptypes into currently running
ttsession tt_session_types_load(current_session, compiled_types_file)

where current_session is the current default ToolTalk session and compiled_types_file is the name of the compiled ToolTalk types file. This function adds new types and replaces existing types of the same name; other existing types remain unchanged.

Tasks Every ToolTalk-aware Application Needs to Perform

There are a number of tasks every ToolTalk-aware application needs to perform, including:

This section provides examples of the ToolTalk code you need to include in your application so that it can perform these tasks.


Note -

The code snippets used in this section are taken from the CoEd.C file. This file contains the general commands any application needs to perform that are not specific to any particular application. See Appendix B, The CoEd Demonstration Program for the detailed source code.


Initializing the Toolkit

Your application needs to initialize and register with the initial ToolTalk session. To do so, it first needs to obtain a process identifier (procid). The following code snippet shows how to obtain a procid and how to initialize the toolkit.

// Obtain process identifier
    int myTtFd; //
Initialize toolkit and create a ToolTalk communication endpoint
    char *myProcID = ttdt_open( &myTtFd, ToolName, "SunSoft", "%I", 1 );

Caution - Caution -

Your application must call ttdt_open before any other calls are made; otherwise, errors may occur.


Joining the ToolTalk Session and Registering Message Patterns

Before your application can receive messages, it must join a ToolTalk session and register the message patterns that are to be matched.

// Join a ToolTalk session and register patterns and default callbacks
           sessPats = ttdt_session_join( 0, 0, session_shell, this, 1 );
    }

Adding the ToolTalk Service to Event Loop

Your application also needs to add the ToolTalk service to its event loop.

// Process ToolTalk events for Xt Clients
      XtAppAddInput( myContext, myTtFd, (XtPointer)XtInputReadMask, tk_Xt_input_handler,
              myProcID );

Tasks ToolTalk-aware Editor Applications Need to Perform

In addition to the duties described in the section "Tasks Every ToolTalk-aware Application Needs to Perform", ToolTalk-aware editor applications also need to perform other tasks, including:

This section provides examples of the ToolTalk code you need to include in your editor application so that it can perform these additional tasks.


Note -

The code snippets used in this section are taken from the CoEditor.C file. This file contains specific commands for editor applications. See Appendix B, The CoEd Demonstration Program for the detailed source code.


Writing a Media Load Pattern Callback

There is one step you need to perform before you code your editor application to include any ToolTalk functions: you need to write a media load pattern callback routine. For example,

Tt_message CoEditor::loadISOLatin1_(     Tt_message       msg,     void          *pWidget,
     Ttttk_op          op,     Tt_status        diagnosis,     unsigned char     *contents,
     int               len,     char              *file,     char              *docname   )

This callback is passed to the media load function at runtime.

Declaring a Ptype

Since type information is specified only once (when your application is installed), your application needs to only declare its ptype each time it starts.

Passing Media Load Pattern Callbacks

The media load pattern callback routine you wrote previously is passed in at runtime. The callbacks are registered when your application joins the session. When your tool agrees to handle a request, a callback message is sent. A callback message is also sent if a file is joined or if a message is failed.

// Join the session and register patterns and callbacks 
sessPats = ttdt_session_join( 0, 0, session_shell, this, 1 );  

// Accept responsibility to handle a request
    _contractPats = ttdt_message_accept(msg, CoEditor::_contractCB_, shell, this, 1, 1 ); 

 // Optional task: Join a file (Can be called recursively)
    if (_filePats == 0) {_filePats = ttdt_file_join( _file, TT_SCOPE_NONE, 1,
                     CoEditor::_fileCB_, this );
    }  

// Fail a message 
tttk_message_fail( msg, TT_DESKTOP_ENODATA, 0, 1 );

Replying When Request Is Completed

After your application has completed the operation request, it must reply to the sending application. The following message returns the edited contents of text to the sender.

// Reply to media load pattern callback 
// with edited contents of text 
ttmedia_load_reply( _contract, (unsigned char *)contents,
                 len, 1 );

Optional Tasks ToolTalk-aware Editor Applications Can Perform

In addition to the tasks described in the section "Tasks ToolTalk-aware Editor Applications Need to Perform" editor applications can also perform other optional tasks such as tasks that use desktop file interfaces to coordinate with other editors. This section provides examples of some of the ToolTalk code you need to include in your editor application so that it can perform these optional tasks.


Note -

The code snippets used in this section are taken from the CoEditor.C file. This file contains specific commands for editor applications. See Appendix B, The CoEd Demonstration Program for the detailed source code.


Requesting Modify, Revert, or Save Operations

The following code snippet asks a file whether it has any changes pending:

// Does the file have any changes pending?
_modifiedByOther = ttdt_Get_Modified( _contract, _file, TT_BOTH,
                     10 * timeOutFactor );

The following code snippet reverts a file to its last version:

// Revert file to last version 
status = ttdt_Revert(_contract, _file, TT_BOTH,
              10 * timeOutFactor );

The following code snippet saves pending changes to a file:

// Save pending changes 
status = ttdt_Save( _contract, _file, TT_BOTH,
             10 * timeOutFactor );

Notifying When a File Is Modified, Reverted, or Saved

The following code snippet announces to interested tools that your application has changes pending for the file:

// File has been modified 
ttdt_file_event( _contract, TTDT_MODIFIED, _filePats, 1 );

The following code snippet announces to interested tools that your application has reverted the file to its last saved version:

// File has been reverted to last version 
ttdt_file_event( _contract, TTDT_REVERTED, _filePats, 1 );

The following code snippet announces to interested tools that your application has saved its pending changes for the file.

// File has been saved 
ttdt_file_event( _contract, TTDT_SAVED, _filePats, 1 );

Quitting a File

The following code snippet unregisters interest in ToolTalk events about a file and destroys the patterns.

// Unregister interest in ToolTalk events and destroy patterns 
status = ttdt_file_quit( _filePats, 1 );
    _filePats = 0;