共通デスクトップ環境 ToolTalk メッセージの概要

付録 D 例

Ttdt_contract_cb の例

例 D-1 は、アプリケーションのための Ttdt_contract_cb コールバックの典型的なアルゴリズムの例です。このアプリケーションは、Pause 要求、 Resume 要求、 Quit 要求を処理しますが、ツールキットには X11 関連の要求しか処理させません。


注 -

この例にあるコールバックは、contract パラメータがゼロ以外の値を持っている場合に処理します。したがって、ttdt_message_accept に渡される Ttdt_contract_cb コールバックとして使用することもできます。



例 D-1 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; 
}

Ttdt_file_cb の例

例 D-2 は、このコールバックの典型的なアルゴリズムの例です。


例 D-2 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; 
}

Ttmedia_load_msg_cb の例

例 D-3 は、このコールバックの典型的なアルゴリズムの例です。


例 D-3 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; 
}

Ttmedia_load_pat_cb の例

例 D-4 は、このコールバックの典型的なアルゴリズムの例です。


例 D-4 TTtmedia_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;
}

Ttmedia_ptype_declare 関数の ptype シグニチャーの例

例 D-5 は、メディア ptype のシグニチャーレイアウトの例です。


例 D-5 メディア ptype のシグニチャーレイアウトの例

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; 
};

Xt 入力処理関数の例

例 D-6 は、Xt 入力処理関数の例です。


例 D-6 Xt 入力処理関数の例

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