4 * $TOG: DtEditor.C /main/11 1998/02/03 10:28:15 mgreess $
6 * RESTRICTED CONFIDENTIAL INFORMATION:
8 * The information in this document is subject to special
9 * restrictions in a confidential disclosure agreement between
10 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
11 * document outside HP, IBM, Sun, USL, SCO, or Univel without
12 * Sun's specific written approval. This document and all copies
13 * and derivative works thereof must be returned or destroyed at
16 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
21 #ifndef I_HAVE_NO_IDENT
34 #include <X11/IntrinsicP.h>
36 #include <Xm/CutPaste.h>
40 #include "DtEditor.hh"
41 #include "MailMsg.h" // DT_catd defined here
43 CDEM_DtWidgetEditor::CDEM_DtWidgetEditor(
45 DtMailEditor *owner_of_editor
49 my_owner = owner_of_editor;
52 _modified_text = NULL;
53 _modified_text_buflen = 0;
55 begin_ins_bracket = NULL;
57 end_ins_bracket = NULL;
58 _auto_show_cursor = FALSE;
61 _buf_len = (unsigned long) 0;
62 text_already_selected = FALSE;
65 CDEM_DtWidgetEditor::~CDEM_DtWidgetEditor()
68 // No DtEditor API equivalent
69 // Remove the callbacks first.
71 XtRemoveCallback(my_text, DtNtextSelectCallback,
72 &CDEM_DtWidgetEditor::text_selected_callback, this);
73 XtRemoveCallback(my_text, DtNtextDeselectCallback,
74 &CDEM_DtWidgetEditor::text_unselected_callback, this);
75 XtRemoveCallback( my_text, XmNhelpCallback, HelpTexteditCB, this ) ;
77 XtDestroyWidget(my_text);
85 if(_modified_text->ptr) {
86 free(_modified_text->ptr);
87 _modified_text->ptr = NULL;
90 _modified_text = NULL;
92 if (NULL != indent_str)
93 free((void*) indent_str);
97 CDEM_DtWidgetEditor::initialize()
108 DtMail::Session * d_session = theRoamApp.session()->session();
109 DtMail::MailRc * mailrc = d_session->mailRc(error);
111 const char * value = NULL;
112 mailrc->getValue(error, "popuplines", &value);
114 value = strdup("24");
116 rows = strtol(value, NULL, 10);
120 // If toolcols is set, overwrite the column width with "toolcols" value.
121 // Otherwise, default resource value will be used.
123 mailrc->getValue(error, "toolcols", &value);
125 cols = strtol(value, NULL, 10);
126 XtSetArg(args[i], DtNcolumns, cols); i++;
132 * MB_CUR_MAX == 1 : SingleByteLanguage
133 * MB_CUR_MAX > 1 : MultiByteLanguage
135 if ( MB_CUR_MAX == 1 )
140 cols = strtol(value, NULL, 10);
141 XtSetArg(args[i], DtNcolumns, cols); i++;
145 XtSetArg(args[i], DtNeditable, FALSE); i++;
146 XtSetArg(args[i], DtNrows, 24); i++;
147 if ( MB_CUR_MAX == 1 ) {
148 XtSetArg(args[i], DtNcolumns, 80); i++;
150 XtSetArg(args[i], DtNcolumns, 40); i++;
152 XtSetArg(args[i], DtNcursorPositionVisible, FALSE); i++;
154 my_text = DtCreateEditor(my_parent, "Text", args, i);
156 update_display_from_props();
157 XtAddCallback(my_text, DtNtextSelectCallback,
158 &CDEM_DtWidgetEditor::text_selected_callback, this);
159 XtAddCallback(my_text, DtNtextDeselectCallback,
160 &CDEM_DtWidgetEditor::text_unselected_callback, this);
161 XtAddCallback( my_text, XmNhelpCallback, HelpTexteditCB, this ) ;
163 XtAddEventHandler(my_text, ButtonPressMask,
164 FALSE, MenuButtonHandler,
167 XtManageChild(my_text);
173 CDEM_DtWidgetEditor::get_contents()
176 DtEditorErrorCode status;
177 static DtEditorContentRec content;
179 content.type = DtEDITOR_TEXT;
181 // Get the contents with hardCarriageReturns = TRUE and
182 // markContentsAsSaved = TRUE.
185 * If hardCarriageReturns = TRUE, the performace of DtEditorGetContents()
186 * suffers since according to man 3 DtEditorGetContents,
188 * The hardCarriageReturns argument, if set to True, indicates
189 * that the DtEditor widget should replace any soft line feeds
190 * (word wraps) with <newline>s when saving the data. When
191 * hardCarriageReturns is set to False, any line wrapped
192 * because it reaches the right edge of the window is saved as
195 * And current default value of DtNwordWrap is TRUE. See dtmail/Dtmail.
196 * My temporary and non-good solution is
197 * - Change default to False.
198 * - If DtNwordWarp == TRUE,
199 * call DtEditorGetContents(my_text, &content, TRUE, TRUE)
201 * call DtEditorGetContents(my_text, &content, False, TRUE)
202 * This value can be controllable by a resource file or Format menu.
204 * Goofy ? but...................;-(
209 XtSetArg( args[0], DtNwordWrap, &ww );
210 XtGetValues( my_text, args, 1 );
211 status = DtEditorGetContents(my_text, &content, ww, TRUE);
213 return(content.value.string);
217 CDEM_DtWidgetEditor::set_contents(
218 const char *contents,
219 const unsigned long len
222 DtEditorContentRec content;
223 DtEditorErrorCode status;
225 this->my_owner->needBuf(&_buffer, &_buf_len, len + 1);
226 this->my_owner->stripCRLF(&_buffer, contents, len);
228 content.type = DtEDITOR_TEXT;
229 content.value.string = _buffer;
230 status = DtEditorSetContents(my_text, &content);
235 CDEM_DtWidgetEditor::set_contents(
239 DtEditorSetContentsFromFile(my_text, (char *)path);
243 CDEM_DtWidgetEditor::clear_contents()
246 // Doesn't work yet. Work around with setting an empty string...
247 // DtEditorReset(my_text);
249 DtEditorContentRec content;
250 DtEditorErrorCode status;
252 content.type = DtEDITOR_TEXT;
253 content.value.string = NULL;
254 status = DtEditorSetContents(my_text, &content);
259 CDEM_DtWidgetEditor::append_to_contents(
260 const char *contents,
261 const unsigned long len
264 DtEditorContentRec rec;
266 rec.type = DtEDITOR_TEXT;
268 if ( contents[len - 1] == 0 ) {
269 rec.value.string = (char *)contents;
271 this->my_owner->needBuf(&_buffer, &_buf_len, len + 1);
272 this->my_owner->stripCRLF(&_buffer, contents, len);
273 rec.value.string = _buffer;
276 DtEditorInsert(my_text, &rec);
280 CDEM_DtWidgetEditor::append_to_contents(
285 DtEditorAppendFromFile(my_text, (char *)path);
290 CDEM_DtWidgetEditor::append_at_cursor(
294 DtEditorInsertFromFile(my_text, (char *) path);
298 CDEM_DtWidgetEditor::append_at_cursor(
299 const char *contents,
300 const unsigned long len
303 DtEditorContentRec rec;
305 rec.type = DtEDITOR_TEXT;
307 if ( contents[len - 1] == 0 ) {
308 rec.value.string = (char *)contents;
310 this->my_owner->needBuf(&_buffer, &_buf_len, len + 1);
311 this->my_owner->stripCRLF(&_buffer, contents, len);
312 rec.value.string = _buffer;
314 //DtEditorAppend(my_text, &rec);
315 // Fix for the defect 179186 05-25-95
316 // The above API will insert "contents" to the end of the buffer
317 // (appending). It should change to DtEditorInsert which insert
318 // string to the current position (the cursor's position)
319 DtEditorInsert(my_text, &rec);
323 CDEM_DtWidgetEditor::get_text_widget()
325 // We actually need to return the text widget contained
326 // within DtEditor. For now, just return the DtEditor.
332 CDEM_DtWidgetEditor::get_text_foreground()
336 XtVaGetValues(my_text,
337 DtNtextForeground, &fg,
344 // DtEditor returns the bg color of the Form widget, not the
345 // text widget that the Form contains.
346 // This explains why the attachment pane color is that of the scroll bar...
347 // DtEditor needs to return the color of its text widget.
348 // OBTW, DtNtextBackground and DtNtextForeground don't work. They
349 // return uninitialized values
352 CDEM_DtWidgetEditor::get_text_background()
356 XtVaGetValues(my_text,
357 DtNtextBackground, &bg,
364 CDEM_DtWidgetEditor::get_text_fontList()
368 XtVaGetValues(my_text,
369 DtNtextFontList, &fl,
376 CDEM_DtWidgetEditor::get_text_width()
380 XtVaGetValues(my_text,
388 CDEM_DtWidgetEditor::get_editor()
394 CDEM_DtWidgetEditor::get_columns()
397 XtVaGetValues(my_text, DtNcolumns, &ncolumns, NULL);
398 return (int) ncolumns;
403 CDEM_DtWidgetEditor::get_rows()
406 XtVaGetValues(my_text, DtNrows, &nrows, NULL);
411 CDEM_DtWidgetEditor::set_editable(Boolean bval)
413 XtVaSetValues(my_text,
415 DtNcursorPositionVisible, bval,
421 CDEM_DtWidgetEditor::set_columns(int ncolumns)
423 XtVaSetValues(my_text, DtNcolumns, ncolumns, NULL);
428 CDEM_DtWidgetEditor::set_rows(int nrows)
430 XtVaSetValues(my_text, DtNrows, nrows, NULL);
434 CDEM_DtWidgetEditor::undo_edit()
437 DtEditorUndoEdit(my_text);
442 CDEM_DtWidgetEditor::cut_selection()
445 DtEditorCutToClipboard(my_text);
450 CDEM_DtWidgetEditor::copy_selection()
453 DtEditorCopyToClipboard(my_text);
458 CDEM_DtWidgetEditor::paste_from_clipboard()
461 DtEditorPasteFromClipboard(my_text);
466 CDEM_DtWidgetEditor::paste_special_from_clipboard(
467 Editor::InsertFormat format
471 unsigned long length, recvd;
472 char *clipboard_data;
473 Display *dpy = XtDisplayOfObject(my_text);
474 Window window = XtWindowOfObject(my_text);
477 status = XmClipboardInquireLength(dpy, window, "STRING", &length);
478 } while (status == ClipboardLocked);
484 clipboard_data = XtMalloc((unsigned)length);
487 status = XmClipboardRetrieve(
488 dpy, window, "STRING", clipboard_data,
491 } while (status == ClipboardLocked);
493 if (status != ClipboardSuccess || recvd != length) {
496 XtFree(clipboard_data);
500 // Now modify the data such that the necessary formatting occurs
501 // within it. Bracketting will cause a line at the beginning and
502 // end of the data. Indenting will prepend a ">" before each line,
503 // realigning the lines if necessary.
504 // The results are stored in _modified_text so clipboard_data can
505 // be freed immediately after this call.
507 this->modifyData(clipboard_data, (unsigned) length, format);
508 XtFree(clipboard_data);
510 // Now copy the modified data stripped of CRLFs to a buffer.
511 // Put that buffer into the structure appropriate for DtEditor.
513 DtEditorContentRec rec;
515 rec.type = DtEDITOR_TEXT;
517 // Length needs to be reset since the text now contains
518 // new characters that do the necessary formatting.
520 length = _modified_text->length;
522 if ( _modified_text->ptr[(unsigned) length - 1] == 0 ) {
523 rec.value.string = (char *)_modified_text->ptr;
525 this->my_owner->needBuf(
527 (unsigned) length + 1
529 this->my_owner->stripCRLF(
530 &_buffer, _modified_text->ptr,
532 rec.value.string = _buffer;
535 DtEditorInsert(my_text, &rec);
540 CDEM_DtWidgetEditor::clear_selection()
543 DtEditorClearSelection(my_text);
548 CDEM_DtWidgetEditor::delete_selection()
550 DtEditorDeleteSelection(my_text);
554 CDEM_DtWidgetEditor::set_word_wrap(
558 XtVaSetValues(my_text, DtNwordWrap, bval, NULL);
562 CDEM_DtWidgetEditor::set_to_top()
564 XtVaSetValues(my_text,
566 DtNcursorPosition, 0,
572 CDEM_DtWidgetEditor::text_selected_callback(
579 CDEM_DtWidgetEditor *obj=(CDEM_DtWidgetEditor *) clientData;
581 obj->text_selected();
586 CDEM_DtWidgetEditor::text_unselected_callback(
593 CDEM_DtWidgetEditor *obj=(CDEM_DtWidgetEditor *) clientData;
595 obj->text_unselected();
600 CDEM_DtWidgetEditor::text_selected()
603 if (!text_already_selected) {
604 text_already_selected = TRUE;
605 my_owner->owner()->text_selected();
610 CDEM_DtWidgetEditor::text_unselected()
613 my_owner->owner()->text_unselected();
614 text_already_selected = FALSE;
619 CDEM_DtWidgetEditor::find_change()
621 DtEditorInvokeFindChangeDialog(my_text);
625 CDEM_DtWidgetEditor::spell()
627 DtEditorInvokeSpellDialog(my_text);
631 CDEM_DtWidgetEditor::format()
633 DtEditorInvokeFormatDialog(my_text);
637 CDEM_DtWidgetEditor::auto_show_cursor_off()
642 CDEM_DtWidgetEditor::auto_show_cursor_restore()
647 CDEM_DtWidgetEditor::select_all()
649 DtEditorSelectAll(my_text);
653 CDEM_DtWidgetEditor::set_to_bottom()
658 CDEM_DtWidgetEditor::no_text()
660 char *text = get_contents();
661 int text_len = strlen(text);
664 for ( int k = 0; k < text_len; k++ ) {
665 if ( isgraph(text[k]) ) {
676 CDEM_DtWidgetEditor::disable_redisplay()
678 DtEditorDisableRedisplay(my_text);
682 CDEM_DtWidgetEditor::enable_redisplay()
685 DtEditorEnableRedisplay(my_text);
692 * This fucntion modifies the pasted data
693 * with an indent prefix before each new line or brackets it.
697 CDEM_DtWidgetEditor::modifyData(
698 char *sp, // source pointer to the insert string
699 int length, // length does not include '\0' char
700 Editor::InsertFormat insert_format
703 if(_modified_text == NULL)
704 _modified_text = (XmTextBlockRec *)calloc(1,sizeof(XmTextBlockRec));
706 char *maxsp = sp + length; // maxmimum source ptr
708 // Allocate memory rounded off to the nearest BUFINC
709 size_t size_req = (size_t)(((length/BUFINC)+1)*BUFINC);
710 if((_modified_text_buflen < size_req) ||
711 ((_modified_text_buflen > CDEM_DtWidgetEditor::MAXBUFSZ) &&
712 (size_req < CDEM_DtWidgetEditor::MAXBUFSZ)) )
713 reallocPasteBuf(size_req);
715 if(_modified_text->ptr == NULL)
716 return; // No memory available
718 switch( insert_format) {
724 // Get the indent prefix string
725 DtMail::Session *m_session = theRoamApp.session()->session();
726 m_session->mailRc(error)->getValue(error,"indentprefix", &indent_str);
727 if (error.isSet() || NULL == indent_str)
728 indent_str = strdup("> ");
730 size_t indlen = strlen(indent_str);
732 // Copy the src buf into dest, inserting indent before '\n'
735 // Make sure there is enough space
736 // for an indent prefix, one char and a terminating '\0'
737 if(!((ip+indlen+2) < _modified_text_buflen) ) {
738 size_req = (size_t)((((_modified_text_buflen +
739 indlen+2)/BUFINC)+1)*BUFINC);
740 reallocPasteBuf(size_req);
741 if(_modified_text->ptr == NULL)
742 return; // No memory available
745 // Copy the indent string at the beginning
747 memcpy(_modified_text->ptr, indent_str, indlen);
751 // Copy the next byte and check for new line
752 _modified_text->ptr[ip++] = *sp++;
753 if(*(sp-1) == '\n') {
754 memcpy(&_modified_text->ptr[ip], indent_str, indlen);
759 _modified_text->ptr[ip] = '\0'; // terminate with a null char
760 _modified_text->length = ip; // Do not include '\0' char in len
766 if( !begin_ins_bracket)
767 begin_ins_bracket = GETMSG(DT_catd, 1, 201,
768 "\n------------- Begin Included Message -------------\n");
770 end_ins_bracket = GETMSG(DT_catd, 1, 202,
771 "\n------------- End Included Message -------------\n");
773 size_t begin_len = strlen(begin_ins_bracket);
774 size_t end_len = strlen(end_ins_bracket);
776 // Make sure there is enough space
777 if((size_req = length + begin_len + end_len + 1) >
778 _modified_text_buflen) {
779 size_req = (size_t) ((((size_req)/BUFINC)+1)*BUFINC);
780 reallocPasteBuf(size_req);
783 if(_modified_text->ptr == NULL)
786 strcpy(_modified_text->ptr, begin_ins_bracket);
787 strncat(_modified_text->ptr,sp,length);
788 strcat(_modified_text->ptr, end_ins_bracket);
789 _modified_text->length = end_len + begin_len + length;
798 CDEM_DtWidgetEditor::MenuButtonHandler(
804 CDEM_DtWidgetEditor *obj = (CDEM_DtWidgetEditor *)cd;
806 if(event->xany.type != ButtonPress)
809 XButtonEvent *be = (XButtonEvent *)event;
811 if(be->button == Button3)
812 obj->my_owner->owner()->postTextPopup(event);