Tooltalk fixes for OpenBSD. This consists mainly of #ifdefs, casts and some small...
[oweals/cde.git] / cde / lib / tt / lib / tttk / ttmedia.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                  
24 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.    
25 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                   
26 //%%  (c) Copyright 1993, 1994 Novell, Inc.                             
27 //%%  $XConsortium: ttmedia.C /main/3 1995/10/23 10:32:41 rswiston $                                                    
28 #include "api/c/tt_c.h"
29 #include "util/tt_gettext.h"
30 #include "tttk/tttk.h"
31 #include "tttk/ttdesktop.h"
32 #include "tttk/tttkmessage.h"
33 #include "tttk/tttkpattern.h"
34 #include "tttk/tttkutils.h"
35 #include "tttk/tttk2free.h"
36
37 Tt_status       _tt_ptype_opnum_user_set(const char *ptype, int opnum,
38                                          void *clientdata);
39 void *          _tt_ptype_opnum_user(const char *ptype, int opnum);
40
41 class _Ttmedia_ptype_info: public _Tt_allocated {
42     public:
43         _Ttmedia_ptype_info(
44                 Ttmedia_load_pat_cb     loadCB,
45                 void                   *clientData
46         );
47
48         Ttmedia_load_pat_cb     _loadCB;
49         void                   *_clientData;
50 };
51
52 _Ttmedia_ptype_info::_Ttmedia_ptype_info(
53         Ttmedia_load_pat_cb     loadCB,
54         void                   *clientData)
55 {
56         _loadCB = loadCB;
57         _clientData = clientData;
58 }
59
60 Tt_message
61 ttMediaLoadPatCB(
62         Tt_message      msg,
63         Tt_pattern      ,
64         Ttmedia_load_pat_cb callback,
65         void           *clientData,
66         Tttk_op         op,
67         int             counterfoilArg  = -1,
68         int             docNameArg      = -1
69 )
70 {
71         static const char here[]        = "ttMediaLoadPatCB()";
72         unsigned char     *contents    = 0;
73         int                len         = 0;
74         char              *file        = 0;
75         Tt_status          status;
76         Tt_status          diagnosis   = TT_OK;
77         const char        *diagnosisStr= 0;
78         char              *counterfoil = 0;
79         char              *docName     = 0;
80
81         if (callback == 0) {
82                 return msg;
83         }
84         status = tt_message_arg_bval( msg, 0, &contents, &len );
85         if (status != TT_OK) {
86                 diagnosis = status;
87                 diagnosisStr = "tt_message_arg_bval( msg, 0 )";
88         } else if (len == 0) {
89                 //
90                 // contents arg empty; contents are in named file
91                 //
92                 file = tt_message_file( msg );
93                 status = tt_ptr_error( file );
94                 if (status != TT_OK) {
95                         file = 0;
96                         diagnosis = status;
97                         diagnosisStr = "tt_message_file()";
98                 } else if (   (file == 0)
99                         && (tt_message_arg_mode( msg, 0 ) != TT_OUT)
100                         && (op != TTME_INSTANTIATE))
101                 {
102                         diagnosis = TT_DESKTOP_ENODATA;
103                         diagnosisStr = catgets( _ttcatd, 1, 25,
104                                 "empty document and no file" );
105                 }
106         }
107         if (counterfoilArg >= 0) {
108                 counterfoil = tt_message_arg_val( msg, counterfoilArg );
109                 status = tt_ptr_error( counterfoil );
110                 if (status != TT_OK) {
111                         _ttDtPrintStatus( here,
112                                           catgets( _ttcatd, 1, 26,
113                                                    "cannot get messageID; "
114                                                    "operation may not be "
115                                                    "cancel-able, because "
116                                                    "tt_message_arg_val()"),
117                                           status );
118                         counterfoil = 0;  // charge ahead
119                 }
120         }
121         if (docNameArg > 0) {
122                 docName = tt_message_arg_val( msg, docNameArg );
123                 status = tt_ptr_error( docName );
124                 if (status != TT_OK) {
125                         _ttDtPrintStatus( here,
126                                           catgets( _ttcatd, 1, 27,
127                                                    "cannot get title; document "
128                                                    "will be untitled because "
129                                                    "tt_message_arg_val()" ),
130                                           status );
131                         docName = 0;  // charge ahead
132                 }
133         }
134         msg = (*callback)( msg, clientData, op, diagnosis, contents,
135                            len, file, docName );
136         status = tt_ptr_error( msg );
137         if ((status == TT_OK) && (msg != 0) && (diagnosis != TT_OK)) {
138                 tttk_message_fail( msg, diagnosis, diagnosisStr, 1 );
139                 return (Tt_message)tt_error_pointer( diagnosis );
140         } else {
141                 return msg;
142         }
143 }
144
145 Tt_callback_action
146 _ttMeOpnumCB(
147         Tt_message msg,
148         Tt_pattern pat
149 )
150 {
151         static const char here[] = "_ttMeOpnumCB()";
152
153         if (    (tt_message_state( msg ) != TT_SENT)
154              || (tt_message_class( msg ) != TT_REQUEST )
155              || (! _tttk_message_am_handling( msg )))
156         {
157                 return TT_CALLBACK_CONTINUE;
158         }
159         int opnum = tt_message_opnum( msg );
160         Tt_status status = tt_int_error( opnum );
161         if ((status != TT_OK) && (opnum != -1)) {
162                 return TT_CALLBACK_PROCESSED;
163         }
164         int base = opnum - (opnum % 1000);
165         int offset = opnum - base;
166         char *ptype = tt_message_handler_ptype( msg );
167         _Ttmedia_ptype_info *i = (_Ttmedia_ptype_info *)
168                 _tt_ptype_opnum_user( ptype, base );
169         tt_free( ptype );
170         status = tt_ptr_error( i );
171         if ((status != TT_OK) || (i == 0)) {
172                 return TT_CALLBACK_PROCESSED;
173         }
174         switch (offset) {
175             case 1:
176                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
177                                         TTME_DISPLAY );
178                 break;
179             case 2:
180                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
181                                         TTME_DISPLAY, 1 );
182                 break;
183             case 3:
184                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
185                                         TTME_DISPLAY, -1, 1 );
186                 break;
187             case 4:
188                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
189                                         TTME_DISPLAY, 1, 2 );
190                 break;
191             case 101:
192                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
193                                         TTME_EDIT );
194                 break;
195             case 102:
196                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
197                                         TTME_EDIT, 1 );
198                 break;
199             case 103:
200                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
201                                         TTME_EDIT, -1, 1 );
202                 break;
203             case 104:
204                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
205                                         TTME_EDIT, 1, 2 );
206                 break;
207             case 201:
208                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
209                                         TTME_COMPOSE );
210                 break;
211             case 202:
212                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
213                                         TTME_COMPOSE, 1 );
214                 break;
215             case 203:
216                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
217                                         TTME_COMPOSE, -1, 1 );
218                 break;
219             case 204:
220                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
221                                         TTME_COMPOSE, 1, 2 );
222                 break;
223             case 301:
224                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
225                                         TTME_MAIL );
226                 break;
227             case 311:
228                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
229                                         TTME_MAIL_EDIT );
230                 break;
231             case 313:
232                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
233                                         TTME_MAIL_EDIT, -1, 1 );
234                 break;
235             case 321:
236                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
237                                         TTME_MAIL_COMPOSE );
238                 break;
239             case 323:
240                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
241                                         TTME_MAIL_COMPOSE, -1, 1 );
242                 break;
243             case 401:
244                 msg = ttMediaLoadPatCB( msg, pat, i->_loadCB, i->_clientData,
245                                         TTME_INSTANTIATE );
246                 break;
247             // Add any new offsets to ttmedia_ptype_declare()
248             default:
249                 _ttDtPrintInt( here,
250                                catgets(_ttcatd, 1, 28, "unknown opnum offset"),
251                                offset );
252                 return TT_CALLBACK_CONTINUE;
253         }
254         return _ttDtCallbackAction( msg );
255 }
256
257 Tt_status
258 ttmedia_ptype_declare(
259         const char             *ptype,
260         int                     baseOpnum,
261         Ttmedia_load_pat_cb     loadCB,
262         void                   *clientData,
263         int                     declare
264 )
265 {
266         Tt_status          status;
267
268 /*
269  * XXX Join default contexts of current default procid.
270  */
271         for (int i = 0; i <= 200; i += 100) {
272                 for (int j = 1; j <= 4; j++) {
273                         status = tt_ptype_opnum_callback_add( ptype,
274                                         i + j + baseOpnum, _ttMeOpnumCB );
275                         if (status != TT_OK) {
276                                 return status;
277                         }
278                 }
279         }
280         status = tt_ptype_opnum_callback_add( ptype, 301, _ttMeOpnumCB );
281         if (status != TT_OK) return status;
282         status = tt_ptype_opnum_callback_add( ptype, 311, _ttMeOpnumCB );
283         if (status != TT_OK) return status;
284         status = tt_ptype_opnum_callback_add( ptype, 313, _ttMeOpnumCB );
285         if (status != TT_OK) return status;
286         status = tt_ptype_opnum_callback_add( ptype, 321, _ttMeOpnumCB );
287         if (status != TT_OK) return status;
288         status = tt_ptype_opnum_callback_add( ptype, 323, _ttMeOpnumCB );
289         if (status != TT_OK) return status;
290         status = tt_ptype_opnum_callback_add( ptype, 401, _ttMeOpnumCB );
291         if (status != TT_OK) return status;
292         //
293         // Like opnum callbacks themselves, this memory lives as long
294         // as the procid.
295         //
296         _Ttmedia_ptype_info *info =
297                 new _Ttmedia_ptype_info( loadCB, clientData );
298         status = _tt_ptype_opnum_user_set( ptype, baseOpnum, info );
299         if (status != TT_OK) {
300                 return status;
301         }
302         if (declare) {
303                 status = tt_ptype_declare( ptype );
304                 if (status != TT_OK) {
305                         return status;
306                 }
307         }
308         return TT_OK;
309 }
310
311 //
312 // Parse Display/Edit/Compose reply, or Deposit request, and pass to
313 // client callback.
314 //
315 static Tt_message
316 _ttMediaLoadMsgCB(
317         Tt_message      msg,
318         Tt_pattern      ,
319         void           *clientCB,
320         void           *clientData
321 )
322 {
323         char *opname = tt_message_op( msg );
324         Tttk_op op = tttk_string_op( opname );
325         tt_free( opname );
326         int final = _tttk_message_in_final_state( msg );
327         switch (tt_message_state( msg )) {
328             case TT_STARTED:
329             case TT_QUEUED:
330                 return 0;
331             case TT_SENT:
332                 if (op != TTME_DEPOSIT) {
333                         // This address space is handler, but is not
334                         // through handling, so continue.
335                         return msg;
336                 }
337                 break;
338         }
339         Tt_pattern depositPat = 0;
340         if (final) {
341                 depositPat =
342                         (Tt_pattern)tt_message_user( msg, _TttkDepositPatKey );
343         }
344         Ttmedia_load_msg_cb _cb = (Ttmedia_load_msg_cb)clientCB;
345         if (_cb != 0) {
346                 _TttkItem2Free fuse = msg;
347                 unsigned char     *contents = 0;
348                 int                len      = 0;
349                 Tt_status          status;
350                 status = tt_message_arg_bval( msg, 0, &contents, &len );
351                 if (status != TT_OK) {
352                         return (Tt_message)tt_error_pointer( status );
353                 }
354                 char *file = tt_message_file( msg );
355                 if (tt_ptr_error( file ) != TT_OK) {
356                         file = 0;
357                 }
358                 fuse = (caddr_t)0;
359                 msg = (*_cb)( msg, clientData, op, contents, len, file );
360         }
361         if (final) {
362                 //
363                 // The reply has now come in, so there can be no
364                 // more Deposit requests on this buffer.
365                 //
366                 tt_pattern_destroy( depositPat );
367         }
368         return msg;
369 }
370
371 static Tt_pattern
372 ttmedia_Deposit_pat(
373         Tt_category             category,
374         const char             *media_type,
375         Tt_message              commission,
376         const char             *buffer_id,
377         Ttmedia_load_msg_cb     clientcb,
378         void                   *clientdata,
379         int                     register_it
380 )
381 {
382         Tt_pattern pat = _ttDtPatternCreate( category, TT_SESSION,
383                                              register_it, 0, TTME_DEPOSIT,
384                                              _ttMediaLoadMsgCB, (void *)clientcb,
385                                              clientdata, 0 );
386         Tt_status status = tt_ptr_error( pat );
387         if (status != TT_OK) {
388                 return pat;
389         }
390         _TttkItem2Free fuse = pat;
391         status = tt_pattern_arg_add( pat, TT_IN, media_type, 0 );
392         if (status != TT_OK) {
393                 return (Tt_pattern)tt_error_pointer( status );
394         }
395         if (buffer_id != 0) {
396                 status = tt_pattern_arg_add( pat, TT_IN, "bufferID",
397                                              buffer_id );
398                 if (status != TT_OK) {
399                         return (Tt_pattern)tt_error_pointer( status );
400                 }
401         }
402         fuse = (caddr_t)0;
403         return _ttDesktopPatternFinish( pat, commission, register_it );
404 }
405
406 Tt_message
407 ttmedia_load(
408         Tt_message              context,
409         Ttmedia_load_msg_cb     cb,
410         void                   *clientData,
411         Tttk_op                 op,
412         const char             *mediaType,
413         const unsigned char    *contents,
414         int                     len,
415         const char             *file,
416         const char             *docname,
417         int                     send
418 )
419 {
420         Tt_message msg = _ttDtPMessageCreate( context, TT_REQUEST, TT_SESSION,
421                                 0, op, _ttMediaLoadMsgCB, (void *)cb, clientData );
422         Tt_status status = tt_ptr_error( msg );
423         if (status != TT_OK) {
424                 return msg;
425         }
426         _TttkItem2Free fuse = msg;
427         Tt_mode mode;
428         switch (op) {
429             case TTME_DISPLAY:
430             case TTME_MAIL:
431             case TTME_INSTANTIATE:
432                 mode = TT_IN;
433                 break;
434             case TTME_COMPOSE:
435             case TTME_MAIL_COMPOSE:
436                 mode = TT_OUT;
437                 break;
438             default:
439                 mode = TT_INOUT;
440                 break;
441         }
442         status = tt_message_barg_add( msg, mode, mediaType, contents, len );
443         if (status != TT_OK) {
444                 return (Tt_message)tt_error_pointer( status );
445         }
446         if (file != 0) {
447                 status = tt_message_file_set( msg, file );
448                 if (status != TT_OK) {
449                         return (Tt_message)tt_error_pointer( status );
450                 }
451         }
452         if (docname != 0) {
453                 status = tt_message_arg_add( msg, TT_IN, Tttk_title, docname );
454                 if (status != TT_OK) {
455                         return (Tt_message)tt_error_pointer( status );
456                 }
457         }
458         Tt_pattern pat = ttmedia_Deposit_pat( TT_HANDLE, mediaType,
459                                         msg, 0, cb, clientData, 1 );
460         status = tt_ptr_error( pat );
461         if (status == TT_OK) {
462                 // Save the pattern so we can destroy it when
463                 // the message reaches a final state.
464                 tt_message_user_set( msg, _TttkDepositPatKey, pat );
465         }
466         if (send) {
467                 status = tt_message_send( msg );
468                 if (status != TT_OK) {
469                         return (Tt_message)tt_error_pointer( status );
470                 }
471         }
472         fuse = (caddr_t)0;
473         return msg;
474 }
475
476 Tt_status
477 ttmedia_load_reply(
478         Tt_message              contract,
479         const unsigned char    *newContents,
480         int                     newLen,
481         int                     reply_and_destroy
482 )
483 {
484         Tt_status status = TT_OK;
485         status = tt_message_arg_bval_set( contract, 0, newContents, newLen );
486         if (status != TT_OK) {
487                 return status;
488         }
489         if (reply_and_destroy) {
490                 status = tt_message_reply( contract );
491                 if (status != TT_OK) {
492                         return status;
493                 }
494                 tttk_message_destroy( contract );
495         }
496         return status;
497 }
498
499 Tt_status
500 ttmedia_Deposit(
501         Tt_message              contract,
502         const char             *buffer_id,
503         const char             *media_type,
504         const unsigned char    *new_contents,
505         int                     new_len,
506         const char             *file,
507         XtAppContext            app2run,
508         int                     ms_timeout
509 )
510 {
511         Tt_status status;
512         char *handler = 0;
513         if (buffer_id == 0) {
514                 handler = tt_message_sender( contract );
515                 status = tt_ptr_error( handler );
516                 if (status != TT_OK) {
517                         return status;
518                 }
519         }
520         int replyStatus = 1;
521         Tt_message msg = _ttDtPMessageCreate( contract, TT_REQUEST, TT_SESSION,
522                                 handler, TTME_DEPOSIT, _ttTkNoteReplyStatus,
523                                 0, &replyStatus );
524         tt_free( handler );
525         status = tt_ptr_error( msg );
526         if (status != TT_OK) {
527                 return status;
528         }
529         _TttkItem2Free fuse = msg;
530         const char *_media_type = media_type;
531         if (media_type == 0) {
532                 _media_type = tt_message_arg_type( contract, 0 );
533         }
534         status = tt_message_barg_add( msg, TT_IN, _media_type, new_contents,
535                                       new_len );
536         if (media_type == 0) {
537                 tt_free( (caddr_t)_media_type );
538         }
539         if (status != TT_OK) {
540                 return status;
541         }
542         if (file != 0) {
543                 status = tt_message_file_set( msg, file );
544                 if (status != TT_OK) {
545                         return status;
546                 }
547         }
548         msg = _ttDesktopMessageFinish( msg, contract, 1 );
549         status = tt_ptr_error( msg );
550         if (status != TT_OK) {
551                 return status;
552         }
553         fuse = (caddr_t)0;
554         status = tttk_block_while( app2run, &replyStatus, ms_timeout );
555         if (status == TT_DESKTOP_ETIMEDOUT) {
556                 // See comment in ttdt_Get_Modified()
557                 tttk_message_destroy( msg );
558                 return status;
559         }
560         return (Tt_status)-replyStatus;
561 }