The ToolTalk service uses spec and otype information to determine object-oriented message recipients.
Figure 12-1 ToolTalk Object Data
One part is called the object content. The object content is managed by the application that creates or manages the object and is typically a piece, or pieces, of an ordinary file: a paragraph, a source code function, or a range of spreadsheet cells, for example.
The second part is called the object specification (spec). A spec contains standard properties such as the type of object, the name of the file in which the object contents are located, and the object owner. Applications can also add their own properties to a spec, for example, the location of the object content within a file. Because applications can store additional information in specs, you can identify data in existing files as objects without changing the formats of the files. You can also create objects from pieces of read-only files. Applications create and write specs to the ToolTalk database managed by rpc.ttdbserverd.
A ToolTalk object is a portion of application data for which a ToolTalk spec has been created.
Table 12-1 Functions to Create
To create an object spec in memory and obtain an objid for the object, use tt_spec_create.
The spec properties are also a convenience for the user. A user may want to associate properties (such as a comment or object name) with the object that they can view later. Your application or another ToolTalk-based tool can search for and display these properties for the user.
spec
, use tt_spec_prop_set. When you are updating an existing spec and the ToolTalk service returns TT_WRN_STALE_OBJID when you call tt_spec_write, it has found a forwarding pointer to the object in the ToolTalk database that indicates the object has been moved. To obtain the new objid, create an object message that contains the old objid and send it. The ToolTalk service will return the same status code, TT_WRN_STALE_OBJID, but updates the message objid attribute to contain the new objid. Use tt_message_object to retrieve the new objid from the message and put the new objid into your internal data structure.
Table 12-2 Functions to Maintain Object Specifications
tt_objid_equal. tt_objid_equal returns a value of 1 even in the case where one objid is a forwarding pointer for the other.Use tt_file_objects_query to find all the objects in the named file. As the ToolTalk service finds each object, it calls your filter function, and passes it the objid of the object and the two application-supplied pointers. Your filter function does some computation and returns a Tt_filter_action value (TT_FILTER_CONTINUE or TT_FILTER_STOP) to either continue the query, or to quit the search and return immediately.
Figure 12-2 illustrates how to obtain a list of specs.
Figure 12-2 Obtaining a List of Specifications
/*
* Called to update the scrolling list of objects for a file. Uses
* tt_file_objects_query to find all the ToolTalk objects.
*/
int
cntl_update_obj_panel()
{
static int list_item = 0;
char *file;
int i;
cntl_objid = (char *)0;
for (i = list_item; i >= 0; i--) {
xv_set(cntl_ui_olist, PANEL_LIST_DELETE, i, NULL);
}
list_item = 0;
file = (char *)xv_get(cntl_ui_file_field, PANEL_VALUE);
if (tt_file_objects_query(file,
(Tt_filter_function)cntl_gather_specs,
&list_item, NULL) != TT_OK) {
xv_set(cntl_ui_base_window, FRAME_LEFT_FOOTER,
"Couldn't query objects for file", NULL);
return 0;
}
return 1;
}
Within the tt_file_objects_query function, the application calls cntl_gather_specs, a filter function that inserts objects into a scrolling list.
/*
* Function to insert the objid given into the scrolling lists of objects
* for a file. Used inside tt_file_objects_query as it iterates through
* all the ToolTalk objects in a file.
*/
Tt_filter_action
cntl_gather_specs(objid, list_count, acc)
char *objid;
void *list_count;
void *acc;
{
int *i = (int *)list_count;
xv_set(cntl_ui_olist, PANEL_LIST_INSERT, *i,
PANEL_LIST_STRING, *i, objid,
NULL);
*i = (*i + 1);
/* continue processing */
return TT_FILTER_CONTINUE;
}
Use tt_spec_move to notify the ToolTalk service when an object moves from one file to another (for example, through a cut and paste operation).
Caution: Despite the efforts of the ToolTalk service and integrated applications, object references can still be broken if you remove, move, or rename files with standard operating system commands such as rm or mv. Broken references will result in undeliverable messages.
Table 12-3 Functions to Copy, Move, or Remove Files that Contain Object Data
Table 12-4 ToolTalk-Wrapped Shell Commands
The following sample code creates an object for its user: it creates the object spec, sets the otype, writes the spec to the ToolTalk database, and wraps the user's selection with C-style comments. The application also sends out a procedure-addressed notice after it creates the new object to update other applications who observe messages with the ToolTalk_EditDemo_new_object operation. If other applications are displaying a list of objects in a file managed by ToolTalk_EditDemo, they update their list after receiving this notice.
/*
* Make a ToolTalk spec out of the selected text in this textpane. Once
* the spec is successfully created and written to a database, wrap the
* text with C-style comments in order to delimit the object and send out
* a notification that an object has been created in this file.
*/
Menu_item
edit_ui_make_object(item, event)
Panel_item item;
Event *event;
{
int mark = tt_mark();
char *objid;
char *file;
char *sel;
Textsw_index first, last;
char obj_start_text[100];
char obj_end_text[100];
Tt_message msg;
if (! get_selection(edit_ui_xserver, edit_ui_textpane,
&sel, &first, &last)) {
xv_set(edit_ui_base_window, FRAME_LEFT_FOOTER,
"First select some text", NULL);
tt_release(mark);
return item;
}
file = tt_default_file();
if (file == (char *)0) {
xv_set(edit_ui_base_window, FRAME_LEFT_FOOTER,
"Not editing any file", NULL);
tt_release(mark);
return item;
}
/* create a new spec */
objid = tt_spec_create(tt_default_file());
if (tt_pointer_error(objid) != TT_OK) {
xv_set(edit_ui_base_window, FRAME_LEFT_FOOTER,
"Couldn't create object", NULL);
tt_release(mark);
return item;
}
/* set its otype */
tt_spec_type_set(objid, "Sun_EditDemo_object");
if (tt_spec_write(objid) != TT_OK) {
xv_set(edit_ui_base_window, FRAME_LEFT_FOOTER,
"Couldn't write out object", NULL);
tt_release(mark);
return item;
}
/* wrap spec's contents (the selected text) with C-style */
/* comments. */
sprintf(obj_start_text," /* begin_object(%s) */", objid);
sprintf(obj_end_text," /* end_object(%s) */", objid);
(void)wrap_selection(edit_ui_xserver, edit_ui_textpane,
obj_start_text, obj_end_text);
/* now send out a notification that we've added a new object */
msg = tt_pnotice_create(TT_FILE_IN_SESSION,"Sun_EditDemo_new_object");
tt_message_file_set(msg, file);
tt_message_send(msg);
tt_release(mark);
return item;
}