dthelp: Change to ANSI function definitions
[oweals/cde.git] / cde / programs / dtmail / dtmail / Editor.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 libraries 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 /*
24  *+SNOTICE
25  *
26  *      $TOG: Editor.C /main/11 1998/07/24 16:06:00 mgreess $
27  *
28  *      RESTRICTED CONFIDENTIAL INFORMATION:
29  *      
30  *      The information in this document is subject to special
31  *      restrictions in a confidential disclosure agreement between
32  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
33  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
34  *      Sun's specific written approval.  This document and all copies
35  *      and derivative works thereof must be returned or destroyed at
36  *      Sun's request.
37  *
38  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
39  *
40  *+ENOTICE
41  */
42
43 #include <Xm/RowColumn.h>
44 #include <EUSCompat.h>
45 #include <assert.h>
46 #include <stdio.h>
47
48 #include <Dt/Dts.h>
49
50 #include "RoamApp.h"
51 #include "MailMsg.h"
52 #include "Editor.hh"
53 #include "str_utils.h"
54
55 Editor::Editor()
56        : UIComponent("Editor")
57 {
58 }
59
60 Editor::~Editor() 
61 {
62 }
63
64
65 AbstractEditorParent::AbstractEditorParent() {
66         _attachmentPopupMenu = NULL;
67         _textPopupMenu = NULL;
68         _menuPopupAtt = NULL;
69         _menuPopupText = NULL;
70 }
71
72 AbstractEditorParent::~AbstractEditorParent() 
73 {
74         delete _menuPopupAtt;
75         delete _menuPopupText;
76 }   
77
78 DtMailBoolean
79 Editor::set_message(DtMail::Message * msg,
80                     char ** status_string,
81                     HeaderFormat header_format,
82                     InsertFormat format,
83                     BracketFormat brackets)
84 {
85     DtMailEnv error;
86     DtMail::Session *m_session = theRoamApp.session()->session(); 
87     DtMail::MailRc * mail_rc = m_session->mailRc(error);
88
89     *status_string = NULL;
90
91     DtMail::Envelope *env = msg->getEnvelope(error);
92
93     DtMailHeaderHandle hdr_hnd;
94     char *name;
95     DtMailValueSeq value;
96
97     // Here is not the place for getting the indent string 
98     // but it'll do for now.
99     const char *indent_str = NULL;
100     mail_rc->getValue(error, "indentprefix", &indent_str);
101     if (error.isSet()) 
102       indent_str = strdup("> ");
103
104     disable_redisplay();
105
106     int indent = 0;
107
108     if (format == IF_BRACKETED) {
109         char * ins_bracket;
110         switch (brackets) {
111           case BF_FORWARD:
112             ins_bracket = GETMSG(DT_catd, 1, 195, "------------- Begin Forwarded Message -------------\n\n");
113             break;
114             
115           case BF_INCLUDE:
116           default:
117             ins_bracket = GETMSG(DT_catd, 1, 196, "------------- Begin Included Message -------------\n\n");
118             break;
119         }
120
121         append_to_contents(ins_bracket, strlen(ins_bracket));
122     }
123
124     // Code from MsgScrollingList - display_message().
125     // We're trying to reduce heap size by not allocating and 
126     // deleting space in every loop iteration.  So just have a 
127     // fixed size buffer initially.
128     // 
129
130     // Initial line size.  When not enough, allocate more.
131     int line_size = 1024;   
132     int tmp_count = 0;
133     char *line = new char[line_size];
134     int hdr_num = 0;
135
136     if (header_format != HF_NONE) {
137         for ( hdr_hnd = env->getFirstHeader(
138                                             error, 
139                                             &name, 
140                                             value);
141               hdr_hnd && !error.isSet();
142               hdr_hnd = env->getNextHeader(
143                                            error, 
144                                            hdr_hnd, 
145                                            &name, 
146                                            value), hdr_num++ ) {
147             
148             
149             if ((header_format == HF_ABBREV)
150                         && (hdr_num != 0 || strcmp(name, "From") != 0)) {
151                 DtMailEnv ierror;
152                 if (mail_rc->ignore(ierror, name)) {
153                     free(name);
154                     value.clear();
155                     continue;
156                 }
157             }
158             
159             for ( int val = 0;  val < value.length();  val++ ) {
160                 tmp_count = strlen(name) + 
161                     strlen(*(value[val])) +
162                     strlen(indent_str) + 
163                     5;
164                 if ( tmp_count > line_size ) { // Need to increase line size.
165                     delete [] line;
166                     line_size = tmp_count;
167                     line = new char[line_size];
168                 }
169                 memset(line, 0, line_size);
170                 if (format == IF_INDENTED) {
171                     strcpy(line, indent_str);
172                     strcat(line, name);
173                 } else {
174                     strcpy(line, name);
175                 }
176                 
177                 if (hdr_num != 0 || strcmp(name, "From") != 0) {
178                     strcat(line, ": ");
179                 }
180                 else {
181                     strcat(line, " ");
182                 }
183                 
184                 strcat(line, *(value[val]));
185                 strcat(line, "\n");
186                 append_to_contents(line, strlen(line));
187             }
188             value.clear();
189             free(name);
190         }
191     }
192     // Don't delete line yet, because it's used below.
193    
194     if (format == IF_INDENTED) {
195         append_to_contents(indent_str, strlen(indent_str));
196     }
197
198     if (header_format != HF_NONE) {
199         append_to_contents("\n", 1);
200     }
201
202     DtMail::BodyPart *bp = msg->getFirstBodyPart(error);
203    
204     char *type;
205     DtMailBoolean firstBPHandled = DTM_FALSE;
206
207     bp->getContents(error, NULL, NULL, &type, NULL, NULL, NULL);
208     if ( type ) {
209         char *attr = DtDtsDataTypeToAttributeValue(
210                                         type, 
211                                         DtDTS_DA_IS_TEXT, 
212                                         NULL);
213         if ((attr && strcasecmp(attr, "true") == 0)
214             || strcoll(type, DtDTS_DT_UNKNOWN) == 0 ) {
215             const void *contents;
216             unsigned long size;
217             bp->lockContents(error, DtMailLockRead);
218             bp->getContents(error, &contents, &size, NULL, NULL, NULL, NULL);
219
220             if (format == IF_INDENTED) {
221                 int byte_count = 0;
222                 int content_count = (int) size;
223                 const char *last = NULL, *content_ptr = NULL;
224                 // Parse the result of getContents().
225                 // Spit out indent string with each line.
226                 // Is contents NULL terminated???
227                 for ( last = (const char *)contents, 
228                     content_ptr = (const char *)contents;
229                     content_count > 0;
230                     content_ptr++, 
231                     byte_count++, 
232                     content_count-- ) {
233                     if ((*content_ptr == '\n') || 
234                         (content_count == 1) ) {
235                         // 2 for null terminator and new line.
236                         tmp_count = strlen(indent_str) + byte_count + 2;
237                         if ( tmp_count > line_size ) { 
238                            // Need to increase line size.
239                            delete [] line;
240                            line_size = tmp_count;
241                            line = new char[line_size];
242                         }
243                         memset(line, 0, line_size);
244                         strcpy(line, indent_str);
245                         strncat(line, last, byte_count + 1);   
246                         // Copy the '\n' also
247                         append_to_contents(line, strlen(line));
248                         last = content_ptr + 1;
249                         byte_count = -1;
250                     }
251                 }  // end of for loop
252             } else {
253                append_to_contents((const char *)contents, size);
254             }
255             bp->unlockContents(error);
256             firstBPHandled = DTM_TRUE;
257         }
258         if (attr) {
259             DtDtsFreeAttributeValue(attr);
260             attr = NULL;
261         }
262         free(type);
263
264         // DLP: We will turn off this test for now. We need to study the problem
265         // of text checksums more.
266         //
267         //if (bp->checksum(error) == DtMailCheckBad) {
268         //    *status_string = GETMSG(DT_catd, 1, -1, "Digital signature did not match.");
269         //}
270     }
271     delete [] line;
272
273     if (format == IF_BRACKETED) {
274         char * ins_bracket;
275         switch (brackets) {
276           case BF_FORWARD:
277             ins_bracket = GETMSG(DT_catd, 1, 197, "------------- End Forwarded Message -------------\n\n");
278             break;
279             
280           case BF_INCLUDE:
281           default:
282             ins_bracket = GETMSG(DT_catd, 1, 198, "------------- End Included Message -------------\n\n");
283             break;
284         }
285
286         append_to_contents(ins_bracket, strlen(ins_bracket));
287     }
288
289     enable_redisplay();
290
291     if (NULL != indent_str)
292       free((void*) indent_str);
293
294     return(firstBPHandled);
295 }
296
297 void
298 Editor::append_newline_to_contents()
299 {
300     append_to_contents("\n", strlen("\n"));
301 }
302
303
304 void
305 Editor::set_attachment(
306                 DtMail::BodyPart *bp,
307                 InsertFormat format,
308                 BracketFormat brackets)
309 {
310     DtMailEnv error;
311     DtMail::Session *m_session = theRoamApp.session()->session(); 
312     DtMail::MailRc * mail_rc = m_session->mailRc(error);
313     DtMailValueSeq value;
314
315     char                *input, *name, *dttype, *description, *mimetype;
316     const char          *indent_str = NULL;
317     unsigned long       len;
318
319     if (format == IF_INDENTED)
320     {
321         mail_rc->getValue(error, "indentprefix", &indent_str);
322         if (error.isSet()) 
323           indent_str = strdup("> ");
324     }
325
326     disable_redisplay();
327     if ((format == IF_BRACKETED) && (brackets == BF_INCLUDE))
328     {
329         char * ins_bracket =
330           GETMSG(
331                 DT_catd, 1, 249,
332                 "------------- Begin Included Attachment -------------\n\n");
333
334         append_to_contents(ins_bracket, strlen(ins_bracket));
335     }
336     else if (format == IF_INDENTED)
337     {
338         append_to_contents(indent_str, strlen(indent_str));
339         append_newline_to_contents();
340     }
341
342     bp->getContents(error, NULL, &len, &dttype, &name, NULL, &description);
343     
344     if ((NULL != name) && (0 != strlen(name)))
345     {
346         if (NULL != indent_str)
347           append_to_contents(indent_str, strlen(indent_str));
348         input = GETMSG(DT_catd, 1, 251, "       Attachment Name:  ");
349         append_to_contents(input, strlen(input));
350         append_to_contents(name, strlen(name));
351         append_newline_to_contents();
352     }
353
354     if ((NULL != dttype) && (0 != strlen(dttype)))
355     {
356         if (NULL != indent_str)
357           append_to_contents(indent_str, strlen(indent_str));
358         input = GETMSG(DT_catd, 1, 252, "     Attachment DtType:  ");
359         append_to_contents(input, strlen(input));
360         append_to_contents(dttype, strlen(dttype));
361         append_newline_to_contents();
362     }
363
364     bp->getContentType(error, &mimetype);
365     if ((NULL != mimetype) && (0 != strlen(mimetype)))
366     {
367         if (NULL != indent_str)
368           append_to_contents(indent_str, strlen(indent_str));
369         input = GETMSG(DT_catd, 1, 253, "Attachment ContentType:  ");
370         append_to_contents(input, strlen(input));
371         append_to_contents(mimetype, strlen(mimetype));
372         append_newline_to_contents();
373     }
374
375     if ((NULL != description) && (0 != strlen(description)))
376     {
377         if (NULL != indent_str)
378           append_to_contents(indent_str, strlen(indent_str));
379         input = GETMSG(DT_catd, 1, 254, "Attachment Description:  ");
380         append_to_contents(input, strlen(input));
381         append_to_contents(description, strlen(description));
382         append_newline_to_contents();
383     }
384
385     if ((format == IF_BRACKETED) && (brackets == BF_INCLUDE))
386     {
387         char * ins_bracket =
388           GETMSG(
389                 DT_catd, 1, 250,
390                 "------------- End Included Attachment -------------\n\n");
391
392         append_to_contents(ins_bracket, strlen(ins_bracket));
393     }
394     else if (format == IF_INDENTED)
395     {
396         append_to_contents(indent_str, strlen(indent_str));
397         append_newline_to_contents();
398     }
399     enable_redisplay();
400
401     if (NULL != indent_str)
402       free((void*) indent_str);
403     if (NULL != name)
404       free((void*) name);
405     if (NULL != dttype)
406       free((void*) dttype);
407     if (NULL != mimetype)
408       free((void*) mimetype);
409     if (NULL != description)
410       free((void*) description);
411 }
412
413 void
414 Editor::update_display_from_props(void)
415 {
416     int rows, cols;
417     DtMailEnv  error;
418     DtMail::Session * d_session = theRoamApp.session()->session();
419     DtMail::MailRc * mailrc = d_session->mailRc(error);
420     const char * value = NULL;
421
422     mailrc->getValue(error, "popuplines", &value);
423     if (error.isSet()) {
424         value = strdup("24");
425     }
426     rows = (int) strtol(value, NULL, 10);
427     free((void*) value);
428     set_rows(rows);
429
430     // If toolcols is set, overwrite the column width with "toolcols" value.
431     // Otherwise, default resource value will be used.
432     value = NULL;
433     error.clear();
434     mailrc->getValue(error, "toolcols", &value);
435     if (!error.isSet()){
436         cols = (int) strtol(value, NULL, 10);      
437         free((void*) value);
438     } else {
439         /*
440          * MB_CUR_MAX == 1 : SingleByteLanguage
441          * MB_CUR_MAX >  1 : MultiByteLanguage
442          */
443         if ( MB_CUR_MAX == 1 )
444           cols = 80;
445         else
446           cols = 40;
447     }
448     set_columns(cols);
449 }
450
451
452 void 
453 AbstractEditorParent::postAttachmentPopup(XEvent *event)
454 {
455         XmMenuPosition(_attachmentPopupMenu, (XButtonEvent *)event);
456         XtManageChild(_attachmentPopupMenu);
457 }
458
459 void 
460 AbstractEditorParent::postTextPopup(XEvent *event)
461 {
462         if (_textPopupMenu == NULL)
463                 return;
464
465         XmMenuPosition(_textPopupMenu, (XButtonEvent *)event);
466         XtManageChild(_textPopupMenu);
467 }
468