]]>
]]>
ttmedia_ptype_declare
library call
ttmedia_ptype_declare
declare the ptype of a Media Exchange media editor
#include <Tt/tttk.h>
Tt_status ttmedia_ptype_declare
const char *ptype
int base_opnum
Ttmedia_load_pat_cb cb
void *clientdata
int declare
DESCRIPTION
The
ttmedia_ptype_declare function
is used to initialize an editor that implements the Media Exchange
message interface for a particular media type.
The
ttmedia_ptype_declare function
notifies
the ToolTalk service
that the
cb callback is to be called when the editor is asked to edit a document
of the kind supported by
ptype.
The
ttmedia_ptype_declare function
installs an implementation-specific
opnum callback on a series of signatures that
ptype
is assumed to contain.
These signatures are listed below, with
their corresponding opnum offsets.
Opnums in
ptype
for these signatures start at
base_opnum, which must be zero or a multiple of 1000.
The implementation-specific
opnum callback will pass
clientdata to
cb when a request is received that matches one of these signatures.
If
declare is True,
ttmedia_ptype_declare calls
tt_ptype_declare with the
ptype
argument.
If
ptype
implements Media Exchange for several different media types,
then
ttmedia_ptype_declare can be called multiple times, with a different
base_opnum each time, and with
declare being True only once.
The
Ttmedia_load_pat_cb argument is a callback defined as:
Tt_message (*Ttmedia_load_pat_cb)(Tt_message msg,
void *clientdata,
Tttk_op op,
Tt_status diagnosis,
unsigned char *contents,
int len,
char *file,
char *docname);
The
msg argument is a
TT_REQUEST in
Tt_state TT_SENT. The client
program becomes responsible for either failing, rejecting or replying
to it.
This can either be done inside the callback, or the message
can be saved and dismissed later (that is, after the callback returns).
Usually, the callback will either immediately reject/fail the request,
or it will start processing the request, perhaps by associating it
with a new window.
When the request is finally dismissed, it should
be destroyed, for example, using
tt_message_destroy.
If the callback knows it will handle the request (either fail or reply
to it, but not reject it), then it should call
&cdeman.ttdt.message.accept;. But if the return value of
&cdeman.tt.message.status; of
msg is
TT_WRN_START_MESSAGE, then the callback should probably do
ttdt_session_join, and perhaps a
ttdt_file_join, before accepting the message.
The
op argument is the
op of the incoming request,
one of
TTME_COMPOSE, TTME_EDIT or
TTME_DISPLAY. The
diagnosis argument is the
recommended error code;
if the ToolTalk service
detects a problem with the request (for example,
TT_DESKTOP_ENODATA), then it passes in the error code
that it recommends the request should be failed with.
If
diagnosis was not
TT_OK and the
Ttmedia_load_pat_cb returns
msg, then the ToolTalk service
will fail and destroy
msg.
The ToolTalk service
does not simply fail the request transparently, because
the request may be the reason that the client process was started
by ToolTalk in the first place.
So if
diagnosis is not
TT_OK and the
tt_message_status of
msg is
TT_WRN_START_MESSAGE, then many applications will
decide that they have no reason to continue running.
If such an application chooses to exit in the callback, then
it should first dismiss the request.
Otherwise, it can set
some global flag, return
msg (thus allowing the ToolTalk service
to dismiss the message), and then
have
main check the flag and exit before even entering the
event loop.
(Exiting without dismissing the request would fail
it with status
TT_ERR_PROCID, instead of with
diagnostic.)
The
contents, len, and
file arguments represent the
contents of the arriving document.
If
len is zero, then the document is contained in
file. If
contents or
file are non-
NULL, they can be freed using
tt_free.
The
docname argument is the
name of the document, if any.
The
clientdata argument is the
clientdata passed to
ttmedia_ptype_declare.
A
Ttmedia_load_pat_cb should return zero if it processes
msg successfully, or a
tt_error_pointer cast to
Tt_message if processing results in an error.
It should return the
msg if it does not consume it.
If
diagnosis is not
TT_OK and
msg is returned, then the ToolTalk service
will consume (namely, fail and destroy) it.
If
diagnosis is
TT_OK and
msg is returned, then the ToolTalk service will pass
TT_CALLBACK_CONTINUE down the call stack, so that
msg will be offered to other callbacks or (more likely) be returned from
&cdeman.tt.message.receive;. Applications will rarely want
msg to get processed by other callbacks or in the main event loop.
RETURN VALUE
Upon successful completion, the
ttmedia_ptype_declare function returns the status of the operation.
The application can use
&cdeman.tt.ptr.error; to extract one of the following
Tt_status values from the returned handle:
TT_OK
The operation completed successfully.
TT_ERR_NOMP
The
&cdeman.ttsession; process is not running and the ToolTalk service cannot restart it.
TT_ERR_POINTER
The pointer passed does not point to an object
of the correct type for this operation.
TT_ERR_PROCID
The specified process identifier is out of date or invalid.
TT_ERR_PTYPE
The specified process type is not the name of an installed process type.
EXAMPLES
This is the typical algorithm of a
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;
}
This is the signature layout to which
ptype should conform:
ptype Acme_Calc {
start "acalc";
handle:
start opnum = 401;
]]> /*
* 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;
};
SEE ALSO
&cdeman.Tt.tttk.h;, &cdeman.tt.ptype.declare;, &cdeman.tt.ptype.undeclare;, &cdeman.ttdt.message.accept;, &cdeman.ttdt.session.join;, &cdeman.ttdt.file.join;, &cdeman.tt.free;, &cdeman.tt.message.receive;.