dtcalc: change from obsoleted MAXFLOAT to FLT_MAX from std C
[oweals/cde.git] / cde / lib / DtWidget / 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 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 /* $TOG: Editor.c /main/24 1999/10/14 16:38:25 mgreess $
24  **********************************<+>*************************************
25  ***************************************************************************
26  **
27  **  File:        Editor.c
28  **
29  **  Project:     Text Editor widget
30  **
31  **  Description:
32  **  -----------
33  **  This is the main source file for the Text Editor widget.
34  **
35  *******************************************************************
36  * (c) Copyright 1996 Digital Equipment Corporation.
37  * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company.
38  * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
39  * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
40  * (c) Copyright 1996 Novell, Inc. 
41  * (c) Copyright 1996 FUJITSU LIMITED.
42  * (c) Copyright 1996 Hitachi.
43  * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
44  ********************************************************************
45  **
46  **************************************************************************
47  **********************************<+>*************************************/
48
49 /*-------------------------------------------------------------
50 **      Include Files
51 */
52
53 #include <ctype.h>
54 #include <stdlib.h>
55
56 #if defined(__hpux) || defined(__osf__) || defined(USL)
57 # include <wchar.h> 
58 #elif defined(__uxp__)
59 # include <widec.h>
60 # include <wctype.h>
61 #elif defined(sun)
62 # if (_XOPEN_VERSION==3)
63 #  include <wctype.h>
64 # else
65 #  include <wchar.h>
66 # endif
67 # include <libintl.h>
68 #elif defined(linux)
69 # include <wctype.h>
70 # define NO_putwc
71 #elif defined(CSRG_BASED)
72 # include <wctype.h>
73 # include <wchar.h>
74 #endif /* linux */
75
76 #include <sys/wait.h>
77 #include "signal.h"
78
79 #include <string.h>
80
81 #include <limits.h>     /* For LINE_MAX definition */
82 #include <sys/errno.h>  /* For Error handling */
83
84 #include "EditorP.h"
85 #include <Dt/Dnd.h>
86 #include "X11/Xutil.h"
87 #include <X11/StringDefs.h>
88 #include <X11/keysymdef.h>
89 #include <Xm/Form.h>
90 #include <Xm/MessageB.h>
91 #include <Xm/MwmUtil.h>
92 #include <Xm/TextF.h>
93 #include <Xm/LabelG.h>
94 #include <Xm/SeparatoG.h>
95 #include <Xm/PushBG.h>
96 #include <Xm/ToggleBG.h>
97 #include <Xm/RowColumn.h>
98
99 /* Need the following for _DtOkString */
100 #include <Dt/DtP.h>
101
102 #include <Dt/DtMsgsP.h>
103 #include <Dt/HourGlass.h>
104
105 #include "DtWidgetI.h"
106
107 /*
108  * Private functions borrowed from Motif.
109  */
110 extern XmTextLineTable _XmTextGetLineTable(Widget widget, int *total_lines);
111 extern char  * _XmStringSourceGetString(XmTextWidget tw,
112                                         XmTextPosition from,
113                                         XmTextPosition to,
114 #if NeedWidePrototypes
115                                         int want_wchar);
116 #else
117                                         Boolean want_wchar);
118 #endif /* NeedWidePrototypes */
119
120
121 /*-------------------------------------------------------------
122 **      Public Interface
123 **-------------------------------------------------------------
124 */
125
126 /********    Public Function Declarations    ********/
127
128 /********    End Public Function Declarations    ********/
129
130 /*-------------------------------------------------------------
131 **      Forward Declarations
132 **-------------------------------------------------------------
133 */
134
135 /********    Static Function Declarations    ********/
136
137 static void     ClassInitialize(void);
138 static void     Initialize(
139                         Widget rw,
140                         Widget nw,
141                         ArgList al,
142                         Cardinal *num_args) ;
143
144 static void     VariableInitialize( 
145                         DtEditorWidget new);
146
147 static void     ValidateResources(
148                         DtEditorWidget new,
149                         DtEditorWidget request);
150
151 static Widget   CreateText(
152                         DtEditorWidget parent);
153
154 static void     extractFontMetrics( 
155                         DtEditorWidget w,
156                         XmFontList fontlist,
157                         int     *height,
158                         int     *width);
159
160 static void     getFontMetrics( 
161                         DtEditorWidget w);
162
163 static void     Destroy(
164                         Widget widget);
165
166 static void     SetStatusLine(
167                         DtEditorWidget  ew,
168                         Boolean statusLineOn);
169
170 static Widget   CreateStatusLine(
171                         DtEditorWidget parent);
172
173 static Boolean  SetValues(
174                         Widget cw,
175                         Widget rw,
176                         Widget nw);
177
178 static void     _DtEditorGetCenterToggleLabel(
179         Widget          wid,
180         int             resource_offset,
181         XtArgVal        *value );
182
183 static void     _DtEditorGetChangeAllButtonLabel(
184         Widget          wid,
185         int             resource_offset,
186         XtArgVal        *value );
187
188 static void     _DtEditorGetChangeButtonLabel(
189         Widget          wid,
190         int             resource_offset,
191         XtArgVal        *value );
192
193 static void     _DtEditorGetChangeFieldLabel(
194         Widget          wid,
195         int             resource_offset,
196         XtArgVal        *value );
197
198 static void     _DtEditorGetColumns(
199         Widget          wid,
200         int             resource_offset,
201         XtArgVal        *value );
202
203 static void     _DtEditorGetCurrentLineLabel(
204         Widget          wid,
205         int             resource_offset,
206         XtArgVal        *value );
207
208 static void     _DtEditorGetCursorPosition(
209         Widget          wid,
210         int             resource_offset,
211         XtArgVal        *value );
212
213 static void     _DtEditorGetFindButtonLabel(
214         Widget          wid,
215         int             resource_offset,
216         XtArgVal        *value );
217
218 static void     _DtEditorGetFindFieldLabel(
219         Widget          wid,
220         int             resource_offset,
221         XtArgVal        *value );
222
223 static void     _DtEditorGetFormatAllButtonLabel(
224         Widget          wid,
225         int             resource_offset,
226         XtArgVal        *value );
227
228 static void     _DtEditorGetFormatParagraphButtonLabel(
229         Widget          wid,
230         int             resource_offset,
231         XtArgVal        *value );
232
233 static void     _DtEditorGetJustifyToggleLabel(
234         Widget          wid,
235         int             resource_offset,
236         XtArgVal        *value );
237
238 static void     _DtEditorGetLeftAlignToggleLabel(
239         Widget          wid,
240         int             resource_offset,
241         XtArgVal        *value );
242
243 static void     _DtEditorGetLeftMarginFieldLabel(
244         Widget          wid,
245         int             resource_offset,
246         XtArgVal        *value );
247
248 static void     _DtEditorGetMaxLength(
249         Widget          wid,
250         int             resource_offset,
251         XtArgVal        *value );
252
253 static void     _DtEditorGetMisspelledListLabel(
254         Widget          wid,
255         int             resource_offset,
256         XtArgVal        *value );
257
258 static void     _DtEditorGetRightAlignToggleLabel(
259         Widget          wid,
260         int             resource_offset,
261         XtArgVal        *value );
262
263 static void     _DtEditorGetRightMarginFieldLabel(
264         Widget          wid,
265         int             resource_offset,
266         XtArgVal        *value );
267
268 static void     _DtEditorGetRows(
269         Widget          wid,
270         int             resource_offset,
271         XtArgVal        *value );
272
273 static void     _DtEditorGetScrollLeftSide(
274         Widget          wid,
275         int             resource_offset,
276         XtArgVal        *value );
277
278 static void     _DtEditorGetScrollTopSide(
279         Widget          wid,
280         int             resource_offset,
281         XtArgVal        *value );
282
283 static void      _DtEditorGetTextBackground(
284         Widget          wid,
285         int             resource_offset,
286         XtArgVal        *value );
287
288 static void      _DtEditorGetTextForeground(
289         Widget          wid,
290         int             resource_offset,
291         XtArgVal        *value );
292
293 static void      _DtEditorGetTopCharacter(
294         Widget          wid,
295         int             resource_offset,
296         XtArgVal        *value );
297
298 static void      _DtEditorGetLineCountLabel(
299         Widget          wid,
300         int             resource_offset,
301         XtArgVal        *value );
302
303 static void     FixWordWrap(               /* XXX Word Wrap workaround */
304         Widget          w,                 /* XXX Word Wrap workaround */
305         Boolean         wrapOn);           /* XXX Word Wrap workaround */
306
307 static void     BackwardChar(
308         Widget          w,
309         XEvent          *event,
310         char            **params,
311         Cardinal        *num_params);
312
313 static void     BackwardPara(
314         Widget          w,
315         XEvent          *event,
316         char            **params,
317         Cardinal        *num_params);
318
319 static void     BackwardWord(
320         Widget          w,
321         XEvent          *event,
322         char            **params,
323         Cardinal        *num_params);
324
325 static void     BeginningOfFile(
326         Widget          w,
327         XEvent          *event,
328         char            **params,
329         Cardinal        *num_params);
330
331 static void     BeginningOfLine(
332         Widget          w,
333         XEvent          *event,
334         char            **params,
335         Cardinal        *num_params);
336
337 static void     ClearSelection(
338         Widget          w,
339         XEvent          *event,
340         char            **params,
341         Cardinal        *num_params);
342
343 static void     CopyClipboard(
344         Widget          w,
345         XEvent          *event,
346         char            **params,
347         Cardinal        *num_params);
348
349 static void     CutClipboard(
350         Widget          w,
351         XEvent          *event,
352         char            **params,
353         Cardinal        *num_params);
354
355 static void     DeleteNextChar(
356         Widget          w,
357         XEvent          *event,
358         char            **params,
359         Cardinal        *num_params);
360
361 static void     DeleteNextWord(
362         Widget          w,
363         XEvent          *event,
364         char            **params,
365         Cardinal        *num_params);
366
367 static void     DeletePrevChar(
368         Widget          w,
369         XEvent          *event,
370         char            **params,
371         Cardinal        *num_params);
372
373 static void     DeletePrevWord(
374         Widget          w,
375         XEvent          *event,
376         char            **params,
377         Cardinal        *num_params);
378
379 static void     DeleteToEOL(
380         Widget          w,
381         XEvent          *event,
382         char            **params,
383         Cardinal        *num_params);
384
385 static void     DeleteToSOL(
386         Widget          w,
387         XEvent          *event,
388         char            **params,
389         Cardinal        *num_params);
390
391 static void     DeselectAll(
392         Widget          w,
393         XEvent          *event,
394         char            **params,
395         Cardinal        *num_params);
396
397 static void     EndOfFile(
398         Widget          w,
399         XEvent          *event,
400         char            **params,
401         Cardinal        *num_params);
402
403 static void     EndOfLine(
404         Widget          w,
405         XEvent          *event,
406         char            **params,
407         Cardinal        *num_params);
408
409 static void     ForwardChar(
410         Widget          w,
411         XEvent          *event,
412         char            **params,
413         Cardinal        *num_params);
414
415 static void     ForwardPara(
416         Widget          w,
417         XEvent          *event,
418         char            **params,
419         Cardinal        *num_params);
420
421 static void     ForwardWord(
422         Widget          w,
423         XEvent          *event,
424         char            **params,
425         Cardinal        *num_params);
426
427 static void     GoToLine(
428         Widget          w,
429         XEvent          *event,
430         char            **params,
431         Cardinal        *num_params);
432
433 static void     GoToLine_I(
434         Widget          w,
435         XEvent          *event,
436         char            **params,
437         Cardinal        *num_params);
438
439 static void     Help(
440         Widget          w,
441         XEvent          *event,
442         char            **params,
443         Cardinal        *num_params);
444
445 static void     InsertString(
446         Widget          w,
447         XEvent          *event,
448         char            **params,
449         Cardinal        *num_params);
450
451 static void     KeySelect(
452         Widget          w,
453         XEvent          *event,
454         char            **params,
455         Cardinal        *num_params);
456
457 static void     NewlineAndBackup(
458         Widget          w,
459         XEvent          *event,
460         char            **params,
461         Cardinal        *num_params);
462
463 static void     NewlineAndIndent(
464         Widget          w,
465         XEvent          *event,
466         char            **params,
467         Cardinal        *num_params);
468
469 static void     NextPage(
470         Widget          w,
471         XEvent          *event,
472         char            **params,
473         Cardinal        *num_params);
474
475 static void     PageLeft(
476         Widget          w,
477         XEvent          *event,
478         char            **params,
479         Cardinal        *num_params);
480
481 static void     PageRight(
482         Widget          w,
483         XEvent          *event,
484         char            **params,
485         Cardinal        *num_params);
486
487 static void     PasteClipboard(
488         Widget          w,
489         XEvent          *event,
490         char            **params,
491         Cardinal        *num_params);
492
493 static void     PreviousPage(
494         Widget          w,
495         XEvent          *event,
496         char            **params,
497         Cardinal        *num_params);
498
499 static void     ProcessCancel(
500         Widget          w,
501         XEvent          *event,
502         char            **params,
503         Cardinal        *num_params);
504
505 static void     ProcessDown(
506         Widget          w,
507         XEvent          *event,
508         char            **params,
509         Cardinal        *num_params);
510
511 static void     ProcessShiftDown(
512         Widget          w,
513         XEvent          *event,
514         char            **params,
515         Cardinal        *num_params);
516
517 static void     ProcessShiftUp(
518         Widget          w,
519         XEvent          *event,
520         char            **params,
521         Cardinal        *num_params);
522
523 static void     ProcessUp(
524         Widget          w,
525         XEvent          *event,
526         char            **params,
527         Cardinal        *num_params);
528
529 static void     QuoteNextChar(
530         Widget          w,
531         XEvent          *event,
532         char            **params,
533         Cardinal        *num_params);
534
535 static void     QuoteNextChar_I(
536         Widget          w,
537         XEvent          *event,
538         char            **params,
539         Cardinal        *num_params);
540
541 static void     SelectAll(
542         Widget          w,
543         XEvent          *event,
544         char            **params,
545         Cardinal        *num_params);
546
547 static void     ToggleInsertMode(
548         Widget          w,
549         XEvent          *event,
550         char            **params,
551         Cardinal        *num_params);
552
553 static void     ToggleInsertMode_I(
554         Widget          w,
555         XEvent          *event,
556         char            **params,
557         Cardinal        *num_params);
558
559 static void     UndoEdit(
560         Widget          w,
561         XEvent          *event,
562         char            **params,
563         Cardinal        *num_params);
564
565 static void     UndoEdit_I(
566         Widget          w,
567         XEvent          *event,
568         char            **params,
569         Cardinal        *num_params);
570
571 static void     Call_TextSelectCallback(
572         DtEditorWidget  editor);
573
574 static void     Call_TextDeselectCallback(
575         DtEditorWidget  editor);
576
577 static void     Editor_SetSelectionProc(
578         XmTextSource    source,
579         XmTextPosition  left,
580         XmTextPosition  right,
581         Time            set_time );
582
583 static void     CallHelpCallback(
584         DtEditorWidget  editor,
585         int             reason);
586
587 static void     HelpEditWindowCB(
588         Widget          w,
589         caddr_t         client_data,
590         caddr_t         call_data );
591
592 static void     HelpStatusCurrentLineCB(
593         Widget          w,
594         caddr_t         client_data,
595         caddr_t         call_data );
596
597 static void     HelpStatusTotalLinesCB(
598         Widget          w,
599         caddr_t         client_data,
600         caddr_t         call_data );
601
602 static void     HelpStatusMessageCB(
603         Widget          w,
604         caddr_t         client_data,
605         caddr_t         call_data );
606
607 static void     HelpStatusOverstrikeCB(
608         Widget          w,
609         caddr_t         client_data,
610         caddr_t         call_data );
611
612 static void     RegisterDropZone( 
613                         DtEditorWidget w );
614
615 static void     UnregisterDropZone( 
616                         DtEditorWidget w );
617
618 static void     SetInfoDialogTitle(
619                         DtEditorWidget editor );
620
621 static int      FormatText ( 
622                         AdjRecPtr pAdjRec );
623
624 static void     AdjustParaCB(
625                         Widget w,
626                         caddr_t client_data,
627                         caddr_t call_data );
628
629 static void     AdjustAllCB(
630                         Widget w,
631                         caddr_t client_data,
632                         caddr_t call_data );
633
634 static DtEditorErrorCode DoAdjust(
635                         DtEditorWidget  editor,
636                         int             leftMargin,
637                         int             rightMargin,
638                         unsigned int    alignment,
639                         XmTextPosition  start,
640                         XmTextPosition  end);
641
642 static void     SetFormatDialogTitle(
643                         DtEditorWidget editor);
644
645 static void     ResetFormatDialog(
646                         DtEditorWidget editor);
647
648 static void     CreateFormatDialog(
649                         DtEditorWidget editor);
650
651 static void     GetAdjustSettings(
652                         DtEditorWidget pPad,
653                         DtEditorFormatSettings  *formatSettings);
654
655 static void     UpdateOverstrikeIndicator( 
656                         DtEditorWidget  widget,
657                         Boolean         overstrikeOn );
658
659 /********    End Static Function Declarations    ********/
660
661
662 /****************************************************************
663  *
664  *      Compatability routines
665  *
666  ****************************************************************/
667 #if defined(NO_putwc)
668 static wint_t putwc(wint_t wc, FILE *stream)
669 {
670     int rc = putc((int) wc, stream);
671     return (wint_t) rc;
672 }
673
674 static wint_t getwc(FILE *stream)
675 {
676     int rc = getc(stream);
677     return (wint_t) rc;
678 }
679 #endif /* NO_putwc */
680
681 /****************************************************************
682  *
683  *      Translations and Actions
684  *
685  ****************************************************************/
686
687 /* 
688  * The following are the translations which DtEditor places (overrides) 
689  * on the scrolled text widget.  If the DtNtextTranslations resource is
690  * set, it will also be added (in override mode) to the text widget.
691  */
692 static char     EditorTranslationTable[] = "\
693         ~s ~c ~m ~a <Key>Return: newline-and-indent()\n\
694         ~s m<Key>osfBackSpace:  I-undo-edit()\n\
695         ~s c<Key>osfBackSpace:  delete-previous-word()\n\
696         s<Key>osfBackSpace:     delete-to-start-of-line()\n\
697         ~s ~c <Key>osfInsert:   I-toggle-insert-mode()\n\
698         <Key>osfUndo:           I-undo-edit()\n\
699         c<Key>g:                I-go-to-line()\n\
700         c<Key>q:                I-quote-next-character()\n\
701         c<Key>z:                I-undo-edit()";
702
703 /*
704  * The following are DtEditor's actions.  A few are internal only (_I
705  * suffix) and will be called by the default translations DtEditor places
706  * on the text widget (see previous comment).  The rest will only be called
707  * from an application with XtCallActionProc().  The main difference is
708  * the internal ones will be passed a text widget ID, while the public
709  * ones will be passed a DtEditor ID.
710  */
711 static XtActionsRec EditorActionTable[] = {
712         {"I-go-to-line",                (XtActionProc)GoToLine_I},
713         {"I-toggle-insert-mode",        (XtActionProc)ToggleInsertMode_I},
714         {"I-undo-edit",                 (XtActionProc)UndoEdit_I},
715         {"I-quote-next-character",      (XtActionProc)QuoteNextChar_I},
716         {"backward-character",          (XtActionProc)BackwardChar},
717         {"backward-paragraph",          (XtActionProc)BackwardPara},
718         {"backward-word",               (XtActionProc)BackwardWord},
719         {"beginning-of-file",           (XtActionProc)BeginningOfFile},
720         {"beginning-of-line",           (XtActionProc)BeginningOfLine},
721         {"clear-selection",             (XtActionProc)ClearSelection},
722         {"copy-clipboard",              (XtActionProc)CopyClipboard},
723         {"cut-clipboard",               (XtActionProc)CutClipboard},
724         {"delete-next-character",       (XtActionProc)DeleteNextChar},
725         {"delete-next-word",            (XtActionProc)DeleteNextWord},
726         {"delete-previous-character",   (XtActionProc)DeletePrevChar},
727         {"delete-previous-word",        (XtActionProc)DeletePrevWord},
728         {"delete-to-end-of-line",       (XtActionProc)DeleteToEOL},
729         {"delete-to-start-of-line",     (XtActionProc)DeleteToSOL},
730         {"deselect-all",                (XtActionProc)DeselectAll},
731         {"end-of-file",                 (XtActionProc)EndOfFile},
732         {"end-of-line",                 (XtActionProc)EndOfLine},
733         {"forward-character",           (XtActionProc)ForwardChar},
734         {"forward-paragraph",           (XtActionProc)ForwardPara}, 
735         {"forward-word",                (XtActionProc)ForwardWord},
736         {"go-to-line",                  (XtActionProc)GoToLine},
737         {"Help",                        (XtActionProc)Help},
738         {"insert-string",               (XtActionProc)InsertString},
739         {"key-select",                  (XtActionProc)KeySelect},
740         {"newline-and-backup",          (XtActionProc)NewlineAndBackup},
741         {"newline-and-indent",          (XtActionProc)NewlineAndIndent},
742         {"next-page",                   (XtActionProc)NextPage},
743         {"page-left",                   (XtActionProc)PageLeft},
744         {"page-right",                  (XtActionProc)PageRight},
745         {"paste-clipboard",             (XtActionProc)PasteClipboard},
746         {"previous-page",               (XtActionProc)PreviousPage},
747         {"process-cancel",              (XtActionProc)ProcessCancel},
748         {"process-down",                (XtActionProc)ProcessDown},
749         {"process-shift-down",          (XtActionProc)ProcessShiftDown},
750         {"process-shift-up",            (XtActionProc)ProcessShiftUp},
751         {"process-up",                  (XtActionProc)ProcessUp},
752         {"quote-next-character",        (XtActionProc)QuoteNextChar},
753         {"select-all",                  (XtActionProc)SelectAll},
754         {"toggle-insert-mode",          (XtActionProc)ToggleInsertMode},
755         {"undo-edit",                   (XtActionProc)UndoEdit},
756 };
757
758 \f
759 /****************************************************************
760  *
761  *      Defines
762  *
763  ****************************************************************/
764
765 #define NL_SETN 1
766
767 #ifdef _AIX
768 #define iswctype(a,b)   is_wctype(a,b)
769 #define wctype(a)       get_wctype(a)
770 #endif /* _AIX */
771
772 #if !(defined(sun) && (_XOPEN_VERSION==3))
773 #if !(defined(__FreeBSD__))
774 #  define iswblank(wc)  iswctype((wc),blnkclass)
775 #  undef getwc                          /* Use the libc function */
776 #endif
777 #if defined(__osf__) || defined(_AIX) /* __osf__ || _AIX */
778 /* function prototype for wctype() was changed to meet spec1170 */
779 /* digital compiler flagged warning */
780 /* IBM defines wctype to get_wctype above - don't use const. */
781          static char *blankString = "space";
782 #elif defined(USL)
783 #   define wctype_t     int
784 #else  /* __osf__ || _AIX */
785    static const char *blankString = "space";
786 #endif /* __osf__ || _AIX */
787    static wctype_t _DtEditor_blankClass;
788 #else
789 #  define wctype_t      int
790 #   if defined(__uxp__)
791 #      if (OSMAJORVERSION < 2)
792          typedef long wint_t ;
793 #      endif
794 #      define WEOF (-1)
795 #   endif /* uxp */
796
797 #  define iswblank(a)   iswspace(a)
798 #     if !defined(__uxp__) 
799 #         define        iswctype(a,b)   _iswctype(a,b)
800 #     endif
801 #     if defined(__uxp__)
802 #         define wcwidth(a)     scrwidth(a)
803 #     else
804 #         define wcwidth(a)     sun_wcwidth(a)
805 #     endif 
806 #endif /* not sun and not uxp */
807
808 #define MAXTABSIZE 100                  /* max legal tabsize    */
809
810
811 /****************************************************************
812  *
813  *  Define misc data structures
814  *
815  ****************************************************************/
816
817 static wctype_t ekinclass = 0;  /* Prop value for "ekinsoku" class */
818 static wctype_t bekinclass = 0; /* Prop value for "bekinsoku" class */
819 static wctype_t blnkclass = 0;  /* Prop value for "Blank" Class */
820 \f
821 /****************************************************************
822  *
823  *  Resource List
824  *
825  ****************************************************************/
826
827 static XmSyntheticResource syn_resources[] =
828 {
829
830         {
831                 DtNcolumns, sizeof(short),
832                 XtOffset (DtEditorWidget, editor.editStuff.columns),
833                 _DtEditorGetColumns, NULL
834         },
835         {
836                 DtNcenterToggleLabel, sizeof (XmString),
837                 XtOffset (DtEditorWidget, editor.formatStuff.centerToggleLabel),
838                 _DtEditorGetCenterToggleLabel, NULL
839         },
840         {
841                 DtNchangeAllButtonLabel, sizeof (XmString),
842                 XtOffset (DtEditorWidget,
843                           editor.searchStuff.changeAllButtonLabel),
844                 _DtEditorGetChangeAllButtonLabel, NULL
845         },
846         {
847                 DtNchangeButtonLabel, sizeof (XmString),
848                 XtOffset(DtEditorWidget, editor.searchStuff.changeButtonLabel),
849                 _DtEditorGetChangeButtonLabel, NULL
850         },
851         {
852                 DtNchangeFieldLabel, sizeof (XmString),
853                 XtOffset(DtEditorWidget, editor.searchStuff.changeFieldLabel),
854                 _DtEditorGetChangeFieldLabel, NULL
855         },
856         {
857                 DtNcurrentLineLabel, sizeof (XmString),
858                 XtOffset(DtEditorWidget, editor.statusStuff.currentLineLabel),
859                 _DtEditorGetCurrentLineLabel, NULL
860         },
861         {
862                 DtNcursorPosition, sizeof (XmTextPosition),
863                 XtOffset(DtEditorWidget, editor.editStuff.cursorPos),
864                 _DtEditorGetCursorPosition, NULL
865         },
866         {
867                 DtNfindButtonLabel, sizeof (XmString),
868                 XtOffset(DtEditorWidget, editor.searchStuff.findButtonLabel),
869                 _DtEditorGetFindButtonLabel, NULL
870         },
871         {
872                 DtNfindFieldLabel, sizeof (XmString),
873                 XtOffset(DtEditorWidget, editor.searchStuff.findFieldLabel),
874                 _DtEditorGetFindFieldLabel, NULL
875         },
876         {
877                 DtNformatAllButtonLabel, sizeof (XmString),
878                 XtOffset(DtEditorWidget, 
879                          editor.formatStuff.formatAllButtonLabel),
880                 _DtEditorGetFormatAllButtonLabel, NULL
881         },
882         {
883                 DtNformatParagraphButtonLabel, sizeof (XmString),
884                 XtOffset(DtEditorWidget,
885                          editor.formatStuff.formatParaButtonLabel),
886                 _DtEditorGetFormatParagraphButtonLabel, NULL
887         },
888         {
889                 DtNjustifyToggleLabel, sizeof (XmString),
890                 XtOffset (DtEditorWidget, 
891                           editor.formatStuff.justifyToggleLabel),
892                 _DtEditorGetJustifyToggleLabel, NULL
893         },
894         {
895                 DtNleftAlignToggleLabel, sizeof (XmString),
896                 XtOffset (DtEditorWidget,  
897                           editor.formatStuff.leftAlignToggleLabel),
898                 _DtEditorGetLeftAlignToggleLabel, NULL
899         },
900         {
901                 DtNleftMarginFieldLabel, sizeof (XmString),
902                 XtOffset (DtEditorWidget,  
903                           editor.formatStuff.leftMarginFieldLabel),
904                 _DtEditorGetLeftMarginFieldLabel, NULL
905         },
906         {
907                 DtNmaxLength, sizeof(int),
908                 XtOffset(DtEditorWidget, editor.editStuff.maxLength),
909                 _DtEditorGetMaxLength, NULL
910         },
911         {
912                 DtNmisspelledListLabel, sizeof (XmString),
913                 XtOffset (DtEditorWidget,  
914                           editor.searchStuff.misspelledListLabel),
915                 _DtEditorGetMisspelledListLabel, NULL
916         },
917         {
918                 DtNrightAlignToggleLabel, sizeof (XmString),
919                 XtOffset (DtEditorWidget,  
920                           editor.formatStuff.rightAlignToggleLabel),
921                 _DtEditorGetRightAlignToggleLabel, NULL
922         },
923         {
924                 DtNrightMarginFieldLabel, sizeof (XmString),
925                 XtOffset (DtEditorWidget,  
926                           editor.formatStuff.rightMarginFieldLabel),
927                 _DtEditorGetRightMarginFieldLabel, NULL
928         },
929         {
930                 DtNrows, sizeof(short),
931                 XtOffset (DtEditorWidget, editor.editStuff.rows),
932                 _DtEditorGetRows, NULL
933         },
934         {
935                 DtNscrollLeftSide, sizeof (Boolean),
936                 XtOffset (DtEditorWidget, editor.editStuff.scrollLeft),
937                 _DtEditorGetScrollLeftSide, NULL
938         },
939         {
940                 DtNscrollTopSide, sizeof (Boolean),
941                 XtOffset (DtEditorWidget, editor.editStuff.scrollTop),
942                 _DtEditorGetScrollTopSide, NULL
943         },
944         {
945                 DtNtextBackground, sizeof(Pixel),
946                 XtOffset (DtEditorWidget, editor.editStuff.background),
947                 _DtEditorGetTextBackground, NULL
948         },
949         {
950                 DtNtextForeground, sizeof(Pixel),
951                 XtOffset (DtEditorWidget, editor.editStuff.foreground),
952                 _DtEditorGetTextForeground, NULL
953         },
954         {
955                 DtNtopCharacter, sizeof(XmTextPosition),
956                 XtOffset (DtEditorWidget, editor.editStuff.topCharacter),
957                 _DtEditorGetTopCharacter, NULL
958         },
959         {
960                 DtNtotalLineCountLabel, sizeof (XmString),
961                 XtOffset (DtEditorWidget, editor.statusStuff.totalLineLabel),
962                 _DtEditorGetLineCountLabel, NULL
963         },
964 };
965 \f
966 static XtResource resources[] =
967 {
968         {
969                 DtNautoShowCursorPosition,
970                 DtCAutoShowCursorPosition, XmRBoolean, sizeof (Boolean),
971                 XtOffset(DtEditorWidget, 
972                          editor.editStuff.autoShowCursorPos),
973                 XmRImmediate, (XtPointer) True
974         },
975         {
976                 DtNbuttonFontList, DtCFontList, XmRFontList, sizeof(XmFontList),
977                 XtOffsetOf(struct _XmBulletinBoardRec, 
978                            bulletin_board.button_font_list),
979                 XmRFontList, (XtPointer) NULL
980         },
981         {
982                 DtNblinkRate, DtCBlinkRate, XmRInt, sizeof(int),
983                 XtOffset(DtEditorWidget, editor.editStuff.blinkRate),
984                 XmRImmediate, (XtPointer) 500
985         },
986         {
987                 DtNcenterToggleLabel, DtCCenterToggleLabel, 
988                 XmRXmString, sizeof (XmString),
989                 XtOffset (DtEditorWidget, editor.formatStuff.centerToggleLabel),
990                 XmRImmediate, (XtPointer) DtUNSPECIFIED
991         },
992         {
993                 DtNchangeAllButtonLabel, DtCChangeAllButtonLabel, 
994                 XmRXmString, sizeof (XmString),
995                 XtOffset (DtEditorWidget,
996                           editor.searchStuff.changeAllButtonLabel),
997                 XmRImmediate, (XtPointer) DtUNSPECIFIED
998         },
999         {
1000                 DtNchangeButtonLabel, DtCChangeButtonLabel, 
1001                 XmRXmString, sizeof (XmString),
1002                 XtOffset(DtEditorWidget, editor.searchStuff.changeButtonLabel),
1003                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1004         },
1005         {
1006                 DtNchangeFieldLabel, DtCChangeFieldLabel, 
1007                 XmRXmString, sizeof (XmString),
1008                 XtOffset(DtEditorWidget, editor.searchStuff.changeFieldLabel),
1009                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1010         },
1011         {
1012                 DtNcolumns, DtCColumns, XmRShort, sizeof(short),
1013                 XtOffset (DtEditorWidget, editor.editStuff.columns),
1014                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1015         },
1016         {
1017                 DtNcurrentLineLabel, DtCCurrentLineLabel, 
1018                 XmRXmString, sizeof (XmString),
1019                 XtOffset(DtEditorWidget, editor.statusStuff.currentLineLabel),
1020                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1021         },
1022         {
1023                 DtNcursorPosition, DtCCursorPosition, XmRTextPosition,
1024                 sizeof (XmTextPosition),
1025                 XtOffset(DtEditorWidget, editor.editStuff.cursorPos),
1026                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1027         },
1028         {
1029                 DtNcursorPositionVisible, DtCCursorPositionVisible, 
1030                 XmRBoolean, sizeof (Boolean), 
1031                 XtOffset(DtEditorWidget, 
1032                          editor.editStuff.cursorPosVisible),
1033                 XmRImmediate, (XtPointer) True
1034         },
1035         {
1036                 DtNdialogTitle, DtCDialogTitle, XmRXmString, sizeof (XmString),
1037                 XtOffsetOf(struct _XmBulletinBoardRec, 
1038                            bulletin_board.dialog_title),
1039                 XmRString, (XtPointer) NULL
1040         },
1041         {
1042                 DtNeditable, DtCEditable, XmRBoolean, sizeof (Boolean),
1043                 XtOffset (DtEditorWidget, editor.editStuff.editable),
1044                 XmRImmediate, (XtPointer) True
1045         },
1046         {
1047                 DtNfindButtonLabel, DtCFindButtonLabel, 
1048                 XmRXmString, sizeof (XmString),
1049                 XtOffset(DtEditorWidget, editor.searchStuff.findButtonLabel),
1050                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1051         },
1052         {
1053                 DtNfindChangeDialogTitle, DtCFindChangeDialogTitle, 
1054                 XmRXmString, sizeof (XmString),
1055                 XtOffset(DtEditorWidget, editor.searchStuff.fndChngTitle),
1056                 XmRString, (XtPointer) NULL
1057         },
1058         {
1059                 DtNfindFieldLabel, DtCFindFieldLabel, 
1060                 XmRXmString, sizeof (XmString),
1061                 XtOffset(DtEditorWidget, editor.searchStuff.findFieldLabel),
1062                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1063         },
1064         {
1065                 DtNformatAllButtonLabel, DtCFormatAllButtonLabel, 
1066                 XmRXmString, sizeof (XmString),
1067                 XtOffset(DtEditorWidget, 
1068                          editor.formatStuff.formatAllButtonLabel),
1069                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1070         },
1071         {
1072                 DtNformatParagraphButtonLabel, DtCFormatParagraphButtonLabel, 
1073                 XmRXmString, sizeof (XmString),
1074                 XtOffset(DtEditorWidget, 
1075                          editor.formatStuff.formatParaButtonLabel),
1076                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1077         },
1078         {
1079                 DtNformatSettingsDialogTitle, DtCFormatSettingsDialogTitle, 
1080                 XmRXmString, sizeof (XmString),
1081                 XtOffset(DtEditorWidget, editor.formatStuff.formatDialogTitle),
1082                 XmRString, (XtPointer) NULL
1083         },
1084         {
1085                 DtNinformationDialogTitle, DtCInformationDialogTitle, 
1086                 XmRXmString, sizeof (XmString),
1087                 XtOffset(DtEditorWidget, editor.warningStuff.infoDialogTitle),
1088                 XmRString, (XtPointer) NULL
1089         },
1090         {
1091                 DtNinsertLabel, DtCInsertLabel, XmRXmString, sizeof (XmString),
1092                 XtOffset (DtEditorWidget, editor.statusStuff.ins),
1093                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1094         },
1095         {
1096                 DtNjustifyToggleLabel, DtCJustifyToggleLabel, 
1097                 XmRXmString, sizeof (XmString),
1098                 XtOffset(DtEditorWidget, editor.formatStuff.justifyToggleLabel),
1099                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1100         },
1101         {
1102                 DtNlabelFontList, DtCFontList, XmRFontList, sizeof(XmFontList),
1103                 XtOffsetOf(struct _XmBulletinBoardRec, 
1104                            bulletin_board.label_font_list),
1105                 XmRFontList, (XtPointer) NULL
1106         },
1107         {
1108                 DtNleftAlignToggleLabel, DtCLeftAlignToggleLabel, 
1109                 XmRXmString, sizeof (XmString),
1110                 XtOffset(DtEditorWidget, 
1111                          editor.formatStuff.leftAlignToggleLabel),
1112                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1113         },
1114         {
1115                 DtNleftMarginFieldLabel, DtCLeftMarginFieldLabel, 
1116                 XmRXmString, sizeof (XmString),
1117                 XtOffset(DtEditorWidget, 
1118                          editor.formatStuff.leftMarginFieldLabel),
1119                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1120         },
1121         {
1122                 DtNmaxLength, DtCMaxLength, XmRInt, sizeof(int),
1123                 XtOffset(DtEditorWidget, editor.editStuff.maxLength),
1124                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1125         },
1126         {
1127                 DtNmisspelledListLabel, DtCMisspelledListLabel, 
1128                 XmRXmString, sizeof (XmString),
1129                 XtOffset (DtEditorWidget,  
1130                           editor.searchStuff.misspelledListLabel),
1131                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1132         },
1133         {
1134                 DtNoverstrike, DtCOverstrike, XmRBoolean, sizeof (Boolean),
1135                 XtOffset(DtEditorWidget, editor.editStuff.overstrikeMode),
1136                 XmRImmediate, (XtPointer) False
1137         },
1138         {
1139                 DtNoverstrikeLabel, DtCOverstrikeLabel, 
1140                 XmRXmString, sizeof (XmString),
1141                 XtOffset (DtEditorWidget, editor.statusStuff.ovr),
1142                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1143         },
1144         {
1145                 DtNrightAlignToggleLabel, DtCRightAlignToggleLabel, 
1146                 XmRXmString, sizeof (XmString),
1147                 XtOffset(DtEditorWidget, 
1148                          editor.formatStuff.rightAlignToggleLabel),
1149                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1150         },
1151         {
1152                 DtNrightMarginFieldLabel, DtCRightMarginFieldLabel, 
1153                 XmRXmString, sizeof (XmString),
1154                 XtOffset(DtEditorWidget, 
1155                          editor.formatStuff.rightMarginFieldLabel),
1156                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1157         },
1158         {
1159                 DtNrows, DtCRows, XmRShort, sizeof(short),
1160                 XtOffset (DtEditorWidget, editor.editStuff.rows),
1161                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1162         },
1163         {
1164                 DtNscrollHorizontal, DtCScroll, XmRBoolean, sizeof (Boolean),
1165                 XtOffset (DtEditorWidget, editor.editStuff.scrollHorizontal),
1166                 XmRImmediate, (XtPointer) True
1167         },
1168         {
1169                 DtNscrollLeftSide, DtCScrollSide, XmRBoolean, sizeof (Boolean),
1170                 XtOffset (DtEditorWidget, editor.editStuff.scrollLeft),
1171                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1172         },
1173         {
1174                 DtNscrollTopSide, DtCScrollSide, XmRBoolean, sizeof (Boolean),
1175                 XtOffset (DtEditorWidget, editor.editStuff.scrollTop),
1176                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1177         },
1178         {
1179                 DtNscrollVertical, DtCScroll, XmRBoolean, sizeof (Boolean),
1180                 XtOffset (DtEditorWidget, editor.editStuff.scrollVertical),
1181                 XmRImmediate, (XtPointer) True
1182         },
1183         {
1184                 DtNshowStatusLine,
1185                 DtCShowStatusLine, XmRBoolean, sizeof (Boolean),
1186                 XtOffset (DtEditorWidget, editor.statusStuff.showStatusLine),
1187                 XmRImmediate, (XtPointer) False
1188         },
1189         {
1190                 DtNspellDialogTitle, DtCSpellDialogTitle, 
1191                 XmRXmString, sizeof (XmString),
1192                 XtOffset(DtEditorWidget, editor.searchStuff.spellTitle),
1193                 XmRString, (XtPointer) NULL
1194         },
1195         {
1196                 DtNspellFilter, DtCSpellFilter, XmRString, sizeof(XmRString),
1197                 XtOffset (DtEditorWidget, editor.searchStuff.spellFilter),
1198                 XmRString, "spell"
1199         },
1200         {
1201                 DtNtextBackground, DtCBackground, 
1202                 XmRPixel, sizeof(Pixel),
1203                 XtOffset (DtEditorWidget, editor.editStuff.background),
1204                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1205         },
1206         {
1207                 DtNtextDeselectCallback,
1208                 DtCCallback, XtRCallback, sizeof (XtCallbackList),
1209                 XtOffset (DtEditorWidget, editor.textDeselect),
1210                 XtRCallback, (XtPointer) NULL
1211         },
1212         {
1213                 DtNtextForeground, DtCForeground, 
1214                 XmRPixel, sizeof(Pixel),
1215                 XtOffset (DtEditorWidget, editor.editStuff.foreground),
1216                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1217         },
1218         {
1219                 DtNtextFontList, DtCFontList, XmRFontList, sizeof(XmFontList),
1220                 XtOffsetOf(struct _XmBulletinBoardRec, 
1221                            bulletin_board.text_font_list),
1222                 XmRFontList, (XtPointer) NULL
1223         },
1224         {
1225                 DtNtextSelectCallback,
1226                 DtCCallback, XtRCallback, sizeof (XtCallbackList),
1227                 XtOffset (DtEditorWidget, editor.textSelect),
1228                 XtRCallback, (XtPointer) NULL
1229         },
1230         {
1231                 DtNtextTranslations, DtCTranslations,
1232                 XmRTranslationTable, sizeof (XtTranslations),
1233                 XtOffsetOf(struct _XmBulletinBoardRec, 
1234                            bulletin_board.text_translations),
1235                 XmRImmediate, (XtPointer) NULL
1236         },
1237         {
1238                 DtNtopCharacter, DtCTopCharacter, 
1239                 XmRTextPosition, sizeof(XmTextPosition),
1240                 XtOffset (DtEditorWidget, editor.editStuff.topCharacter),
1241                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1242         },
1243         {
1244                 DtNtotalLineCountLabel, DtCTotalLineCountLabel, 
1245                 XmRXmString, sizeof (XmString),
1246                 XtOffset (DtEditorWidget, 
1247                           editor.statusStuff.totalLineLabel),
1248                 XmRImmediate, (XtPointer) DtUNSPECIFIED
1249         },
1250         {
1251                 DtNwordWrap,
1252                 DtCWordWrap, XmRBoolean, sizeof (Boolean),
1253                 XtOffset (DtEditorWidget, editor.editStuff.wordWrap),
1254                 XmRImmediate, (XtPointer) False
1255         },
1256 };
1257
1258 /****************************************************************
1259  *
1260  *  Public Function Declarations
1261  *
1262  ****************************************************************/
1263
1264 /****************************************************************
1265  *
1266  *  Class Record
1267  *
1268  ****************************************************************/
1269
1270 externaldef( dteditorclassrec ) DtEditorClassRec 
1271 dtEditorClassRec =
1272 {
1273 /*      Core Part
1274 */
1275         {       
1276                 (WidgetClass) &xmFormClassRec,  /* superclass   */
1277                 "DtEditor",                     /* class_name           */
1278                 sizeof (DtEditorRec),           /* widget_size          */
1279                 ClassInitialize,                /* class_initialize     */
1280                 NULL,                           /* class_part_initialize*/
1281                 False,                          /* class_inited         */
1282                 (XtInitProc) Initialize,        /* initialize           */
1283                 NULL,                           /* initialize_hook      */
1284                 XtInheritRealize,               /* realize              */
1285                 (XtActionList)EditorActionTable,/* actions              */
1286                 (Cardinal)XtNumber(EditorActionTable), /* num_actions   */
1287                 resources,                      /* resources            */
1288                 XtNumber (resources),           /* num_resources        */
1289                 NULLQUARK,                      /* xrm_class            */
1290                 True,                           /* compress_motion      */
1291                 XtExposeCompressMaximal,        /* compress_exposure    */
1292                 False,                          /* compress_enterleave  */
1293                 False,                          /* visible_interest     */      
1294                 (XtWidgetProc) Destroy,         /* destroy              */      
1295                 XtInheritResize,                /* resize               */
1296                 XtInheritExpose,                /* expose               */      
1297                 (XtSetValuesFunc) SetValues,    /* set_values           */      
1298                 NULL,                           /* set_values_hook      */
1299                 XtInheritSetValuesAlmost,       /* set_values_almost    */
1300                 NULL,                           /* get_values_hook      */
1301                 XtInheritAcceptFocus,           /* accept_focus         */      
1302                 XtVersion,                      /* version              */
1303                 NULL,                           /* callback private     */
1304                 XtInheritTranslations,          /* tm_table             */
1305                 XtInheritQueryGeometry,         /* query_geometry       */
1306                 (XtStringProc)NULL,             /* display_accelerator  */
1307                 NULL,                           /* extension            */
1308         },
1309
1310 /*      Composite Part
1311 */
1312         {
1313                 XtInheritGeometryManager,       /* geometry_manager     */
1314                 XtInheritChangeManaged,         /* change_managed       */
1315                 XtInheritInsertChild,           /* insert_child         */
1316                 XtInheritDeleteChild,           /* delete_child         */
1317                 NULL,                           /* extension            */
1318         },
1319
1320
1321 /*      Constraint Part
1322 */
1323         {
1324                 NULL,                           /* constraint_resources    */
1325                 0,                              /* num_constraint_resource */
1326                 sizeof(XmFormConstraintRec),    /* size of constraint      */
1327                 NULL,                           /* initialization          */
1328                 NULL,                           /* constraint_destroy      */
1329                 NULL,                           /* constraint_set_values   */
1330                 NULL,                           /* extension               */
1331         },
1332
1333 /*      XmManager Part
1334 */
1335         {
1336                 XmInheritTranslations,          /* default_translations */
1337                 syn_resources,                  /* syn_resources        */
1338                 XtNumber(syn_resources),        /* num_syn_resources    */
1339                 NULL,                           /* syn_cont_resources   */
1340                 0,                              /* num_syn_cont_resources */
1341                 XmInheritParentProcess,         /* parent_process       */
1342                 NULL,                           /* extension            */
1343         },
1344
1345 /* XmbulletinBoard Part
1346 */
1347    {  
1348       FALSE,                            /* always_install_accelerators */
1349       (XmGeoCreateProc)NULL,                    /* geo_matrix_create  */
1350       XmInheritFocusMovedProc,                  /* focus_moved_proc   */
1351       NULL,                                     /* extension          */
1352    },
1353
1354 /*      XmForm Part 
1355 */
1356         {
1357                 NULL,                   /* extension            */
1358         },
1359
1360 /*      DtEditor Part
1361 */
1362         {
1363                 0,                      /* extension            */
1364         }
1365 };
1366
1367 WidgetClass dtEditorWidgetClass = (WidgetClass) &dtEditorClassRec;
1368
1369 /*-------------------------------------------------------------
1370 **      Editor Procs
1371 **-------------------------------------------------------------
1372 */
1373
1374 /****************************************************************
1375  *
1376  *  Private Procs
1377  *
1378  ****************************************************************/
1379
1380
1381 /*-------------------------------------------------------------
1382 **      Function: static void ClassInitialize (void);
1383 **
1384 **      Parameters:
1385 **
1386 **      Purpose:    This is the Editor class initializzation routine.
1387 **                  It is called once, before the first instance
1388 **                  is created.
1389 */
1390 static void
1391 ClassInitialize(void)
1392 {
1393 #if !(defined(sun) && (_XOPEN_VERSION==3)) && !defined(USL) && !defined(__uxp__)
1394   _DtEditor_blankClass = wctype(blankString);
1395
1396   /*
1397    ** These calls determine if the particular value is True for
1398    ** the current locale. A value of -1 is returned if the locale
1399    ** does not support the charclass. If the locale supports the
1400    ** charclass, the return value is passed as a parameter to the
1401    ** iswctype call.
1402    */
1403   ekinclass = wctype("ekinsoku");
1404   bekinclass = wctype("bkinsoku");
1405   blnkclass = wctype("blank");
1406 #endif /* end not Sun */
1407 }
1408
1409
1410 /*-------------------------------------------------------------
1411 **      Function: static void Initialize (
1412 **                              Widget rw,
1413 **                              Widget nw,
1414 **                              ArgList arg_list,
1415 **                              Cardinal *num_args)
1416 **
1417 **      Parameters:
1418 **
1419 **      Purpose:    This is the Editor widget initialize routine.
1420 **                  It is responsible for the following:
1421 **                      1) Validate all resources the user passed in,
1422 **                      2) Override any invalid resources,
1423 **                      3) Initialize the internal data structures,
1424 **                      4) Create the edit area widget
1425 **                      5) Create the status area widget, if requested
1426 **                      6) Add any callbacks and actions
1427 */
1428 static void
1429 Initialize(
1430         Widget rw,
1431         Widget nw,
1432         ArgList arg_list,
1433         Cardinal *num_args)
1434 {
1435
1436   DtEditorWidget  request = (DtEditorWidget) rw,
1437                   new     = (DtEditorWidget) nw;
1438
1439   /* Initialize non-resource portion of the instance structure */
1440   VariableInitialize (new);
1441
1442   /* Validate the incoming arguments to make sure they are OK */
1443   ValidateResources (new, request);
1444
1445   /* 
1446    * Create & customize the scrolled text widget 
1447    */
1448   M_text(new) = CreateText (new);
1449   XtManageChild( M_text(new)) ;
1450
1451   /*
1452    * If the widget is not "read only" then register it as a drop zone
1453    */
1454   if ( M_editable(new) == True )
1455      RegisterDropZone( new );
1456
1457   /* 
1458    * Compute the width & height of the scrolled text's font.  These values 
1459    * will be used when formatting and in calculating the window manager 
1460    * hints.  
1461    */
1462   getFontMetrics(new);
1463
1464   /*
1465    *  Create the status line
1466    */ 
1467   SetStatusLine( new, M_status_showStatusLine(request) );
1468
1469
1470 } /* end Initialize */
1471
1472
1473 /*-------------------------------------------------------------
1474 **      Function: static void VariableInitialize (
1475 **                              DtEditorWidget new )
1476 **
1477 **      Parameters: The Editor widget being created
1478 **
1479 **      Purpose:    This routine:
1480 **                      1) Initializes the widget's instance structure
1481 */
1482 static void
1483 VariableInitialize(
1484         DtEditorWidget new)
1485 {
1486   Widget                thisParent;
1487
1488   /* 
1489    * Initialize the non-resource instance fields
1490    */
1491
1492   M_display(new) = XtDisplayOfObject( (Widget)new->core.parent );
1493   M_app_context(new) = XtDisplayToApplicationContext(M_display(new));
1494
1495   /*
1496    * Empty 'for' walks up the widget tree to find a shell.
1497    */
1498   for (thisParent = new->core.parent; 
1499        thisParent != (Widget)NULL && XtIsShell(thisParent) == False;
1500        thisParent = XtParent(thisParent));
1501   M_topLevelShell(new) = thisParent;
1502
1503   /* Initialize edit area fields                                  */
1504   M_loadingAllNewData(new) = False;
1505   M_unreadChanges(new) = False;     /* There have not been any changes since */
1506                                     /* the app requested the data            */
1507   M_deletionStart(new) = NO_DELETION_IN_PROGRESS;
1508   M_deletedText(new) = (char *)NULL;
1509   M_insertStart(new) = 0;
1510   M_insertionLength(new) = 0;
1511   M_textSelectCbCalled(new) = False;
1512   M_fontWidth(new) = -1;
1513
1514   /* Initialize status line fields                                 */
1515   M_status_statusArea(new) = (Widget)NULL;
1516   M_status_messageText(new) = (Widget)NULL;
1517   M_status_currentLine(new) = -1;
1518   M_status_lastLine(new) = -1;
1519
1520   /* Initialize search function data                               */
1521   M_search_dialog(new) = (Widget) NULL;
1522   M_search_dialogMode(new) = SPELL;
1523   M_search_string(new) = (char *)NULL;
1524   M_replace_string(new) = (char *)NULL;
1525   M_misspelled_string(new) = (char *)NULL;
1526   M_misspelled_found(new) = False;
1527
1528   /* Initialize format function data                               */
1529   M_format_dialog(new) = (Widget)NULL;
1530
1531   /* Initialize warning dialogs data                               */
1532   M_gen_warning(new) = (Widget)NULL;
1533
1534 } /* end VariableInitialize */
1535
1536
1537 /*-------------------------------------------------------------
1538 **      Function: static void ValidateResources (
1539 **                              DtEditorWidget new,
1540 **                              DtEditorWidget request )
1541 **
1542 **      Parameters: The Editor widget being created & its requested
1543 **                  resource values
1544 **
1545 **      Purpose:    This routine:
1546 **                      1) Validates the widget's requested resources
1547 */
1548 static void
1549 ValidateResources(
1550         DtEditorWidget new,
1551         DtEditorWidget request)
1552 {
1553   /* 
1554    * Validate the requested values for the editor's resources
1555    */
1556
1557   /* 
1558    * Make local copies of all resource strings assigned by the application. 
1559    */
1560
1561   if (M_spellFilter(request) != (char *) NULL)
1562     M_spellFilter(new) = XtNewString( M_spellFilter(request) );
1563
1564   /* 
1565    * Copy the dialog titles if the application set them, otherwise, 
1566    * get their values from the message catalog.
1567    */
1568
1569   if (M_spellTitle(request) != (XmString) NULL)
1570     M_spellTitle(new) = XmStringCopy( M_spellTitle(request) );
1571   else
1572     M_spellTitle(new) = XmStringCreateLocalized(SPELL_TITLE);
1573
1574   if (M_fndChngTitle(request) != (XmString) NULL)
1575     M_fndChngTitle(new) = XmStringCopy( M_fndChngTitle(request) );
1576   else
1577     M_fndChngTitle(new) = XmStringCreateLocalized(FIND_TITLE);
1578
1579   if (E_format_dialogTitle(request) != (XmString) NULL)
1580     E_format_dialogTitle(new) = XmStringCopy( E_format_dialogTitle(request) );
1581   else
1582     E_format_dialogTitle(new) = XmStringCreateLocalized(FORMAT_SETTINGS);
1583
1584   if (E_infoDialogTitle(request) != (XmString) NULL)
1585     E_infoDialogTitle(new) = XmStringCopy( E_infoDialogTitle(request) );
1586   else
1587     E_infoDialogTitle(new) = XmStringCreateLocalized(INFO_TITLE);
1588
1589   /* 
1590    * Copy the insert & overstrike label indicators if the appli-
1591    * cation set them, otherwise, get their value from the message 
1592    * catalog.
1593    * Check for DtUNSPECIFIED because NULL is a valid value.
1594    */
1595
1596   if (M_status_insertLabel(request) != (XmString) DtUNSPECIFIED)
1597     M_status_insertLabel(new) = 
1598                         XmStringCopy( M_status_insertLabel(request) );
1599   else
1600     M_status_insertLabel(new) = XmStringCreateLocalized(INS);
1601
1602   if (M_status_overstrikeLabel(request) != (XmString) DtUNSPECIFIED)
1603     M_status_overstrikeLabel(new) = 
1604                         XmStringCopy( M_status_overstrikeLabel(request) );
1605   else
1606     M_status_overstrikeLabel(new) = XmStringCreateLocalized(OVR);
1607
1608 } /* end ValidateResources */
1609
1610
1611 /*-------------------------------------------------------------
1612 **      Function: static Widget CreateText (
1613 **                              DtEditorWidget parent)
1614 **
1615 **      Parameters: The parent of the text widget
1616 **
1617 **      Purpose:    This routine creates the scrolled text widget which
1618 **                  lives inside the editor widget.
1619 **                  It is responsible for the following:
1620 **                      1) Creating the scrolled text widget,
1621 **                      2) Adding specific translations,
1622 **                      3) Adding our own callbacks,
1623 **                      4) Substituting our own set selection routine.
1624 */
1625 static Widget
1626 CreateText(
1627         DtEditorWidget parent)
1628 {
1629     register            int ac;         /* arg count */
1630     Arg                 al[21];         /* arg list */
1631     Widget              text;
1632
1633    /* 
1634     * First, set up the hardwired scrolled text widget resource values.
1635     * (Change these and you die!  Aha! Ha! Ha! Ha! [evil laugh])
1636     */
1637
1638    ac = 0;
1639    XtSetArg (al[ac], XmNeditMode, XmMULTI_LINE_EDIT);  ac++;
1640    XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++; 
1641    XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++; 
1642    XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++; 
1643    XtSetArg(al[ac], XmNpendingDelete, True); ac++; 
1644
1645    /* 
1646     * Now, set up the resource values which can vary (passed in from 
1647     * application or default values).
1648     *
1649     * If a synthetic resource is DtUNSPECIFIED don't set it, but let
1650     * it default to the scrolled text default value.  
1651     * If it is specified, clear the data field after setting the 
1652     * resource because the value in the field will be out of sync 
1653     * with the real value.
1654     */
1655    XtSetArg(al[ac], XmNautoShowCursorPosition, M_autoShowCursorPos(parent));
1656    ac++;
1657
1658    XtSetArg(al[ac], XmNblinkRate, M_blinkRate(parent)); ac++;
1659
1660    if ( M_columns(parent) != DtUNSPECIFIED) {
1661      XtSetArg (al[ac], XmNcolumns, M_columns(parent) );  ac++;
1662      M_columns(parent) = (short) DtUNSPECIFIED;
1663    }
1664
1665    if ( M_cursorPos(parent) != DtUNSPECIFIED) {
1666      XtSetArg (al[ac], XmNcursorPosition, M_cursorPos(parent));  ac++;
1667      M_cursorPos(parent) = (XmTextPosition) DtUNSPECIFIED;
1668    }
1669
1670    XtSetArg(al[ac], XmNcursorPositionVisible, M_cursorPosVisible(parent));
1671    ac++;
1672
1673    XtSetArg(al[ac], XmNeditable, M_editable(parent)); ac++;
1674   
1675    if ( E_textFontList(parent) != (XmFontList) NULL) {
1676      XtSetArg (al[ac], XmNfontList, E_textFontList(parent));  ac++;
1677    }
1678
1679    if ( M_maxLength(parent) != DtUNSPECIFIED) {
1680      XtSetArg (al[ac], XmNmaxLength, M_maxLength(parent) );  ac++;
1681      M_maxLength(parent) = (int) DtUNSPECIFIED;
1682    }
1683
1684    if ( M_rows(parent) != DtUNSPECIFIED) {
1685      XtSetArg (al[ac], XmNrows, M_rows(parent) );  ac++;
1686      M_rows(parent) = (short) DtUNSPECIFIED;
1687    }
1688
1689    XtSetArg (al[ac], XmNscrollHorizontal, M_scrollHorizontal(parent) ); ac++;
1690
1691    if ( M_scrollLeftSide(parent) != (Boolean)DtUNSPECIFIED) {
1692      XtSetArg (al[ac], XmNscrollLeftSide, M_scrollLeftSide(parent) ); ac++;
1693      M_scrollLeftSide(parent) = (Boolean)DtUNSPECIFIED;
1694    }
1695
1696    if ( M_scrollTopSide(parent) != (Boolean)DtUNSPECIFIED) {
1697      XtSetArg (al[ac], XmNscrollTopSide, M_scrollTopSide(parent) ); ac++;
1698      M_scrollTopSide(parent) = (Boolean)DtUNSPECIFIED;
1699    }
1700
1701    XtSetArg (al[ac], XmNscrollVertical, M_scrollVertical(parent) );  ac++;
1702
1703    if ( M_topCharacter(parent) != DtUNSPECIFIED) {
1704      XtSetArg (al[ac], XmNtopCharacter, M_topCharacter(parent) );  ac++;
1705      M_topCharacter(parent) = (XmTextPosition) DtUNSPECIFIED;
1706    }
1707
1708    XtSetArg (al[ac], XmNwordWrap, M_wordWrap(parent) );  ac++;
1709
1710    /* Create text widget */
1711    text = XmCreateScrolledText ( (Widget) parent, "text", al, ac );
1712
1713
1714    /* 
1715     * Now, set the foreground & background of the text widget.  Could not 
1716     * set it at create time because the scrolled window would have
1717     * picked it up, too.
1718     */
1719    ac=0;
1720
1721    if ( M_textBackground(parent) != DtUNSPECIFIED) {
1722      XtSetArg (al[ac], XmNbackground, M_textBackground(parent) );  ac++;
1723      M_textBackground(parent) = (Pixel) DtUNSPECIFIED;
1724    }
1725
1726    if ( M_textForeground(parent) != DtUNSPECIFIED) {
1727      XtSetArg (al[ac], XmNforeground, M_textForeground(parent) );  ac++;
1728      M_textForeground(parent) = (Pixel) DtUNSPECIFIED;
1729    }
1730
1731    if (ac)
1732        XtSetValues( text, al, ac);
1733
1734
1735    /* XXX Word Wrap workaround.  See comments for FixWordWrap() */
1736    if ( M_scrollHorizontal(parent) )         /* XXX Word Wrap workaround */
1737      FixWordWrap(text, M_wordWrap(parent));  /* XXX Word Wrap workaround */
1738    
1739
1740    /* Put the editor-specific translation routines in place. */
1741    XtOverrideTranslations(text, 
1742                         XtParseTranslationTable(EditorTranslationTable));
1743
1744    /* Add any translations set by the application. */
1745    if ( E_textTranslations(parent) != (XtTranslations)NULL ) {
1746      XtOverrideTranslations(text, E_textTranslations(parent));
1747    }
1748
1749
1750    /*
1751     * Add modify verify callback
1752     */
1753    XtAddCallback(text, XmNmodifyVerifyCallback,
1754                   (XtCallbackProc) _DtEditorModifyVerifyCB,
1755                   (XtPointer) parent);
1756
1757    /* 
1758     * Add the Help callback
1759     */
1760    XtAddCallback( text, XmNhelpCallback, (XtCallbackProc) HelpEditWindowCB,
1761                   (XtPointer) parent );
1762
1763
1764    /*
1765     * Substitute our own Set Selection routine which can
1766     * call the textSelect and textDeselect callback procs
1767     */
1768    if(((XmTextWidget)(text))->text.source->SetSelection !=
1769       Editor_SetSelectionProc) {
1770        M_setSelection(parent) =
1771                ((XmTextWidget)(text))->text.source->SetSelection;
1772        ((XmTextWidget)(text))->text.source->SetSelection =
1773                                                 Editor_SetSelectionProc;
1774    }
1775
1776
1777    XtSetSensitive (text, True);
1778    return(text);
1779
1780 } /* end CreateText */
1781
1782
1783 /*-------------------------------------------------------------
1784 **      Function: static int extractFontMetrics (
1785 **                              XmFontList fontlist )
1786 **
1787 **      Purpose: Given a font list, determine the width & height
1788 **               of the characters.
1789 **
1790 **      This routine is lifted almost straight out of 
1791 **      lib/Xm/TextOut.c (see LoadFontMetrics() ) so the editor will
1792 **      select the same font the text widget is working with.
1793 */
1794 static void 
1795 extractFontMetrics(
1796         DtEditorWidget w,
1797         XmFontList fontlist,
1798         int     *height,
1799         int     *width)
1800 {
1801     XmFontContext context;
1802     XmFontListEntry next_entry;
1803     XmFontType type_return = XmFONT_IS_FONT;
1804     XtPointer tmp_font;
1805     XFontStruct *font;
1806     Boolean have_font_struct = False;
1807     Boolean have_font_set = False;
1808     Boolean use_font_set = False;
1809     XFontSetExtents *fs_extents;
1810     unsigned long tmp_width = 0;
1811     int font_descent, font_ascent;
1812     char* font_tag = NULL;
1813     
1814
1815     *width = *height = 0;
1816     if (XmFontListInitFontContext(&context, fontlist)) {
1817
1818        /*
1819         * Look through the font list for a fontset with the default tag.
1820         * If we do not find it, use the first font set we came to, otherwise,
1821         * use the first font struct we came to.
1822         */
1823        do {
1824           Boolean do_break = False;
1825
1826           next_entry = XmFontListNextEntry(context);
1827           if (next_entry) {
1828
1829              tmp_font = XmFontListEntryGetFont(next_entry, &type_return);
1830              if (type_return == XmFONT_IS_FONTSET) {
1831
1832                 /* 
1833                  * Have a font set
1834                  */
1835                 font_tag = XmFontListEntryGetTag(next_entry);
1836
1837                 if (!have_font_set){ 
1838
1839                    /* 
1840                     * Save the first fontset found in case we don't find 
1841                     * a default tag font set.
1842                     */
1843                    have_font_set = True;    /* we have a font set. */
1844                    use_font_set = True;
1845                    font = (XFontStruct *)tmp_font;
1846
1847                    /* 
1848                     * We have a font set, so no need to consider future font 
1849                     * structs
1850                     */
1851                    have_font_struct = True; 
1852
1853                    /*
1854                     * If this is the default font set break out, we've
1855                     * found the one we want.
1856                     */
1857                    if (!strcmp(XmFONTLIST_DEFAULT_TAG, font_tag))
1858                       do_break = True; 
1859
1860                 } 
1861                 else if (!strcmp(XmFONTLIST_DEFAULT_TAG, font_tag)) {
1862                    /*
1863                     * If this is the default font set save it & break out,
1864                     * we've found the one we want.
1865                     */
1866                    font = (XFontStruct *)tmp_font;
1867                    have_font_set = True; 
1868                    do_break = True; 
1869                 }
1870
1871                 if (NULL != font_tag)
1872                   XtFree(font_tag);
1873
1874                 if (do_break)
1875                   break;
1876              } 
1877              else if (!have_font_struct){
1878
1879                 /*
1880                  * Have a font
1881                  */
1882                 use_font_set = False;
1883
1884                 /* 
1885                  * Save the first one in case no font set is found 
1886                  */
1887                 font = (XFontStruct *)tmp_font;
1888                 use_font_set = False;
1889                 have_font_struct = True;
1890
1891              }
1892           }
1893
1894        } while (next_entry != NULL);
1895
1896        XmFontListFreeFontContext(context);
1897
1898        /*
1899         * Now, extract the font metrics from the font set or font that
1900         * we chose.
1901         */
1902
1903        if (use_font_set) {
1904           /*
1905            * Chose a font set
1906            */
1907           fs_extents = XExtentsOfFontSet((XFontSet)font);
1908
1909           if (XmDirectionMatch(w->manager.string_direction,
1910                                XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1911             tmp_width = (unsigned long)fs_extents->max_ink_extent.width;
1912           } else {
1913             tmp_width = (unsigned long)fs_extents->max_logical_extent.width;
1914           }
1915           /* max_logical_extent.y is number of pixels from origin to top of
1916            * rectangle (i.e. y is negative) */
1917           font_ascent = -fs_extents->max_logical_extent.y;
1918           font_descent = fs_extents->max_logical_extent.height +
1919                          fs_extents->max_logical_extent.y;
1920        } 
1921        else {
1922
1923           /*
1924            * Chose a font struct
1925            */
1926           font_ascent = font->max_bounds.ascent;
1927           font_descent = font->max_bounds.descent;
1928           if ( (!XGetFontProperty(font, XA_QUAD_WIDTH, &tmp_width)) || 
1929                tmp_width == 0 ) 
1930           { 
1931              if ( font->per_char && font->min_char_or_byte2 <= '0' &&
1932                   font->max_char_or_byte2 >= '0' )
1933                tmp_width = font->per_char['0' - font->min_char_or_byte2].width;
1934              else
1935                tmp_width = font->max_bounds.width;
1936           }
1937
1938        }
1939
1940        if (tmp_width <= 0) tmp_width = 1;
1941        *width = (int)tmp_width; /* This assumes there will be no truncation */
1942        *height = font_descent + font_ascent;
1943
1944     }
1945
1946 } /* end extractFontMetrics */
1947
1948
1949
1950 /*-------------------------------------------------------------
1951 **      Function: static void getFontMetrics (
1952 **                              DtEditorWidget w )
1953 **
1954 **      Parameters: An Editor widget
1955 **
1956 **      Purpose:    Determine the height & width of the scrolled text 
1957 **                  widget's font
1958 **
1959 */
1960 static void
1961 getFontMetrics( 
1962         DtEditorWidget w)
1963 {
1964     Arg al[10];                 /* arg list */
1965     XmFontList fontlist;
1966     int width, height;
1967
1968     /*
1969      * Get the text widget's font list
1970      *
1971      * Note, have to retrieve the fontList from the text widget rather
1972      * than use the DtNtextFontList resource because the text widget may
1973      * have rejected the font specified with DtNtextFontList.  This way
1974      * we will get the fontList actually used by the text widget.
1975      */
1976
1977     XtSetArg(al[0], XmNfontList, &fontlist); 
1978     XtGetValues(M_text(w), al, 1);
1979
1980     /*
1981      * Now, extract the height and width
1982      */
1983     extractFontMetrics( w, fontlist, &height, &width );
1984     M_fontWidth(w) = width; 
1985     M_fontHeight(w) = height;
1986
1987 } /* end getFontMetrics */
1988
1989
1990 /*-------------------------------------------------------------
1991 **      Destroy
1992 **              Release resources allocated for a widget instance.
1993 */
1994 static void
1995 Destroy(
1996         Widget widget )
1997 {
1998    DtEditorWidget editor = (DtEditorWidget) widget;
1999
2000    /*
2001     * Cleanup the edit window 
2002     */
2003    
2004    /* 
2005     * (Nothing to be done. Unregistering it as a drop site is handled
2006     *  automatically by the DnD library.)
2007     */
2008
2009    /*
2010     * Cleanup the status line
2011     */
2012    
2013    if (M_status_insertLabel(editor) != (XmString)DtUNSPECIFIED)
2014       XmStringFree(M_status_insertLabel(editor));
2015
2016    if (M_status_overstrikeLabel(editor) != (XmString)DtUNSPECIFIED)
2017       XmStringFree(M_status_overstrikeLabel(editor));
2018
2019    if (E_status_currentLineLabel(editor) != (XmString)DtUNSPECIFIED)
2020       XmStringFree(E_status_currentLineLabel(editor));
2021
2022    if (E_status_totalLineCountLabel(editor) != (XmString)DtUNSPECIFIED)
2023       XmStringFree(E_status_totalLineCountLabel(editor));
2024
2025    /*
2026     * Cleanup the Find/Change & Spell dialogs
2027     */
2028
2029    if (M_search_string(editor))
2030       XtFree(M_search_string(editor));
2031
2032    if (M_replace_string(editor))
2033       XtFree(M_replace_string(editor));
2034
2035    if (M_misspelled_string(editor))
2036       XtFree(M_misspelled_string(editor));
2037
2038    if (M_spellFilter(editor))
2039       XtFree(M_spellFilter(editor));
2040
2041    if (M_spellTitle(editor) != (XmString)NULL)
2042       XmStringFree(M_spellTitle(editor));
2043
2044    if (E_misspelledListLabel(editor) != (XmString)DtUNSPECIFIED)
2045       XmStringFree(E_misspelledListLabel(editor));
2046
2047    if (M_fndChngTitle(editor) != (XmString)NULL)
2048       XmStringFree(M_fndChngTitle(editor));
2049
2050    if (E_findFieldLabel(editor) != (XmString)DtUNSPECIFIED)
2051       XmStringFree(E_findFieldLabel(editor));
2052
2053    if (E_changeFieldLabel(editor) != (XmString)DtUNSPECIFIED)
2054       XmStringFree(E_changeFieldLabel(editor));
2055
2056    if (E_findButtonLabel(editor) != (XmString)DtUNSPECIFIED)
2057       XmStringFree(E_findButtonLabel(editor));
2058
2059    if (E_changeButtonLabel(editor) != (XmString)DtUNSPECIFIED)
2060       XmStringFree(E_changeButtonLabel(editor));
2061
2062    if (E_changeAllButtonLabel(editor) != (XmString)DtUNSPECIFIED)
2063       XmStringFree(E_changeAllButtonLabel(editor));
2064
2065    /*
2066     * Cleanup the Format Settings dialog
2067     */
2068    if (E_format_dialogTitle(editor) != (XmString)NULL)
2069       XmStringFree(E_format_dialogTitle(editor));
2070
2071    if (E_format_leftMarginFieldLabel(editor) != (XmString)DtUNSPECIFIED)
2072       XmStringFree(E_format_leftMarginFieldLabel(editor));
2073
2074    if (E_format_rightMarginFieldLabel(editor) != (XmString)DtUNSPECIFIED)
2075       XmStringFree(E_format_rightMarginFieldLabel(editor));
2076
2077    if (E_format_leftAlignToggleLabel(editor) != (XmString)DtUNSPECIFIED)
2078       XmStringFree(E_format_leftAlignToggleLabel(editor));
2079
2080    if (E_format_rightAlignToggleLabel(editor) != (XmString)DtUNSPECIFIED)
2081       XmStringFree(E_format_rightAlignToggleLabel(editor));
2082
2083    if (E_format_justifyToggleLabel(editor) != (XmString)DtUNSPECIFIED)
2084       XmStringFree(E_format_justifyToggleLabel(editor));
2085
2086    if (E_format_centerToggleLabel(editor) != (XmString)DtUNSPECIFIED)
2087       XmStringFree(E_format_centerToggleLabel(editor));
2088
2089    if (E_format_formatAllButtonLabel(editor) != (XmString)DtUNSPECIFIED)
2090       XmStringFree(E_format_formatAllButtonLabel(editor));
2091
2092    if (E_format_formatParagraphButtonLabel(editor) != (XmString)DtUNSPECIFIED)
2093       XmStringFree(E_format_formatParagraphButtonLabel(editor));
2094
2095    /*
2096     * Cleanup the Information dialog
2097     */
2098    if (E_infoDialogTitle(editor) != (XmString)NULL)
2099       XmStringFree(E_infoDialogTitle(editor));
2100
2101    /*
2102     * Cleanup the Undo deletion context
2103     */
2104
2105    _DtEditorResetUndo(editor);
2106
2107 } /* end Destroy */
2108
2109
2110 /*-------------------------------------------------------------
2111 **      SetValues
2112 **              Handle changes in resource data.
2113 */
2114
2115
2116 static Boolean
2117 SetValues(
2118         Widget cw,
2119         Widget rw,
2120         Widget nw )
2121 {
2122   Boolean         redisplay_flag = False;
2123   Arg           al[15];         /*  arg list            */
2124   register int    ac;           /*  arg count           */
2125
2126   Boolean       resetSpellTitle = False,
2127                 resetFormatTitle = False,
2128                 resetInfoTitle = False,
2129                 newButtonFontList = False,
2130                 newLabelFontList = False,
2131                 newTextFontList = False,
2132                 NeedToFixWordWrap = False;      /* XXX Word Wrap workaround*/
2133
2134   DtEditorWidget  current = (DtEditorWidget) cw;
2135   DtEditorWidget  request = (DtEditorWidget) rw;
2136   DtEditorWidget  new     = (DtEditorWidget) nw;
2137
2138   /* 
2139    * XXX Need to propagate changes to Core resources, like XmNbackground,
2140    * to the children.
2141    */
2142
2143   /*
2144    * If a synthetic resource is specified, clear the data field 
2145    * after setting the resource because the value in the field 
2146    * will be out of sync with the real value (contained in the 
2147    * child widget).
2148    */
2149
2150   /* 
2151    * General changes, not directly affecting a child
2152    */
2153
2154   /* Check for a new spell filter */
2155
2156   if ( strcmp(M_spellFilter(request), M_spellFilter(current)) != 0 )
2157   {
2158     XtFree( M_spellFilter(current) );
2159     M_spellFilter(new) = XtNewString( M_spellFilter(request) );
2160   }
2161
2162   /* Check for new font lists */
2163
2164   if ( E_buttonFontList(request) != E_buttonFontList(current) ) 
2165      newButtonFontList = True;
2166
2167   if ( E_labelFontList(request) != E_labelFontList(current) ) 
2168      newLabelFontList = True;
2169
2170   if ( E_textFontList(request) != E_textFontList(current) ) 
2171      newTextFontList = True;
2172
2173   /* 
2174    * Check for any changes which affect the dialog titles
2175    */
2176
2177   if (XmStringCompare(E_dialogTitle(request),E_dialogTitle(current)) == False) {
2178     resetSpellTitle = resetFormatTitle = resetInfoTitle = True;
2179   }
2180
2181   if (XmStringCompare(M_spellTitle(request),M_spellTitle(current)) == False) {
2182     XmStringFree( M_spellTitle(current) );
2183     M_spellTitle(new) = XmStringCopy( M_spellTitle(request) );
2184     resetSpellTitle = True;
2185   }
2186
2187   if (XmStringCompare(M_fndChngTitle(request),M_fndChngTitle(current)) == False)
2188   {
2189     XmStringFree( M_fndChngTitle(current) );
2190     M_fndChngTitle(new) = XmStringCopy( M_fndChngTitle(request) );
2191     resetSpellTitle = True;
2192   }
2193
2194   if (XmStringCompare(E_format_dialogTitle(request),
2195                       E_format_dialogTitle(current) ) == False)
2196   {
2197     XmStringFree( E_format_dialogTitle(current) );
2198     E_format_dialogTitle(new) = XmStringCopy( E_format_dialogTitle(request) );
2199     resetFormatTitle = True;
2200   }
2201
2202   if (XmStringCompare(E_infoDialogTitle(request),
2203                       E_infoDialogTitle(current) ) == False)
2204   {
2205     XmStringFree( E_infoDialogTitle(current) );
2206     E_infoDialogTitle(new) = XmStringCopy( E_infoDialogTitle(request) );
2207     resetInfoTitle = True;
2208   }
2209
2210  /*
2211   * Calculate new titles for the dialogs depending upon which resources
2212   * changed.
2213   */
2214   if ( resetSpellTitle == True ) {
2215     /*
2216      * No need to do anything because the Spell and Find/Change dialog
2217      * titles are recomputed every time.
2218      */
2219     redisplay_flag = True;
2220   }
2221
2222   if ( resetFormatTitle == True ) {
2223     SetFormatDialogTitle( new );
2224     redisplay_flag = True;
2225   }
2226
2227   if ( resetInfoTitle == True ) {
2228     SetInfoDialogTitle( new );
2229     redisplay_flag = True;
2230   }
2231
2232
2233   /* 
2234    * Check for any changes which affect the status line
2235    */
2236   if (M_status_showStatusLine(request) != M_status_showStatusLine(current)) {
2237     SetStatusLine( new, M_status_showStatusLine(request) );
2238     redisplay_flag = True;
2239   }
2240
2241   if ( M_overstrikeMode(request) != M_overstrikeMode(current) ) {
2242
2243     UpdateOverstrikeIndicator( new, M_overstrikeMode(request) );
2244     XtCallActionProc( (Widget) M_text(current), "toggle-overstrike", 
2245                       (XEvent *)NULL, (String *)NULL, 0 );
2246     redisplay_flag = True;
2247   }
2248
2249   if ( M_status_statusArea(current) != (Widget)NULL ) {
2250
2251     if (newLabelFontList == True) {
2252       XtSetArg (al[0], XmNfontList, E_labelFontList(request) );  
2253       XtSetValues( (Widget) M_status_lineLabel(current), al, 1);
2254       XtSetValues( (Widget) M_status_totalLabel(current), al, 1);
2255       XtSetValues( (Widget) M_status_totalText(current), al, 1);
2256       XtSetValues( (Widget) M_status_overstrikeWidget(current), al, 1);
2257     }
2258
2259     ac=0;
2260     if (newTextFontList == True) {
2261        XtSetArg( al[ac], XmNfontList, E_textFontList(request) ); ac++;
2262     }
2263
2264     if ( M_textBackground(request) != DtUNSPECIFIED) {
2265        XtSetArg( al[ac], XmNbackground, M_textBackground(request) ); ac++;
2266     }
2267
2268     if ( M_textForeground(request) != DtUNSPECIFIED) {
2269        XtSetArg( al[ac], XmNforeground, M_textForeground(request) ); ac++;
2270     }
2271
2272     if ( ac ) {
2273        XtSetValues( (Widget) M_status_lineText(current), al, ac);
2274        XtSetValues( (Widget) M_status_messageText(current), al, ac);
2275     }
2276
2277   }
2278
2279
2280   /* 
2281    * Check for any changes which affect the dialog boxes
2282    */
2283
2284   /* Information dialog */
2285
2286   if ( M_gen_warning(current) != (Widget)NULL ) {
2287
2288     if ( newButtonFontList == True ) { 
2289       XtSetArg (al[0], XmNfontList, E_buttonFontList(request) );
2290       XtSetValues( 
2291          XmMessageBoxGetChild(M_gen_warning(current), XmDIALOG_OK_BUTTON),
2292          al, 1 );
2293     }
2294
2295     if ( newLabelFontList == True ) { 
2296       XtSetArg (al[0], XmNfontList, E_labelFontList(request) ); 
2297       XtSetValues( 
2298          XmMessageBoxGetChild(M_gen_warning(current), XmDIALOG_MESSAGE_LABEL),
2299          al, 1 );
2300     }
2301
2302   }
2303
2304   /* Find/Change dialog */
2305   if ( M_search_dialog(current) != (Widget)NULL ) 
2306   {
2307     if ( newButtonFontList == True ) { 
2308       XtSetArg (al[0], XmNfontList, E_buttonFontList(request)); 
2309       XtSetValues( (Widget)M_search_findBtn(current), al, 1 );
2310       XtSetValues( (Widget)M_search_replaceBtn(current), al, 1 );
2311       XtSetValues( (Widget)M_search_replaceAllBtn(current), al, 1 );
2312       XtSetValues( (Widget)M_search_closeBtn(current), al, 1 );
2313       XtSetValues( (Widget)M_search_helpBtn(current), al, 1 );
2314     }
2315
2316     if ( newLabelFontList == True ) { 
2317       XtSetArg (al[0], XmNfontList, E_labelFontList(request)  );
2318       XtSetValues( (Widget)M_search_listLbl(current), al, 1   );
2319       XtSetValues( (Widget)M_search_findLbl(current), al, 1   );
2320       XtSetValues( (Widget)M_search_replaceLbl(current), al, 1);
2321     }
2322
2323     if ( newTextFontList == True ) {
2324       XtSetArg (al[0], XmNfontList, E_textFontList(request)  ); 
2325       XtSetValues( (Widget)M_search_spellList(current), al, 1);
2326       XtSetValues( (Widget)M_findText(current), al, 1 );
2327       XtSetValues( (Widget)M_replaceText(current), al, 1 );
2328     }
2329
2330     ac=0;
2331     if ( M_textBackground(request) != DtUNSPECIFIED) {
2332        XtSetArg( al[ac], XmNbackground, M_textBackground(request) ); ac++;
2333     }
2334
2335     if ( M_textForeground(request) != DtUNSPECIFIED) {
2336        XtSetArg( al[ac], XmNforeground, M_textForeground(request) ); ac++;
2337     }
2338
2339     if ( ac ) {
2340        XtSetValues( (Widget) M_findText(current), al, ac);
2341        XtSetValues( (Widget) M_replaceText(current), al, ac);
2342     }
2343
2344   }
2345
2346   /* Format Settings dialog */
2347   if ( M_format_dialog(current) != (Widget)NULL ) 
2348   {
2349     if ( newButtonFontList == True ) { 
2350       XtSetArg (al[0], XmNfontList, E_buttonFontList(request)); 
2351       XtSetValues( (Widget)M_format_leftJust(current), al, 1 );
2352       XtSetValues( (Widget)M_format_rightJust(current), al, 1);
2353       XtSetValues( (Widget)M_format_bothJust(current), al, 1 );
2354       XtSetValues( (Widget)M_format_center(current), al, 1   );
2355       XtSetValues( (Widget)M_format_paragraph(current), al, 1);
2356       XtSetValues( (Widget)M_format_all(current), al, 1      );
2357       XtSetValues( (Widget)M_format_close(current), al, 1    );
2358       XtSetValues( (Widget)M_format_help(current), al, 1     );
2359     }
2360
2361     if ( newLabelFontList == True ) { 
2362       XtSetArg (al[0], XmNfontList, E_labelFontList(request)  );
2363       XtSetValues( (Widget)M_format_leftLabel(current), al, 1 );
2364       XtSetValues( (Widget)M_format_rightLabel(current), al, 1);
2365     }
2366
2367     if ( newTextFontList == True ) {
2368       XtSetArg (al[0], XmNfontList, E_textFontList(request) ); 
2369       XtSetValues( (Widget)M_format_leftMarginField(current), al, 1 );
2370       XtSetValues( (Widget)M_format_rightMarginField(current), al, 1);
2371     }
2372
2373     ac=0;
2374     if ( M_textBackground(request) != DtUNSPECIFIED) {
2375        XtSetArg( al[ac], XmNbackground, M_textBackground(request) ); ac++;
2376     }
2377
2378     if ( M_textForeground(request) != DtUNSPECIFIED) {
2379        XtSetArg( al[ac], XmNforeground, M_textForeground(request) ); ac++;
2380     }
2381
2382     if ( ac ) {
2383        XtSetValues( (Widget) M_format_leftMarginField(current), al, ac);
2384        XtSetValues( (Widget) M_format_rightMarginField(current), al, ac);
2385     }
2386
2387   }
2388
2389
2390   /* 
2391    * Check for any changes which affect the edit area (scrolled text widget)
2392    */
2393
2394   ac=0;
2395   if ( M_autoShowCursorPos(request) != M_autoShowCursorPos(current) ) {
2396      XtSetArg( al[ac], XmNautoShowCursorPosition, M_autoShowCursorPos(request));
2397      ac++;
2398   }
2399
2400   if ( M_blinkRate(request) != M_blinkRate(current) ) {
2401      XtSetArg( al[ac], XmNblinkRate, M_blinkRate(request)); ac++;
2402   }
2403
2404   if ( M_columns(request) != DtUNSPECIFIED) {
2405      XtSetArg (al[ac], XmNcolumns, M_columns(request) );  ac++;
2406      M_columns(new) = (short) DtUNSPECIFIED;
2407      redisplay_flag = True;
2408   }
2409
2410   /* PERF - disable redisplay for all SetValues */
2411   if ( M_cursorPos(request) != DtUNSPECIFIED) {
2412      XmTextSetCursorPosition( M_text(new), M_topCharacter(request) );
2413      M_cursorPos(new) = (XmTextPosition) DtUNSPECIFIED;
2414   }
2415
2416   if ( M_cursorPosVisible(request) != M_cursorPosVisible(current) ) {
2417      XtSetArg( al[ac], XmNcursorPositionVisible, M_cursorPosVisible(request));
2418      ac++;
2419   }
2420
2421   if ( M_editable(request) != M_editable(current) ) {
2422      XtSetArg( al[ac], XmNeditable, M_editable(request)); ac++;
2423
2424      if( M_editable(request) ) {
2425
2426         /*
2427          * If the widget is becoming editable, register it as a 
2428          * drop site and...
2429          */
2430         RegisterDropZone( new );
2431
2432         /*
2433          * ...turn back on the Change To field in the Find/Change dialog
2434          */
2435         if ( M_search_dialog(current) != (Widget)NULL ) {
2436           XtSetSensitive(M_search_replaceLbl(current), True);
2437           XtSetSensitive(M_replaceText(current), True);
2438         }
2439
2440      } 
2441      else 
2442         /* 
2443          * It's no longer available as a drop site.
2444          */
2445         UnregisterDropZone( current );
2446   }
2447
2448   if ( M_maxLength(request) != DtUNSPECIFIED) {
2449      XtSetArg (al[ac], XmNmaxLength, M_maxLength(request) );  ac++;
2450      M_maxLength(new) = (int) DtUNSPECIFIED;
2451   }
2452
2453   if ( M_rows(request) != DtUNSPECIFIED) {
2454      XtSetArg (al[ac], XmNrows, M_rows(request) );  ac++;
2455      M_rows(new) = (short) DtUNSPECIFIED;
2456      redisplay_flag = True;
2457   }
2458
2459   if ( M_textBackground(request) != DtUNSPECIFIED) {
2460      XtSetArg (al[ac], XmNbackground, M_textBackground(request) );  ac++;
2461      M_textBackground(new) = (XmTextPosition) DtUNSPECIFIED;
2462      redisplay_flag = True;
2463   }
2464
2465   if ( newTextFontList == True ) {
2466      XtSetArg (al[ac], XmNfontList, E_textFontList(request) );  ac++;
2467      redisplay_flag = True;
2468   }
2469
2470   if ( M_textForeground(request) != DtUNSPECIFIED) {
2471      XtSetArg (al[ac], XmNforeground, M_textForeground(request) );  ac++;
2472      M_textForeground(new) = (XmTextPosition) DtUNSPECIFIED;
2473      redisplay_flag = True;
2474   }
2475
2476   /* PERF - disable redisplay for all SetValues */
2477   if ( M_topCharacter(request) != DtUNSPECIFIED) {
2478      XmTextSetTopCharacter( M_text(new), M_topCharacter(request) );
2479      M_topCharacter(new) = (XmTextPosition) DtUNSPECIFIED;
2480   }
2481
2482   if ( M_wordWrap(request) != M_wordWrap(current) ) { 
2483     XtSetArg( al[ac], XmNwordWrap, M_wordWrap(request)); ac++; 
2484     NeedToFixWordWrap=M_scrollHorizontal(current);/*XXX Word Wrap workaround*/
2485   }
2486
2487   if ( NeedToFixWordWrap )                        /*XXX Word Wrap workaround*/
2488     FixWordWrap(M_text(new), M_wordWrap(request));/*XXX Word Wrap workaround*/
2489
2490   if ( ac )
2491      XtSetValues( (Widget) M_text(new), al, ac);
2492
2493   if ( E_textTranslations(request) != E_textTranslations(current) ) {
2494    XtOverrideTranslations(M_text(new), E_textTranslations(request));
2495   }
2496
2497   if ( newTextFontList == True ) {
2498     getFontMetrics(new);
2499   }
2500
2501   return (redisplay_flag);
2502
2503 } /* end Set values */
2504
2505
2506 /**************************************************************
2507 **
2508 **      Get values routines for synthetic resources
2509 **
2510 **/
2511
2512 static void
2513 _DtEditorGetCenterToggleLabel(
2514         Widget          wid,
2515         int             resource_offset,
2516         XtArgVal        *value )
2517 {
2518     DtEditorWidget editor = (DtEditorWidget) wid;
2519     XmString    data;
2520     Arg al[1];
2521
2522     /*
2523      * Get the value directly from the field in the instance structure.
2524      * If it is DtUNSPECIFIED then either:
2525      *   1) the value has been assigned to the widget (so get it from
2526      *      there), or
2527      *   2) the value has never been set (so return the default value).
2528      */
2529
2530     if (E_format_centerToggleLabel(editor) != (XmString) DtUNSPECIFIED)
2531       data = XmStringCopy( E_format_centerToggleLabel(editor) );
2532     else if (M_format_dialog(editor) != (Widget)NULL)
2533     { 
2534        XtSetArg( al[0], XmNlabelString, &data) ;
2535        XtGetValues( (Widget) M_format_center(editor), al, 1) ;
2536     } 
2537     else
2538       data = XmStringCreateLocalized(CENTER);  
2539     *value = (XtArgVal) data ;
2540
2541     return;
2542 } /* end _DtEditorGetCenterToggleLabel */
2543
2544 static void
2545 _DtEditorGetChangeAllButtonLabel(
2546         Widget          wid,
2547         int             resource_offset,
2548         XtArgVal        *value )
2549 {
2550     DtEditorWidget editor = (DtEditorWidget) wid;
2551     XmString    data;
2552     Arg al[1];
2553
2554     /*
2555      * Get the value directly from the field in the instance structure.
2556      * If it is DtUNSPECIFIED then either:
2557      *   1) the value has been assigned to the widget (so get it from
2558      *      there), or
2559      *   2) the value has never been set (so return the default value).
2560      */
2561
2562     if (E_changeAllButtonLabel(editor) != (XmString) DtUNSPECIFIED)
2563       data = XmStringCopy( E_changeAllButtonLabel(editor) );
2564     else if (M_search_dialog(editor) != (Widget) NULL)
2565     { 
2566        XtSetArg( al[0], XmNlabelString, &data) ;
2567        XtGetValues( (Widget) M_search_replaceAllBtn(editor), al, 1) ;
2568     } 
2569     else
2570       data = XmStringCreateLocalized(CHNG_ALL_BUTTON);  
2571     *value = (XtArgVal) data ;
2572     return;
2573
2574 } /* end _DtEditorGetChangeAllButtonLabel */
2575
2576 static void
2577 _DtEditorGetChangeButtonLabel(
2578         Widget          wid,
2579         int             resource_offset,
2580         XtArgVal        *value )
2581 {
2582     DtEditorWidget editor = (DtEditorWidget) wid;
2583     XmString    data;
2584     Arg al[1];
2585
2586     /*
2587      * Get the value directly from the field in the instance structure.
2588      * If it is DtUNSPECIFIED then either:
2589      *   1) the value has been assigned to the widget (so get it from
2590      *      there), or
2591      *   2) the value has never been set (so return the default value).
2592      */
2593
2594     if (E_changeButtonLabel(editor) != (XmString) DtUNSPECIFIED)
2595       data = XmStringCopy( E_changeButtonLabel(editor) );
2596     else if (M_search_dialog(editor) != (Widget) NULL)
2597     { 
2598        XtSetArg( al[0], XmNlabelString, &data) ;
2599        XtGetValues( (Widget) M_search_replaceBtn(editor), al, 1) ;
2600     } 
2601     else
2602       data = XmStringCreateLocalized(CHANGE_BUTTON);  
2603     *value = (XtArgVal) data ;
2604     return;
2605
2606 } /* end _DtEditorGetChangeButtonLabel */
2607
2608 static void
2609 _DtEditorGetChangeFieldLabel(
2610         Widget          wid,
2611         int             resource_offset,
2612         XtArgVal        *value )
2613 {
2614     DtEditorWidget editor = (DtEditorWidget) wid;
2615     XmString    data;
2616     Arg al[1];
2617
2618     /*
2619      * Get the value directly from the field in the instance structure.
2620      * If it is DtUNSPECIFIED then either:
2621      *   1) the value has been assigned to the widget (so get it from
2622      *      there), or
2623      *   2) the value has never been set (so return the default value).
2624      */
2625
2626     if (E_changeFieldLabel(editor) != (XmString) DtUNSPECIFIED)
2627       data = XmStringCopy( E_changeFieldLabel(editor) );
2628     else if (M_search_dialog(editor) != (Widget) NULL)
2629     { 
2630        XtSetArg( al[0], XmNlabelString, &data) ;
2631        XtGetValues( (Widget) M_search_replaceLbl(editor), al, 1) ;
2632     } 
2633     else
2634       data = XmStringCreateLocalized(CHANGE_LABEL);  
2635     *value = (XtArgVal) data ;
2636     return;
2637
2638 } /* end _DtEditorGetChangeFieldLabel */
2639
2640 static void
2641 _DtEditorGetColumns(
2642         Widget          wid,
2643         int             resource_offset,
2644         XtArgVal        *value )
2645 {
2646     DtEditorWidget editor = (DtEditorWidget) wid;
2647     short       data;
2648     Arg al[1];
2649
2650     XtSetArg( al[0], XmNcolumns, &data) ;
2651     XtGetValues( (Widget) M_text(editor), al, 1) ;
2652     *value = (XtArgVal) data ;
2653
2654     return;
2655 } /* end _DtEditorGetColumns */
2656
2657 static void
2658 _DtEditorGetCurrentLineLabel(
2659         Widget          wid,
2660         int             resource_offset,
2661         XtArgVal        *value )
2662 {
2663     DtEditorWidget editor = (DtEditorWidget) wid;
2664     XmString    data;
2665     Arg al[1];
2666
2667     /*
2668      * Get the value directly from the field in the instance structure.
2669      * If it is DtUNSPECIFIED then either:
2670      *   1) the value has been assigned to the widget (so get it from
2671      *      there), or
2672      *   2) the value has never been set (so return the default value).
2673      */
2674
2675     if (E_status_currentLineLabel(editor) != (XmString) DtUNSPECIFIED)
2676       data = XmStringCopy( E_status_currentLineLabel(editor) );
2677     else if (M_status_statusArea(editor) != (Widget) NULL)
2678     { 
2679        XtSetArg( al[0], XmNlabelString, &data) ;
2680        XtGetValues( (Widget) M_status_lineLabel(editor), al, 1) ;
2681     } 
2682     else
2683       data = XmStringCreateLocalized(LINE);  
2684     *value = (XtArgVal) data ;
2685
2686     return;
2687 } /* end _DtEditorGetCurrentLineLabel */
2688
2689 static void
2690 _DtEditorGetCursorPosition(
2691         Widget          wid,
2692         int             resource_offset,
2693         XtArgVal        *value )
2694 {
2695     DtEditorWidget editor = (DtEditorWidget) wid;
2696     XmTextPosition      data;
2697     Arg al[1];
2698
2699     XtSetArg( al[0], XmNcursorPosition, &data) ;
2700     XtGetValues( (Widget) M_text(editor), al, 1) ;
2701     *value = (XtArgVal) data ;
2702
2703     return;
2704 } /* end _DtEditorGetCursorPosition */
2705
2706 static void
2707 _DtEditorGetFindButtonLabel(
2708         Widget          wid,
2709         int             resource_offset,
2710         XtArgVal        *value )
2711 {
2712     DtEditorWidget editor = (DtEditorWidget) wid;
2713     XmString    data;
2714     Arg al[1];
2715
2716     /*
2717      * Get the value directly from the field in the instance structure.
2718      * If it is DtUNSPECIFIED then either:
2719      *   1) the value has been assigned to the widget (so get it from
2720      *      there), or
2721      *   2) the value has never been set (so return the default value).
2722      */
2723
2724     if (E_findButtonLabel(editor) != (XmString) DtUNSPECIFIED)
2725       data = XmStringCopy( E_findButtonLabel(editor) );
2726     else if (M_search_dialog(editor) != (Widget) NULL)
2727     { 
2728        XtSetArg( al[0], XmNlabelString, &data) ;
2729        XtGetValues( (Widget) M_search_findBtn(editor), al, 1) ;
2730     } 
2731     else
2732       data = XmStringCreateLocalized(FIND_BUTTON);  
2733     *value = (XtArgVal) data ;
2734     return;
2735
2736 } /* end _DtEditorGetFindButtonLabel */
2737
2738 static void
2739 _DtEditorGetFindFieldLabel(
2740         Widget          wid,
2741         int             resource_offset,
2742         XtArgVal        *value )
2743 {
2744     DtEditorWidget editor = (DtEditorWidget) wid;
2745     XmString    data;
2746     Arg al[1];
2747
2748     /*
2749      * Get the value directly from the field in the instance structure.
2750      * If it is DtUNSPECIFIED then either:
2751      *   1) the value has been assigned to the widget (so get it from
2752      *      there), or
2753      *   2) the value has never been set (so return the default value).
2754      */
2755
2756     if (E_findFieldLabel(editor) != (XmString) DtUNSPECIFIED)
2757       data = XmStringCopy( E_findFieldLabel(editor) );
2758     else if (M_search_dialog(editor) != (Widget) NULL)
2759     { 
2760        XtSetArg( al[0], XmNlabelString, &data) ;
2761        XtGetValues( (Widget) M_search_findLbl(editor), al, 1) ;
2762     } 
2763     else
2764       data = XmStringCreateLocalized(FIND_LABEL);  
2765     *value = (XtArgVal) data ;
2766     return;
2767
2768 } /* end _DtEditorGetFindFieldLabel */
2769
2770 static void
2771 _DtEditorGetFormatAllButtonLabel(
2772         Widget          wid,
2773         int             resource_offset,
2774         XtArgVal        *value )
2775 {
2776     DtEditorWidget editor = (DtEditorWidget) wid;
2777     XmString    data;
2778     Arg al[1];
2779
2780     /*
2781      * Get the value directly from the field in the instance structure.
2782      * If it is DtUNSPECIFIED then either:
2783      *   1) the value has been assigned to the widget (so get it from
2784      *      there), or
2785      *   2) the value has never been set (so return the default value).
2786      */
2787
2788     if (E_format_formatAllButtonLabel(editor) != (XmString) DtUNSPECIFIED)
2789       data = XmStringCopy( E_format_formatAllButtonLabel(editor) );
2790     else if (M_format_dialog(editor) != (Widget)NULL)
2791     { 
2792        XtSetArg( al[0], XmNlabelString, &data) ;
2793        XtGetValues( (Widget) M_format_all(editor), al, 1) ;
2794     } 
2795     else
2796       data = XmStringCreateLocalized(ALL);  
2797     *value = (XtArgVal) data ;
2798
2799     return;
2800 } /* end _DtEditorGetFormatAllButtonLabel */
2801
2802 static void
2803 _DtEditorGetFormatParagraphButtonLabel(
2804         Widget          wid,
2805         int             resource_offset,
2806         XtArgVal        *value )
2807 {
2808     DtEditorWidget editor = (DtEditorWidget) wid;
2809     XmString    data;
2810     Arg al[1];
2811
2812     /*
2813      * Get the value directly from the field in the instance structure.
2814      * If it is DtUNSPECIFIED then either:
2815      *   1) the value has been assigned to the widget (so get it from
2816      *      there), or
2817      *   2) the value has never been set (so return the default value).
2818      */
2819
2820     if(E_format_formatParagraphButtonLabel(editor) != (XmString) DtUNSPECIFIED)
2821       data = XmStringCopy( E_format_formatParagraphButtonLabel(editor) );
2822     else if (M_format_dialog(editor) != (Widget)NULL)
2823     { 
2824        XtSetArg( al[0], XmNlabelString, &data) ;
2825        XtGetValues( (Widget) M_format_paragraph(editor), al, 1) ;
2826     } 
2827     else
2828       data = XmStringCreateLocalized(PARAGRAPH);  
2829     *value = (XtArgVal) data ;
2830
2831     return;
2832 } /* end _DtEditorGetFormatParagraphButtonLabel */
2833
2834 static void
2835 _DtEditorGetJustifyToggleLabel(
2836         Widget          wid,
2837         int             resource_offset,
2838         XtArgVal        *value )
2839 {
2840     DtEditorWidget editor = (DtEditorWidget) wid;
2841     XmString    data;
2842     Arg al[1];
2843
2844     /*
2845      * Get the value directly from the field in the instance structure.
2846      * If it is DtUNSPECIFIED then either:
2847      *   1) the value has been assigned to the widget (so get it from
2848      *      there), or
2849      *   2) the value has never been set (so return the default value).
2850      */
2851
2852     if (E_format_justifyToggleLabel(editor) != (XmString) DtUNSPECIFIED)
2853       data = XmStringCopy( E_format_justifyToggleLabel(editor) );
2854     else if (M_format_dialog(editor) != (Widget)NULL)
2855     { 
2856        XtSetArg( al[0], XmNlabelString, &data) ;
2857        XtGetValues( (Widget) M_format_bothJust(editor), al, 1) ;
2858     } 
2859     else
2860       data = XmStringCreateLocalized(JUSTIFY);  
2861     *value = (XtArgVal) data ;
2862
2863     return;
2864 } /* end _DtEditorGetJustifyToggleLabel */
2865
2866 static void
2867 _DtEditorGetLeftAlignToggleLabel(
2868         Widget          wid,
2869         int             resource_offset,
2870         XtArgVal        *value )
2871 {
2872     DtEditorWidget editor = (DtEditorWidget) wid;
2873     XmString    data;
2874     Arg al[1];
2875
2876     /*
2877      * Get the value directly from the field in the instance structure.
2878      * If it is DtUNSPECIFIED then either:
2879      *   1) the value has been assigned to the widget (so get it from
2880      *      there), or
2881      *   2) the value has never been set (so return the default value).
2882      */
2883
2884     if (E_format_leftAlignToggleLabel(editor) != (XmString) DtUNSPECIFIED)
2885       data = XmStringCopy( E_format_leftAlignToggleLabel(editor) );
2886     else if (M_format_dialog(editor) != (Widget)NULL)
2887     { 
2888        XtSetArg( al[0], XmNlabelString, &data) ;
2889        XtGetValues( (Widget) M_format_leftJust(editor), al, 1) ;
2890     } 
2891     else
2892       data = XmStringCreateLocalized(LEFT_ALIGN);  
2893     *value = (XtArgVal) data ;
2894
2895     return;
2896 } /* end _DtEditorGetLeftAlignToggleLabel */
2897
2898 static void
2899 _DtEditorGetLeftMarginFieldLabel(
2900         Widget          wid,
2901         int             resource_offset,
2902         XtArgVal        *value )
2903 {
2904     DtEditorWidget editor = (DtEditorWidget) wid;
2905     XmString    data;
2906     Arg al[1];
2907
2908     /*
2909      * Get the value directly from the field in the instance structure.
2910      * If it is DtUNSPECIFIED then either:
2911      *   1) the value has been assigned to the widget (so get it from
2912      *      there), or
2913      *   2) the value has never been set (so return the default value).
2914      */
2915
2916     if (E_format_leftMarginFieldLabel(editor) != (XmString) DtUNSPECIFIED)
2917       data = XmStringCopy( E_format_leftMarginFieldLabel(editor) );
2918     else if (M_format_dialog(editor) != (Widget)NULL)
2919     { 
2920        XtSetArg( al[0], XmNlabelString, &data) ;
2921        XtGetValues( (Widget) M_format_leftLabel(editor), al, 1) ;
2922     } 
2923     else
2924       data = XmStringCreateLocalized(LEFT_MARGIN);  
2925     *value = (XtArgVal) data ;
2926
2927     return;
2928 } /* end _DtEditorGetLeftMarginFieldLabel */
2929
2930 static void
2931 _DtEditorGetMaxLength(
2932         Widget          wid,
2933         int             resource_offset,
2934         XtArgVal        *value )
2935 {
2936     DtEditorWidget editor = (DtEditorWidget) wid;
2937     int data;
2938     Arg al[1];
2939
2940     XtSetArg( al[0], XmNmaxLength, &data) ;
2941     XtGetValues( (Widget) M_text(editor), al, 1) ;
2942     *value = (XtArgVal) data ;
2943
2944     return;
2945 } /* end _DtEditorGetMaxLength */
2946
2947 static void
2948 _DtEditorGetMisspelledListLabel(
2949         Widget          wid,
2950         int             resource_offset,
2951         XtArgVal        *value )
2952 {
2953     DtEditorWidget editor = (DtEditorWidget) wid;
2954     XmString    data;
2955     Arg al[1];
2956
2957     /*
2958      * Get the value directly from the field in the instance structure.
2959      * If it is DtUNSPECIFIED then either:
2960      *   1) the value has been assigned to the widget (so get it from
2961      *      there), or
2962      *   2) the value has never been set (so return the default value).
2963      */
2964
2965     if (E_misspelledListLabel(editor) != (XmString) DtUNSPECIFIED)
2966       data = XmStringCopy( E_misspelledListLabel(editor) );
2967     else if (M_search_dialog(editor) != (Widget) NULL)
2968     { 
2969        XtSetArg( al[0], XmNlabelString, &data) ;
2970        XtGetValues( (Widget) M_search_listLbl(editor), al, 1) ;
2971     } 
2972     else
2973       data = XmStringCreateLocalized(MISSPELLED);  
2974     *value = (XtArgVal) data ;
2975     return;
2976
2977 } /* end _DtEditorGetMisspelledListLabel */
2978
2979 static void
2980 _DtEditorGetRightAlignToggleLabel(
2981         Widget          wid,
2982         int             resource_offset,
2983         XtArgVal        *value )
2984 {
2985     DtEditorWidget editor = (DtEditorWidget) wid;
2986     XmString    data;
2987     Arg al[1];
2988
2989     /*
2990      * Get the value directly from the field in the instance structure.
2991      * If it is DtUNSPECIFIED then either:
2992      *   1) the value has been assigned to the widget (so get it from
2993      *      there), or
2994      *   2) the value has never been set (so return the default value).
2995      */
2996
2997     if (E_format_rightAlignToggleLabel(editor) != (XmString) DtUNSPECIFIED)
2998       data = XmStringCopy( E_format_rightAlignToggleLabel(editor) );
2999     else if (M_format_dialog(editor) != (Widget)NULL)
3000     { 
3001        XtSetArg( al[0], XmNlabelString, &data) ;
3002        XtGetValues( (Widget) M_format_rightJust(editor), al, 1) ;
3003     } 
3004     else
3005       data = XmStringCreateLocalized(RIGHT_ALIGN);  
3006     *value = (XtArgVal) data ;
3007
3008     return;
3009 } /* end _DtEditorGetRightAlignToggleLabel */
3010
3011 static void
3012 _DtEditorGetRightMarginFieldLabel(
3013         Widget          wid,
3014         int             resource_offset,
3015         XtArgVal        *value )
3016 {
3017     DtEditorWidget editor = (DtEditorWidget) wid;
3018     XmString    data;
3019     Arg al[1];
3020
3021     /*
3022      * Get the value directly from the field in the instance structure.
3023      * If it is DtUNSPECIFIED then either:
3024      *   1) the value has been assigned to the widget (so get it from
3025      *      there), or
3026      *   2) the value has never been set (so return the default value).
3027      */
3028
3029     if (E_format_rightMarginFieldLabel(editor) != (XmString) DtUNSPECIFIED)
3030       data = XmStringCopy( E_format_rightMarginFieldLabel(editor) );
3031     else if (M_format_dialog(editor) != (Widget)NULL)
3032     { 
3033        XtSetArg( al[0], XmNlabelString, &data) ;
3034        XtGetValues( (Widget) M_format_rightLabel(editor), al, 1) ;
3035     } 
3036     else
3037       data = XmStringCreateLocalized(RIGHT_MARGIN);  
3038     *value = (XtArgVal) data ;
3039
3040     return;
3041 } /* end _DtEditorGetRightMarginFieldLabel */
3042
3043 static void
3044 _DtEditorGetRows(
3045         Widget          wid,
3046         int             resource_offset,
3047         XtArgVal        *value )
3048 {
3049     DtEditorWidget editor = (DtEditorWidget) wid;
3050     short       data;
3051     Arg al[1];
3052
3053     XtSetArg( al[0], XmNrows, &data) ;
3054     XtGetValues( (Widget) M_text(editor), al, 1) ;
3055     *value = (XtArgVal) data ;
3056
3057     return;
3058 } /* end _DtEditorGetRows */
3059
3060 static void
3061 _DtEditorGetScrollLeftSide(
3062         Widget          wid,
3063         int             resource_offset,
3064         XtArgVal        *value )
3065 {
3066     DtEditorWidget editor = (DtEditorWidget) wid;
3067     Boolean     data;
3068     Arg al[1];
3069
3070     XtSetArg( al[0], XmNscrollLeftSide, &data) ;
3071     XtGetValues( (Widget) M_text(editor), al, 1) ;
3072     *value = (XtArgVal) data ;
3073
3074     return;
3075 } /* end _DtEditorGetScrollLeftSide */
3076
3077 static void
3078 _DtEditorGetScrollTopSide(
3079         Widget          wid,
3080         int             resource_offset,
3081         XtArgVal        *value )
3082 {
3083     DtEditorWidget editor = (DtEditorWidget) wid;
3084     Boolean     data;
3085     Arg al[1];
3086
3087     XtSetArg( al[0], XmNscrollTopSide, &data) ;
3088     XtGetValues( (Widget) M_text(editor), al, 1) ;
3089     *value = (XtArgVal) data ;
3090
3091     return;
3092 } /* end _DtEditorGetScrollTopSide */
3093
3094 static void
3095 _DtEditorGetTextBackground(
3096         Widget          wid,
3097         int             resource_offset,
3098         XtArgVal        *value )
3099 {
3100     DtEditorWidget      editor = (DtEditorWidget) wid;
3101     Pixel               data;
3102     Arg al[1];
3103
3104     XtSetArg( al[0], XmNbackground, &data) ;
3105     XtGetValues( (Widget) M_text(editor), al, 1) ;
3106     *value = (XtArgVal) data ;
3107
3108     return;
3109 } /* end _DtEditorGetTextBackground */
3110
3111 static void
3112 _DtEditorGetTextForeground(
3113         Widget          wid,
3114         int             resource_offset,
3115         XtArgVal        *value )
3116 {
3117     DtEditorWidget      editor = (DtEditorWidget) wid;
3118     Pixel               data;
3119     Arg al[1];
3120
3121     XtSetArg( al[0], XmNforeground, &data) ;
3122     XtGetValues( (Widget) M_text(editor), al, 1) ;
3123     *value = (XtArgVal) data ;
3124
3125     return;
3126 } /* end _DtEditorGetTextForeground */
3127
3128 static void
3129 _DtEditorGetTopCharacter(
3130         Widget          wid,
3131         int             resource_offset,
3132         XtArgVal        *value )
3133 {
3134     DtEditorWidget      editor = (DtEditorWidget) wid;
3135     XmTextPosition      data;
3136     Arg al[1];
3137
3138     XtSetArg( al[0], XmNtopCharacter, &data) ;
3139     XtGetValues( (Widget) M_text(editor), al, 1) ;
3140     *value = (XtArgVal) data ;
3141
3142     return;
3143 } /* end _DtEditorGetTopCharacter */
3144
3145 static void
3146 _DtEditorGetLineCountLabel(
3147         Widget          wid,
3148         int             resource_offset,
3149         XtArgVal        *value )
3150 {
3151     DtEditorWidget editor = (DtEditorWidget) wid;
3152     XmString    data;
3153     Arg al[1];
3154
3155     /*
3156      * Get the value directly from the field in the instance structure.
3157      * If it is DtUNSPECIFIED then either:
3158      *   1) the value has been assigned to the widget (so get it from
3159      *      there), or
3160      *   2) the value has never been set (so return the default value).
3161      */
3162
3163     if (E_status_totalLineCountLabel(editor) != (XmString) DtUNSPECIFIED)
3164       data = XmStringCopy( E_status_totalLineCountLabel(editor) );
3165     else if (M_status_statusArea(editor) != (Widget) NULL)
3166     { 
3167        XtSetArg( al[0], XmNlabelString, &data) ;
3168        XtGetValues( (Widget) M_status_totalLabel(editor), al, 1) ;
3169     } 
3170     else
3171       data = XmStringCreateLocalized(TOTAL);  
3172     *value = (XtArgVal) data ;
3173
3174     return;
3175 } /* end _DtEditorGetLineCountLabel */
3176
3177 \f
3178 /**************************************************************
3179 **
3180 **      Action Procedures
3181 **
3182 **/
3183
3184 /*
3185  * The following are DtEditor's actions.  A few are internal only (_I
3186  * suffix) and will be called by the default translations DtEditor places
3187  * on the text widget.  The rest will be called from an application with 
3188  * XtCallActionProc().  The main difference is the internal ones will be 
3189  * passed a text widget ID, while the public ones will be passed a DtEditor ID.
3190  */
3191
3192 static void
3193 BackwardChar(
3194                 Widget w,
3195                 XEvent *event,
3196                 char **params,
3197                 Cardinal *num_params)
3198 {
3199
3200     DtEditorWidget editor = (DtEditorWidget)w;
3201
3202     XtCallActionProc( M_text(editor), "backward-character", event, 
3203                       params, *num_params );
3204
3205
3206 static void
3207 BackwardPara(
3208                 Widget w,
3209                 XEvent *event,
3210                 char **params,
3211                 Cardinal *num_params)
3212 {
3213
3214     DtEditorWidget editor = (DtEditorWidget)w;
3215
3216     XtCallActionProc( M_text(editor), "backward-paragraph", event, 
3217                       params, *num_params );
3218
3219
3220 static void
3221 BackwardWord(
3222                 Widget w,
3223                 XEvent *event,
3224                 char **params,
3225                 Cardinal *num_params)
3226 {
3227
3228     DtEditorWidget editor = (DtEditorWidget)w;
3229
3230     XtCallActionProc( M_text(editor), "backward-word", event, 
3231                       params, *num_params );
3232
3233
3234 static void
3235 BeginningOfFile(
3236                 Widget w,
3237                 XEvent *event,
3238                 char **params,
3239                 Cardinal *num_params)
3240 {
3241
3242     DtEditorWidget editor = (DtEditorWidget)w;
3243
3244     XtCallActionProc( M_text(editor), "beginning-of-file", event, 
3245                       params, *num_params );
3246
3247
3248 static void
3249 BeginningOfLine(
3250                 Widget w,
3251                 XEvent *event,
3252                 char **params,
3253                 Cardinal *num_params)
3254 {
3255
3256     DtEditorWidget editor = (DtEditorWidget)w;
3257
3258     XtCallActionProc( M_text(editor), "beginning-of-line", event, 
3259                       params, *num_params );
3260
3261
3262 static void
3263 ClearSelection(
3264                 Widget w,
3265                 XEvent *event,
3266                 char **params,
3267                 Cardinal *num_params)
3268 {
3269
3270     DtEditorWidget editor = (DtEditorWidget)w;
3271
3272     XtCallActionProc( M_text(editor), "clear-selection", event, 
3273                       params, *num_params );
3274
3275     /* 
3276      * Clearing selected text also deselects the selection, but for some
3277      * reason the selection proc (Editor_SetSelectionProc) does not get
3278      * called, therefore, we need to call the DtNtextDeselectCallback
3279      * from here.
3280      */
3281     Call_TextDeselectCallback(editor);
3282
3283
3284
3285 static void
3286 CopyClipboard(
3287                 Widget w,
3288                 XEvent *event,
3289                 char **params,
3290                 Cardinal *num_params)
3291 {
3292
3293     DtEditorWidget editor = (DtEditorWidget)w;
3294
3295     XtCallActionProc( M_text(editor), "copy-clipboard", event, 
3296                       params, *num_params );
3297
3298
3299 static void
3300 CutClipboard(
3301                 Widget w,
3302                 XEvent *event,
3303                 char **params,
3304                 Cardinal *num_params)
3305 {
3306
3307     DtEditorWidget editor = (DtEditorWidget)w;
3308
3309     XtCallActionProc( M_text(editor), "cut-clipboard", event, 
3310                       params, *num_params );
3311
3312
3313 static void
3314 DeleteNextChar(
3315                 Widget w,
3316                 XEvent *event,
3317                 char **params,
3318                 Cardinal *num_params)
3319 {
3320
3321     DtEditorWidget editor = (DtEditorWidget)w;
3322
3323     XtCallActionProc( M_text(editor), "delete-next-character", event, 
3324                       params, *num_params );
3325
3326
3327 static void
3328 DeleteNextWord(
3329                 Widget w,
3330                 XEvent *event,
3331                 char **params,
3332                 Cardinal *num_params)
3333 {
3334
3335     DtEditorWidget editor = (DtEditorWidget)w;
3336
3337     XtCallActionProc( M_text(editor), "delete-next-word", event, 
3338                       params, *num_params );
3339
3340
3341 static void
3342 DeletePrevChar(
3343                 Widget w,
3344                 XEvent *event,
3345                 char **params,
3346                 Cardinal *num_params)
3347 {
3348
3349     DtEditorWidget editor = (DtEditorWidget)w;
3350
3351     XtCallActionProc( M_text(editor), "delete-previous-character", event, 
3352                       params, *num_params );
3353
3354
3355 static void
3356 DeletePrevWord(
3357                 Widget w,
3358                 XEvent *event,
3359                 char **params,
3360                 Cardinal *num_params)
3361 {
3362
3363     DtEditorWidget editor = (DtEditorWidget)w;
3364
3365     XtCallActionProc( M_text(editor), "delete-previous-word", event, 
3366                       params, *num_params );
3367
3368
3369 static void
3370 DeleteToEOL(
3371                 Widget w,
3372                 XEvent *event,
3373                 char **params,
3374                 Cardinal *num_params)
3375 {
3376
3377     DtEditorWidget editor = (DtEditorWidget)w;
3378
3379     XtCallActionProc( M_text(editor), "delete-to-end-of-line", event, 
3380                       params, *num_params );
3381
3382
3383 static void
3384 DeleteToSOL(
3385                 Widget w,
3386                 XEvent *event,
3387                 char **params,
3388                 Cardinal *num_params)
3389 {
3390
3391     DtEditorWidget editor = (DtEditorWidget)w;
3392
3393     XtCallActionProc( M_text(editor), "delete-to-start-of-line", event, 
3394                       params, *num_params );
3395
3396
3397 static void
3398 DeselectAll(
3399                 Widget w,
3400                 XEvent *event,
3401                 char **params,
3402                 Cardinal *num_params)
3403 {
3404
3405     DtEditorWidget editor = (DtEditorWidget)w;
3406
3407     XtCallActionProc( M_text(editor), "deselect-all", event, 
3408                       params, *num_params );
3409
3410
3411 static void
3412 EndOfFile(
3413                 Widget w,
3414                 XEvent *event,
3415                 char **params,
3416                 Cardinal *num_params)
3417 {
3418
3419     DtEditorWidget editor = (DtEditorWidget)w;
3420
3421     XtCallActionProc( M_text(editor), "end-of-file", event, 
3422                       params, *num_params );
3423
3424
3425 static void
3426 EndOfLine(
3427                 Widget w,
3428                 XEvent *event,
3429                 char **params,
3430                 Cardinal *num_params)
3431 {
3432
3433     DtEditorWidget editor = (DtEditorWidget)w;
3434
3435     XtCallActionProc( M_text(editor), "end-of-line", event, 
3436                       params, *num_params );
3437
3438
3439 static void
3440 ForwardChar(
3441                 Widget w,
3442                 XEvent *event,
3443                 char **params,
3444                 Cardinal *num_params)
3445 {
3446
3447     DtEditorWidget editor = (DtEditorWidget)w;
3448
3449     XtCallActionProc( M_text(editor), "forward-character", event, 
3450                       params, *num_params );
3451
3452
3453 static void
3454 ForwardPara(
3455                 Widget w,
3456                 XEvent *event,
3457                 char **params,
3458                 Cardinal *num_params)
3459 {
3460
3461     DtEditorWidget editor = (DtEditorWidget)w;
3462
3463     XtCallActionProc( M_text(editor), "forward-paragraph", event, 
3464                       params, *num_params );
3465
3466
3467 static void
3468 ForwardWord(
3469                 Widget w,
3470                 XEvent *event,
3471                 char **params,
3472                 Cardinal *num_params)
3473 {
3474
3475     DtEditorWidget editor = (DtEditorWidget)w;
3476
3477     XtCallActionProc( M_text(editor), "forward-word", event, 
3478                       params, *num_params );
3479
3480
3481 static void
3482 GoToLine(
3483                 Widget w,
3484                 XEvent *event,
3485                 char **params,
3486                 Cardinal *num_params)
3487 {
3488     DtEditorWidget editor = (DtEditorWidget)w;
3489
3490     if( M_status_statusArea(editor) != (Widget)NULL && 
3491         XtIsManaged(M_status_statusArea(editor)) == True ) 
3492     {
3493
3494        /*
3495         * Set the input focus to the "Line" text field.
3496         */
3497
3498        XmProcessTraversal(M_status_lineText(editor), XmTRAVERSE_CURRENT);
3499
3500        /*
3501         * Select the current contents to allow easy modification.
3502         */
3503
3504        XtCallActionProc( (Widget)M_status_lineText(editor), "select-all",
3505                          event, (String *)NULL, 0 );
3506     }
3507
3508 } /* end GoToLine */
3509
3510 /* 
3511  * Internal action called only from the scrolled text widget
3512  */
3513 static void
3514 GoToLine_I(
3515                 Widget w,
3516                 XEvent *event,
3517                 char **params,
3518                 Cardinal *num_params)
3519 {
3520     XmTextWidget tw = (XmTextWidget)w;
3521     DtEditorWidget editor = (DtEditorWidget)M_editor(tw);
3522
3523     GoToLine( (Widget)editor, event, params, num_params );
3524
3525 } /* end GoToLine_I */
3526
3527 static void
3528 Help(
3529                 Widget w,
3530                 XEvent *event,
3531                 char **params,
3532                 Cardinal *num_params)
3533 {
3534
3535     CallHelpCallback((DtEditorWidget)w, DtEDITOR_HELP_EDIT_WINDOW);
3536
3537
3538
3539 static void
3540 InsertString(
3541                 Widget w,
3542                 XEvent *event,
3543                 char **params,
3544                 Cardinal *num_params)
3545 {
3546
3547     DtEditorWidget editor = (DtEditorWidget)w;
3548
3549     XtCallActionProc( M_text(editor), "insert-string", event, 
3550                       params, *num_params );
3551
3552
3553 static void
3554 KeySelect(
3555                 Widget w,
3556                 XEvent *event,
3557                 char **params,
3558                 Cardinal *num_params)
3559 {
3560
3561     DtEditorWidget editor = (DtEditorWidget)w;
3562
3563     XtCallActionProc( M_text(editor), "key-select", event, 
3564                       params, *num_params );
3565
3566
3567 static void
3568 NewlineAndBackup(
3569                 Widget w,
3570                 XEvent *event,
3571                 char **params,
3572                 Cardinal *num_params)
3573 {
3574
3575     DtEditorWidget editor = (DtEditorWidget)w;
3576
3577     XtCallActionProc( M_text(editor), "newline-and-backup", event, 
3578                       params, *num_params );
3579
3580
3581 static void
3582 NewlineAndIndent(
3583                 Widget w,
3584                 XEvent *event,
3585                 char **params,
3586                 Cardinal *num_params)
3587 {
3588
3589     DtEditorWidget editor = (DtEditorWidget)w;
3590
3591     XtCallActionProc( M_text(editor), "newline-and-indent", event, 
3592                       params, *num_params );
3593
3594
3595 static void
3596 NextPage(
3597                 Widget w,
3598                 XEvent *event,
3599                 char **params,
3600                 Cardinal *num_params)
3601 {
3602
3603     DtEditorWidget editor = (DtEditorWidget)w;
3604
3605     XtCallActionProc( M_text(editor), "next-page", event, 
3606                       params, *num_params );
3607
3608
3609 static void
3610 PageLeft(
3611                 Widget w,
3612                 XEvent *event,
3613                 char **params,
3614                 Cardinal *num_params)
3615 {
3616
3617     DtEditorWidget editor = (DtEditorWidget)w;
3618
3619     XtCallActionProc( M_text(editor), "page-left", event, 
3620                       params, *num_params );
3621
3622
3623 static void
3624 PageRight(
3625                 Widget w,
3626                 XEvent *event,
3627                 char **params,
3628                 Cardinal *num_params)
3629 {
3630
3631     DtEditorWidget editor = (DtEditorWidget)w;
3632
3633     XtCallActionProc( M_text(editor), "page-right", event, 
3634                       params, *num_params );
3635
3636
3637 static void
3638 PasteClipboard(
3639                 Widget w,
3640                 XEvent *event,
3641                 char **params,
3642                 Cardinal *num_params)
3643 {
3644
3645     DtEditorWidget editor = (DtEditorWidget)w;
3646
3647     XtCallActionProc( M_text(editor), "paste-clipboard", event, 
3648                       params, *num_params );
3649
3650
3651 static void
3652 PreviousPage(
3653                 Widget w,
3654                 XEvent *event,
3655                 char **params,
3656                 Cardinal *num_params)
3657 {
3658
3659     DtEditorWidget editor = (DtEditorWidget)w;
3660
3661     XtCallActionProc( M_text(editor), "previous-page", event, 
3662                       params, *num_params );
3663
3664
3665 static void
3666 ProcessCancel(
3667                 Widget w,
3668                 XEvent *event,
3669                 char **params,
3670                 Cardinal *num_params)
3671 {
3672
3673     DtEditorWidget editor = (DtEditorWidget)w;
3674
3675     XtCallActionProc( M_text(editor), "process-cancel", event, 
3676                       params, *num_params );
3677
3678
3679 static void
3680 ProcessDown(
3681                 Widget w,
3682                 XEvent *event,
3683                 char **params,
3684                 Cardinal *num_params)
3685 {
3686
3687     DtEditorWidget editor = (DtEditorWidget)w;
3688
3689     XtCallActionProc( M_text(editor), "process-down", event, 
3690                       params, *num_params );
3691
3692
3693 static void
3694 ProcessShiftDown(
3695                 Widget w,
3696                 XEvent *event,
3697                 char **params,
3698                 Cardinal *num_params)
3699 {
3700
3701     DtEditorWidget editor = (DtEditorWidget)w;
3702
3703     XtCallActionProc( M_text(editor), "process-shift-down", event, 
3704                       params, *num_params );
3705
3706
3707 static void
3708 ProcessShiftUp(
3709                 Widget w,
3710                 XEvent *event,
3711                 char **params,
3712                 Cardinal *num_params)
3713 {
3714
3715     DtEditorWidget editor = (DtEditorWidget)w;
3716
3717     XtCallActionProc( M_text(editor), "process-shift-up", event, 
3718                       params, *num_params );
3719
3720
3721 static void
3722 ProcessUp(
3723                 Widget w,
3724                 XEvent *event,
3725                 char **params,
3726                 Cardinal *num_params)
3727 {
3728
3729     DtEditorWidget editor = (DtEditorWidget)w;
3730
3731     XtCallActionProc( M_text(editor), "process-up", event, 
3732                       params, *num_params );
3733
3734
3735 /************************************************************************
3736  *  GetModeSwitchModifier
3737  *      Find if any Mod<n> modifier is acting as the Group modifier - you
3738  *      can't assume Mod1Mask is always it.
3739  *      Returns the mask of the modifier key to which the Mode_switch
3740  *      keysym is attached.
3741  *
3742  ************************************************************************/
3743 /* ARGSUSED */
3744 static unsigned int
3745 GetModeSwitchModifier(
3746                 Display *dpy)
3747 {
3748     register XModifierKeymap *pMap;
3749     register int mapIndex, keyCol, mapSize;
3750     KeySym keySym;
3751     unsigned int modeSwitchModMask = 0;
3752     pMap = XGetModifierMapping(dpy);
3753     mapSize = 8*pMap->max_keypermod;
3754
3755     for (mapIndex = 3*pMap->max_keypermod; mapIndex < mapSize; mapIndex++) {
3756         /* look only at the first 4 columns of key map */
3757         for (keyCol = 0; keyCol < 4; keyCol++) {
3758           keySym = XKeycodeToKeysym(dpy, pMap->modifiermap[mapIndex], keyCol);
3759           if (keySym == XK_Mode_switch)
3760              modeSwitchModMask |= 1 << (mapIndex / pMap->max_keypermod);
3761         }
3762     }
3763
3764     XFreeModifiermap(pMap);
3765     return modeSwitchModMask;
3766 }
3767
3768 /************************************************************************
3769  *
3770  *  DtEditorQuoteNextChar
3771  *      This action routine circumvents the normal XtDispatchEvent
3772  *      mechanism, inserting the next control or extended character
3773  *      directly into text without processed by event handlers or the
3774  *      translation manager.  This means, for
3775  *      example, that the next control or extended character will be
3776  *      inserted into text without being intrepreted as a Motif menu
3777  *      or text widget accelerator.
3778  *
3779  ************************************************************************/
3780 /* ARGSUSED */
3781 static void
3782 QuoteNextChar(
3783                 Widget widget,
3784                 XEvent *event,
3785                 char **params,
3786                 Cardinal *num_params)
3787 {
3788     DtEditorWidget editor = (DtEditorWidget)widget;
3789     static unsigned int ExtendcharMask = 0;
3790
3791     /*  NOTE:  ExtendcharMask could be a global set via a MappingNotify
3792      *         event handler.  But it isn't...
3793      */
3794
3795     if (! ExtendcharMask) 
3796       {
3797         _DtProcessLock();
3798         if (! ExtendcharMask)
3799           ExtendcharMask = GetModeSwitchModifier( M_display(editor) );
3800         _DtProcessUnlock();
3801       }
3802
3803     for (;;) 
3804     {
3805       XEvent next;
3806
3807 #ifdef XTHREADS
3808       /* 
3809        * We cannot let XtAppNextEvent bloc, because the intrinsics
3810        * will release locks and some other thread might dispatch
3811        * the event we want to trap.
3812        */
3813       XtInputMask mask;
3814       XtAppContext app = XtWidgetToApplicationContext(widget);
3815       while ((mask = XtAppPending(app)) == 0)
3816         {
3817           if (XtAppGetExitFlag(app))
3818             return;
3819         }
3820
3821       if (mask & XtIMXEvent)
3822         {
3823 #endif
3824           XtAppNextEvent(M_app_context(editor), &next);
3825           if ((next.type == KeyPress) &&
3826               (! IsModifierKey(XLookupKeysym((XKeyEvent *) &next, 0))) ) 
3827             {
3828               if (next.xkey.state & (ControlMask|ExtendcharMask)) 
3829                 XtCallActionProc(M_text(editor), "self-insert", &next, NULL, 0);
3830               else
3831                 XtDispatchEvent(&next);
3832               break;
3833             } 
3834           else
3835             XtDispatchEvent(&next);
3836 #ifdef XTHREADS
3837         }
3838       else
3839         {
3840           /* Some (non-X) event is pending, so this should not block. */
3841           XtAppProcessEvent(app, mask);
3842         }
3843 #endif
3844     }
3845
3846 } /* end QuoteNextChar */
3847
3848 /* 
3849  * Internal action called only from the scrolled text widget
3850  */
3851 static void
3852 QuoteNextChar_I(
3853                 Widget w,
3854                 XEvent *event,
3855                 char **params,
3856                 Cardinal *num_params)
3857 {
3858     XmTextWidget tw = (XmTextWidget)w;
3859     DtEditorWidget editor = (DtEditorWidget) M_editor(tw);
3860
3861     QuoteNextChar( (Widget)editor, event, params, num_params );
3862
3863 } /* end QuoteNextChar_I */
3864
3865 static void
3866 SelectAll(
3867                 Widget w,
3868                 XEvent *event,
3869                 char **params,
3870                 Cardinal *num_params)
3871 {
3872
3873     DtEditorWidget editor = (DtEditorWidget)w;
3874
3875     XtCallActionProc( M_text(editor), "select-all", event, 
3876                       params, *num_params );
3877
3878
3879 static void
3880 ToggleInsertMode(
3881                 Widget w,
3882                 XEvent *event,
3883                 char **params,
3884                 Cardinal *num_params)
3885 {
3886     DtEditorWidget editor = (DtEditorWidget)w;
3887
3888     /*
3889      * Toggle the state of the DtNoverstrike resource
3890      */
3891     XtVaSetValues(w, DtNoverstrike, !M_overstrikeMode(editor), NULL);
3892
3893 } /* end ToggleInsertMode */
3894
3895 static void
3896 ToggleInsertMode_I(
3897                 Widget w,
3898                 XEvent *event,
3899                 char **params,
3900                 Cardinal *num_params)
3901 {
3902     XmTextWidget tw = (XmTextWidget)w;
3903     DtEditorWidget editor = (DtEditorWidget)M_editor(tw);
3904
3905     ToggleInsertMode( (Widget)editor, event, params, num_params );
3906
3907 } /* end ToggleInsertMode_I */
3908
3909
3910 static void
3911 UndoEdit(
3912                 Widget w,
3913                 XEvent *event,
3914                 char **params,
3915                 Cardinal *num_params)
3916 {
3917
3918     DtEditorUndoEdit(w);
3919
3920 } /* end UndoEdit */
3921
3922 static void
3923 UndoEdit_I(
3924                 Widget w,
3925                 XEvent *event,
3926                 char **params,
3927                 Cardinal *num_params)
3928 {
3929     XmTextWidget tw = (XmTextWidget)w;
3930
3931     UndoEdit( (Widget)M_editor(tw), event, params, num_params );
3932
3933 } /* end UndoEdit_I */
3934
3935 \f
3936 /*
3937  * XXX All lines in this file marked "XXX Word Wrap workaround"
3938  * XXX are related to a Motif 1.2 Text widget design defect regarding 
3939  * XXX word wrap.  For Motif 1.2, the Text widget was designed so word
3940  * XXX wrap will not function if the scrolled text widget has a 
3941  * XXX horizontal scroll bar ("a hscrollbar means the paper is infinite
3942  * XXX so there is no edge to wrap at").  This change was made in 
3943  * XXX Xm/TextOut.c RCS version 1.71 checked in July, 1991.  A
3944  * XXX CMVC report was filed 9/8/94 & assigned number 4772.
3945  */
3946 #include <Xm/TextOutP.h>                   /* XXX Word Wrap workaround */
3947 static void                                /* XXX Word Wrap workaround */
3948 FixWordWrap(                               /* XXX Word Wrap workaround */
3949         Widget  w,                         /* XXX Word Wrap workaround */
3950         Boolean wrapOn)                    /* XXX Word Wrap workaround */
3951 {                                          /* XXX Word Wrap workaround */
3952   XmTextWidget tw = (XmTextWidget)w;       /* XXX Word Wrap workaround */
3953   OutputData data = tw->text.output->data; /* XXX Word Wrap workaround */
3954   
3955   data->scrollhorizontal = !wrapOn;        /* XXX Word Wrap workaround */
3956 }                                          /* XXX Word Wrap workaround */
3957
3958 static void
3959 Call_TextSelectCallback(
3960         DtEditorWidget  editor)
3961 {
3962
3963    DtEditorSelectCallbackStruct select_cb;
3964
3965    /*
3966     * Call the Editor widget's DtNtextSelectCallback proc 
3967     * if it hasn't been called since the last select.  
3968     */
3969
3970    if ( !M_textSelectCbCalled(editor) ) {
3971
3972         M_textSelectCbCalled(editor) = True;
3973         select_cb.reason = DtEDITOR_TEXT_SELECT;
3974         select_cb.event = (XEvent *)NULL;
3975         XtCallCallbackList ((Widget)editor, M_textSelect(editor),
3976                             (XtPointer) &select_cb);
3977    }
3978
3979 } /* end Call_TextSelectCallback */
3980
3981 static void
3982 Call_TextDeselectCallback(
3983         DtEditorWidget  editor)
3984 {
3985
3986    DtEditorSelectCallbackStruct select_cb;
3987
3988    /*
3989     * Call the Editor widget's DtNtextDeselectCallback proc
3990     * if it hasn't been called since the last deselect.
3991     */
3992
3993    if ( M_textSelectCbCalled(editor) ) {
3994
3995         M_textSelectCbCalled(editor) = False;
3996         select_cb.reason = DtEDITOR_TEXT_DESELECT;
3997         select_cb.event = (XEvent *)NULL;
3998         XtCallCallbackList ((Widget)editor, M_textDeselect(editor),
3999                             (XtPointer) &select_cb);
4000    }
4001
4002 } /* end Call_TextDeselectCallback */
4003
4004 /*
4005  * Editor_SetSelectionProc 
4006  *                 is put into the widget->text.source->SetSelection.
4007  *                 Used to call the DtEditor's select/unselect callbacks
4008  */
4009 static void
4010 Editor_SetSelectionProc(
4011         XmTextSource source,
4012         XmTextPosition left,
4013         XmTextPosition right,
4014         Time set_time )  
4015 {
4016     XmSourceData data = source->data;
4017     Widget                              widget;
4018     XmTextWidget                        tw;
4019     DtEditorWidget                      editor;
4020
4021
4022     /*
4023      * Sanity check
4024      */
4025     if (!XtIsRealized((Widget)data->widgets[0]) ||
4026         data->numwidgets <= 0)
4027         return;
4028
4029     if (left < 0) left = right = 0;
4030
4031     widget = (Widget) data->widgets[0];
4032     tw = (XmTextWidget)widget;
4033     editor = M_editor(tw);
4034
4035     if (!editor->core.being_destroyed) {
4036
4037        if (left < right) {
4038           /*
4039            * There is a selected area if left < right so call the
4040            * DtNtextSelectCallback.
4041            */
4042
4043           Call_TextSelectCallback( editor );
4044
4045        } 
4046        else {
4047           /*
4048            * Left = Right so nothing is selected; call the
4049            * DtNtextDeselectCallback.
4050            */
4051
4052            Call_TextDeselectCallback( editor );
4053
4054        }
4055     }
4056
4057     /* 
4058      * Now, call the text widget's real Set Selection proc
4059      */
4060     (*M_setSelection(editor))(source, left, right, set_time);
4061
4062 } /* end Editor_SetSelectionProc */
4063
4064 \f
4065 /**************************************************************
4066 **
4067 **      Drag and drop routines
4068 **
4069 **/
4070
4071
4072 /*
4073  * Handles drops of a file into the text editor, after validation in the 
4074  * transfer callback.  Files are handled by reading their contents. 
4075  * Text is handled by Motif.
4076  *
4077  * Changing the contents of the text widget occurs here, rather than in
4078  * the transfer callback, because of the visual changes which occur when
4079  * changing the text widget.
4080  */
4081
4082 static void
4083 AnimateCallback(
4084         Widget w,
4085         XtPointer client_data,
4086         XtPointer call_data )
4087
4088     int numItems, ii; 
4089     DtEditorErrorCode   error;
4090
4091     DtDndDropAnimateCallbackStruct *animateInfo = 
4092                                 (DtDndDropAnimateCallbackStruct *) call_data;
4093     DtEditorWidget editor = (DtEditorWidget) client_data;
4094
4095 /* 
4096  * XXX Only really needed if # of items is > 1
4097  */
4098     _DtTurnOnHourGlass( M_topLevelShell(editor) ); 
4099
4100     /*
4101      * How many items are being dropped on us?
4102      */
4103     numItems = animateInfo->dropData->numItems;
4104
4105     switch (animateInfo->dropData->protocol) 
4106     {
4107        case DtDND_FILENAME_TRANSFER:
4108        {
4109          /*
4110           * OK, insert each file we are given
4111           */
4112          for (ii = 0; ii < numItems; ii++) 
4113          {
4114            error = DtEditorInsertFromFile( (Widget)editor, 
4115                                 animateInfo->dropData->data.files[ii] );
4116
4117            /*
4118             * If the file was not inserted successfully, then quit
4119             * (don't care if the file is read only or if it contained 
4120             * nulls that were stripped out).
4121             */
4122            if( error != DtEDITOR_NO_ERRORS && 
4123                error != DtEDITOR_READ_ONLY_FILE &&
4124                error != DtEDITOR_NULLS_REMOVED )
4125            {
4126              ii = numItems; /* break out of loop */
4127            }
4128
4129          } /* end for */
4130
4131          break;
4132
4133        } /* end file transfer case */
4134
4135        case DtDND_BUFFER_TRANSFER:
4136        {
4137          /*
4138           * OK, insert each buffer we are given
4139           */
4140
4141          DtDndBuffer *buffers = animateInfo->dropData->data.buffers;
4142          DtEditorContentRec cr;
4143          cr.type = DtEDITOR_DATA;
4144
4145          for (ii = 0; ii < numItems; ii++) 
4146          {
4147            cr.value.data.buf = buffers[ii].bp;
4148            cr.value.data.length = buffers[ii].size;
4149            
4150            error = DtEditorInsert( (Widget)editor, &cr );
4151
4152            /*
4153             * If the buffer was not inserted successfully, then quit
4154             * (don't care if the file contained nulls that were stripped out).
4155             */
4156            if( error != DtEDITOR_NO_ERRORS && error != DtEDITOR_NULLS_REMOVED )
4157            {
4158              ii = numItems; /* break out of loop */
4159            }
4160
4161          } /* end for */
4162
4163          break;
4164
4165        } /* end buffer transfer case */
4166
4167        case DtDND_TEXT_TRANSFER:
4168        {
4169          /*
4170           * Receiving a text drop.
4171           *
4172           * Text drag and drop is handled by Motif so this switch 
4173           * will never be called.
4174           *
4175           */
4176          break;
4177
4178        } /* end text transfer case */
4179
4180        default:
4181        {
4182        } 
4183
4184     } /* end switch */
4185
4186 /* 
4187  * XXX Only really needed if # of items is > 1
4188  */
4189     _DtTurnOffHourGlass( M_topLevelShell(editor) );
4190
4191 } /* end AnimateCallback */
4192
4193
4194 /*
4195  * Validates a drop of a file into the text widget.  
4196  *
4197  * Changing the contents of the text widget occurs in the animate
4198  * callback, rather than here, because of the visual changes which 
4199  * occur when changing the text widget.
4200  */
4201
4202 /* ARGSUSED */
4203 static void
4204 TransferCallback(
4205         Widget w,
4206         XtPointer client_data,
4207         XtPointer call_data)
4208 {
4209     int numItems, ii; 
4210     DtEditorErrorCode   error;
4211
4212     DtDndTransferCallbackStruct *transferInfo = 
4213                                     (DtDndTransferCallbackStruct *) call_data;
4214
4215     transferInfo->status = DtDND_SUCCESS;
4216
4217     /*
4218      * How many items are being dropped on us?
4219      */
4220     numItems = transferInfo->dropData->numItems;
4221
4222     switch (transferInfo->dropData->protocol) 
4223     {
4224        case DtDND_FILENAME_TRANSFER:
4225        {
4226
4227          /*
4228           * Check to see if we can read each file we are given
4229           */
4230          for (ii = 0; ii < numItems; ii++) 
4231          {
4232            error = _DtEditorValidateFileAccess(
4233                                 transferInfo->dropData->data.files[ii],
4234                                 READ_ACCESS);
4235
4236            /*
4237             * Can't access it for reading so reject drop
4238             */
4239            if ( error != DtEDITOR_NO_ERRORS ) {
4240               transferInfo->status = DtDND_FAILURE;
4241               ii = numItems; /* break out of loop */
4242            }
4243
4244          } /* end for each file */
4245
4246          break;
4247
4248        } /* end file transfer case */
4249
4250        case DtDND_BUFFER_TRANSFER:
4251        {
4252          /*
4253           * Receiving a buffer drop.
4254           *  -- do nothing in transfer
4255           */
4256          break;
4257
4258        } /* end buffer transfer case */
4259
4260        case DtDND_TEXT_TRANSFER:
4261        {
4262          /*
4263           * Receiving a text drop.
4264           *
4265           * Text drag and drop is handled by Motif so this switch 
4266           * will never be called.
4267           *
4268           */
4269          break;
4270
4271        } /* end text transfer case */
4272
4273        default:
4274        {
4275          transferInfo->status = DtDND_FAILURE;
4276          break;
4277        }
4278
4279     } /* end switch */
4280
4281 } /* end TransferCallback */ 
4282
4283
4284 /*-------------------------------------------------------------
4285 **      Function: static void RegisterDropZone ( 
4286 **                              DtEditorWidget w)
4287 **
4288 **      Parameters: A DtEditor widget 
4289 **
4290 **      Purpose:    This routine registers the edit window's text widget 
4291 **                  as a drop site for file & buffer drops.  Because it 
4292 **                  is a text widget it will automatically accept text 
4293 **                  drops.
4294 */
4295 static void
4296 RegisterDropZone(
4297         DtEditorWidget w)
4298 {
4299     int             ac;
4300     Arg             al[2];
4301     
4302     XtCallbackRec transferCB[] = { {TransferCallback, NULL}, {NULL, NULL} };
4303     XtCallbackRec animateCB[] = { {AnimateCallback, NULL}, {NULL, NULL} };
4304     transferCB[0].closure = (XtPointer) w;
4305     animateCB[0].closure = (XtPointer) w;
4306
4307     /*
4308      * Register file & buffer transfers... let Motif handle text DnD
4309      */
4310     ac=0;
4311     XtSetArg( al[ac], DtNdropAnimateCallback, animateCB ); ac++;
4312
4313     DtDndDropRegister( M_text(w), 
4314                        DtDND_FILENAME_TRANSFER|DtDND_BUFFER_TRANSFER,
4315                        XmDROP_COPY, transferCB, al, ac );
4316
4317 } /* end RegisterDropZone */
4318
4319 /*-------------------------------------------------------------
4320 **      Function: static void UnregisterDropZone ( 
4321 **                              DtEditorWidget w)
4322 **
4323 **      Parameters: A DtEditor widget 
4324 **
4325 **      Purpose:    This routine unregisters the edit window
4326 */
4327 static void
4328 UnregisterDropZone(
4329         DtEditorWidget w)
4330 {
4331
4332     DtDndDropUnregister( M_text(w) );
4333
4334 } /* end UnregisterDropZone */
4335
4336 /************************************************************************
4337  *
4338  *  SetInfoDialogTitle - Change the title for the Information dialog
4339  *
4340  ************************************************************************/
4341
4342 static void
4343 SetInfoDialogTitle(
4344         DtEditorWidget editor)
4345 {
4346
4347   Arg al[2];
4348
4349   /*
4350    * If the Information dialog has been created, change its title
4351    */
4352   if( M_gen_warning(editor) != (Widget)NULL )
4353   {
4354
4355        /*
4356         * Prepend the DialogTitle resource, if it has been set
4357         */
4358        if( E_dialogTitle(editor) != (XmString)NULL ) {
4359          XmString titleStr;
4360
4361          /*
4362           * Add the "functional title" to the DialogTitle
4363           */
4364          titleStr = XmStringConcat( E_dialogTitle(editor), 
4365                                     E_infoDialogTitle(editor) );
4366
4367          XtSetArg( al[0], XmNdialogTitle, titleStr );
4368          XtSetValues(M_gen_warning(editor), al, 1);
4369
4370          XmStringFree( titleStr );
4371
4372      }
4373      else {
4374          XtSetArg( al[0], XmNdialogTitle, E_infoDialogTitle(editor) );
4375          XtSetValues(M_gen_warning(editor), al, 1);
4376      }
4377   }
4378
4379 } /* end SetInfoDialogTitle */
4380
4381 /************************************************************************
4382  *
4383  *  _DtEditorWarning - get a message to the user
4384  *
4385  ************************************************************************/
4386
4387 void 
4388 _DtEditorWarning(
4389         DtEditorWidget editor,
4390         char *mess,
4391         unsigned char dialogType)
4392 {
4393     Arg al[10];
4394     int ac;
4395     char *tmpMess;
4396     XmString tmpStr;
4397  
4398     tmpMess = strdup(mess);
4399
4400     /* create the dialog if it is the first time */
4401     if(M_gen_warning(editor) == (Widget) NULL) 
4402     {
4403         XmString titleStr = (XmString) NULL;
4404         XmString okStr;
4405
4406         ac = 0;
4407
4408        /*
4409         * First, create the dialog's title, prepending the
4410         * DtNdialogTitle resource, if it is set
4411         */
4412
4413         if( E_dialogTitle(editor) != (XmString)NULL ) {
4414           
4415           /*
4416            * Add the "functional title" to the DialogTitle
4417            */
4418           titleStr = XmStringConcat( E_dialogTitle(editor), 
4419                                     E_infoDialogTitle(editor) );
4420
4421           XtSetArg (al[ac], XmNdialogTitle, titleStr ); ac++;
4422
4423         }
4424         else {
4425           XtSetArg (al[ac], XmNdialogTitle, E_infoDialogTitle(editor)); ac++;
4426         }
4427
4428         okStr = XmStringCreateLocalized((char*) _DtOkString);
4429         XtSetArg (al[ac], XmNokLabelString, okStr); ac++;
4430         M_gen_warning(editor) = (Widget) XmCreateMessageDialog(
4431                                                M_topLevelShell(editor), "Warn",
4432                                                al, ac);
4433
4434         if (titleStr != (XmString) NULL)
4435           XmStringFree( titleStr );
4436         XmStringFree(okStr);
4437
4438         /* Set the correct font lists for the message & OK button. */
4439         XtSetArg (al[0], XmNfontList, E_buttonFontList(editor));
4440         XtSetValues( 
4441            XmMessageBoxGetChild(M_gen_warning(editor), XmDIALOG_OK_BUTTON),
4442            al, 1) ;
4443
4444         XtSetArg (al[0], XmNfontList, E_labelFontList(editor));
4445         XtSetValues( 
4446            XmMessageBoxGetChild(M_gen_warning(editor), XmDIALOG_MESSAGE_LABEL),
4447            al, 1) ;
4448
4449         /* Unmanage unneeded children. */
4450         XtUnmanageChild ( XmMessageBoxGetChild(M_gen_warning(editor), 
4451                                                  XmDIALOG_CANCEL_BUTTON) );
4452         XtUnmanageChild ( XmMessageBoxGetChild(M_gen_warning(editor),
4453                                                  XmDIALOG_HELP_BUTTON) );
4454
4455         XtRealizeWidget (M_gen_warning(editor));
4456         ac=0;
4457         XtSetArg(al[ac], XmNmwmInputMode, 
4458                  MWM_INPUT_PRIMARY_APPLICATION_MODAL);ac++;
4459         XtSetValues(XtParent(M_gen_warning(editor)), al, ac);
4460     }
4461
4462     tmpStr = XmStringCreateLocalized(tmpMess);
4463     ac = 0;
4464     XtSetArg(al[ac], XmNdialogType, dialogType); ac++; 
4465     XtSetArg(al[ac], XmNmessageString, tmpStr); ac++;
4466     XtSetValues(M_gen_warning(editor), al, ac);
4467     XmStringFree(tmpStr);
4468
4469     XtFree( (char *) tmpMess );
4470
4471     XtManageChild (M_gen_warning(editor));
4472
4473 } /* end _DtEditorWarning */ 
4474
4475
4476 /*********************************************************************
4477  *
4478  * The following section contains the procedures related to the staus
4479  * line
4480  *
4481  *********************************************************************/
4482
4483 #define FORCE           True
4484 #define DONT_FORCE      False
4485
4486 /*
4487  * PositionActivateCB is invoked when the user presses [Return] after
4488  * (presumably) modifying the current line text field.  It retrieves
4489  * the user specified line number and calls DtEditorGoToLine().
4490  */
4491  
4492 /* ARGSUSED */
4493 static void
4494 PositionActivateCB(
4495         Widget w,
4496         caddr_t client_data,
4497         caddr_t call_data )
4498 {
4499     DtEditorWidget editor = (DtEditorWidget)client_data;
4500     char *lineStr = XmTextFieldGetString(M_status_lineText(editor));
4501     int newLineNum = atoi(lineStr);
4502     XtFree(lineStr);
4503
4504     DtEditorGoToLine ((Widget)editor, newLineNum);
4505     XmProcessTraversal(M_text(editor), XmTRAVERSE_CURRENT);
4506
4507 } /* PositionActivateCB */
4508
4509 /* 
4510  * _DtEditorUpdateLineDisplay updates the current & total line displays
4511  * in the status line, if needed.  Normally, the displays are not changed 
4512  * if the correct numbers are (supposedly) displayed.  Setting forceUpdate 
4513  * will cause the numbers to be updated anyways.  This is primarily used
4514  * when the user enters a number into the current line display to force
4515  * display of the correct number.
4516  */
4517 void
4518 _DtEditorUpdateLineDisplay(
4519         DtEditorWidget  editor,
4520         int             currentLine,
4521         Boolean         forceUpdate )
4522 {
4523     XmTextWidget tw = (XmTextWidget) M_text(editor);
4524     Arg         al[10];
4525     char        tmpChars[8];
4526     int         lastLine;
4527     XmString    tmpXmStr;
4528
4529     /*
4530      * Only change the current & total lines displays if the status 
4531      * line is visible
4532      */
4533     if ( M_status_showStatusLine(editor) == True )
4534     {
4535       /* 
4536        * Current line
4537        */
4538       if (M_status_currentLine(editor) != currentLine || forceUpdate) 
4539       {
4540         sprintf(tmpChars, "%d", currentLine);
4541         XmTextFieldSetString(M_status_lineText(editor), tmpChars);
4542         M_status_currentLine(editor) = currentLine;
4543       }
4544
4545       /*
4546        * Total lines
4547        */
4548       lastLine = tw->text.total_lines;
4549       if(M_status_lastLine(editor) != lastLine )
4550       {
4551
4552         sprintf(tmpChars, "%d", lastLine);
4553         tmpXmStr = XmStringCreateLocalized(tmpChars); 
4554         XtSetArg(al[0], XmNlabelString, tmpXmStr); 
4555         XtSetValues( M_status_totalText(editor), al, 1 );
4556
4557         XmStringFree(tmpXmStr);
4558         M_status_lastLine(editor) = lastLine;
4559
4560       }
4561     }
4562 } /* end _DtEditorUpdateLineDisplay */
4563
4564
4565 static void
4566 UpdateOverstrikeIndicator( 
4567         DtEditorWidget  widget,
4568         Boolean         overstrikeOn )
4569 {
4570     Arg            al[10];
4571     register       int ac;
4572     DtEditorWidget ew = (DtEditorWidget) widget;
4573  
4574     /*
4575      * Only change the overstrike indicator if the status line is visible
4576      */
4577     if ( M_status_showStatusLine(ew) == True &&
4578          M_status_overstrikeWidget(ew) != (Widget) NULL )
4579     {
4580        ac=0;
4581
4582        if ( overstrikeOn == True ) {
4583          XtSetArg(al[ac], XmNlabelString, M_status_overstrikeLabel(ew)); ac++;
4584        }
4585        else {
4586          XtSetArg(al[ac], XmNlabelString, M_status_insertLabel(ew)); ac++;
4587        }
4588
4589        XtSetValues( M_status_overstrikeWidget(ew), al, ac );
4590     }
4591
4592 } /* end UpdateOverstrikeIndicator */
4593
4594
4595 int
4596 _DtEditorGetLineIndex(
4597         XmTextWidget tw,
4598         XmTextPosition pos)
4599 {
4600     int startLine, lastLine, middleLine;
4601     XmTextLineTable lineTab = tw->text.line_table;
4602
4603     startLine = 0;
4604     lastLine = tw->text.total_lines - 1;
4605
4606     while(startLine != lastLine)
4607     {
4608         middleLine = (startLine + lastLine)/2;
4609         if(middleLine == startLine || middleLine == lastLine)
4610         {
4611             /*
4612              * We're down to 2 lines.  It's gotta be on one of these
4613              * two lines.
4614              */
4615             if(pos < (XmTextPosition) lineTab[lastLine].start_pos)
4616                 lastLine = startLine;
4617             else
4618                 startLine = lastLine;
4619         }
4620         else
4621         {
4622             if (pos < (XmTextPosition) lineTab[middleLine].start_pos)
4623                 lastLine = middleLine;
4624             else
4625                 startLine = middleLine;
4626         }
4627     }
4628     return startLine;
4629 } /* end _DtEditorGetLineIndex */
4630
4631
4632 /*
4633  * SetCursorPosStatus is called as an XmNmotionVerifyCallback on the
4634  * text widget when the statusLine is turned on.  It computes and
4635  * displays the new line of the insert cursor.
4636  */
4637 static void
4638 SetCursorPosStatus(
4639         Widget w,
4640         caddr_t client_data,
4641         caddr_t call_data )
4642 {
4643     DtEditorWidget editor = (DtEditorWidget)client_data;
4644     XmTextWidget tw = (XmTextWidget)w;
4645     XmTextVerifyCallbackStruct * cb = (XmTextVerifyCallbackStruct *) call_data;
4646     int startLine;
4647
4648     startLine = _DtEditorGetLineIndex(tw, cb->newInsert) + 1;
4649
4650     _DtEditorUpdateLineDisplay( editor, startLine, FORCE );
4651
4652 } /* end SetCursorPosStatus */
4653
4654
4655 static void
4656 SetStatusLine(
4657         DtEditorWidget  ew,
4658         Boolean statusLineOn)
4659 {
4660    Arg          al[10];
4661    register int ac;
4662    int currentLine;
4663    XmTextPosition cursorPos;
4664
4665    M_status_showStatusLine(ew) = statusLineOn;
4666
4667    if( statusLineOn == True )
4668    {
4669      if( M_status_statusArea(ew) == (Widget)NULL )
4670         M_status_statusArea(ew) = CreateStatusLine( ew ); 
4671
4672      /*
4673       * Update the line counts
4674       */
4675
4676      cursorPos = (XmTextPosition)DtEditorGetInsertionPosition( (Widget)ew );
4677      currentLine = _DtEditorGetLineIndex( (XmTextWidget) M_text(ew), 
4678                                           cursorPos ) + 1;
4679      _DtEditorUpdateLineDisplay( ew, currentLine, DONT_FORCE );
4680
4681      /*
4682       * Update the overstrike indicator
4683       */
4684      UpdateOverstrikeIndicator( ew, M_overstrikeMode(ew) );
4685
4686      /* 
4687       * Show the status line
4688       */
4689      
4690      XtManageChild( M_status_statusArea(ew) );
4691
4692      /*
4693       * Hook the scrolled text widget to the status line
4694       */
4695      ac = 0;
4696      XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_WIDGET ); ac++;
4697      XtSetArg( al[ac], XmNbottomWidget, M_status_statusArea(ew) ); ac++;
4698      XtSetValues( XtParent(M_text(ew)), al, ac );
4699      
4700      XtAddCallback( M_text(ew), XmNmotionVerifyCallback,
4701                     (XtCallbackProc) SetCursorPosStatus, (XtPointer)ew);
4702
4703    }
4704    else 
4705    {
4706      /*
4707       * Hook the scrolled text widget to the bottom of the form
4708       */
4709      ac = 0;
4710      XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_FORM ); ac++;
4711      XtSetValues( XtParent(M_text(ew)), al, ac );
4712
4713      XtRemoveCallback( M_text(ew), XmNmotionVerifyCallback,
4714                     (XtCallbackProc) SetCursorPosStatus, (XtPointer)ew);
4715
4716      /* 
4717       * Hide the status line
4718       */
4719      if( M_status_statusArea(ew) != (Widget)NULL )
4720        XtUnmanageChild( M_status_statusArea(ew) );
4721
4722    }
4723
4724 } /* SetStatusLine */
4725
4726
4727 /************************************************************************
4728  *
4729  * CreateStatusLine - Creates the status line
4730  *
4731  ************************************************************************/
4732
4733 static Widget   
4734 CreateStatusLine(
4735         DtEditorWidget parent)
4736 {
4737     Arg         al[20];
4738     int         ac;
4739     Widget      container;
4740     XmString    tmpStr;
4741     Pixel       background, foreground;
4742
4743     /* 
4744      * Match the background & foreground colors of the edit window
4745      * Don't use DtNtextBackground/Foreground directly because they 
4746      * will be DtUNSPECIFIED.
4747      */
4748     ac = 0;
4749     XtSetArg(al[ac], XmNforeground, &foreground); ac++;
4750     XtSetArg(al[ac], XmNbackground, &background); ac++;
4751     XtGetValues(M_text(parent), al, ac);
4752
4753     /*
4754      * Create the status line container
4755      */
4756     ac = 0;
4757     XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_FORM ); ac++;
4758     XtSetArg( al[ac], XmNleftAttachment, XmATTACH_FORM ); ac++;
4759     XtSetArg( al[ac], XmNrightAttachment, XmATTACH_FORM ); ac++;
4760     XtSetArg( al[ac], XmNverticalSpacing, 3 ); ac++;
4761     XtSetArg( al[ac], XmNhorizontalSpacing, 3 ); ac++;
4762     container = (Widget) XmCreateForm( (Widget)parent, "statusLine", 
4763                                             al, ac );
4764
4765     /*
4766      * Create the current line label and text field
4767      */
4768     ac = 0;
4769     if (E_status_currentLineLabel(parent) != (XmString)DtUNSPECIFIED)
4770     {
4771       /*
4772        * Use the resource value & clear it (to save space).
4773        */
4774       tmpStr = XmStringCopy(E_status_currentLineLabel(parent));
4775       E_status_currentLineLabel(parent) = (XmString)DtUNSPECIFIED;
4776     }
4777     else {
4778       /*
4779        * The resource has not been set so use its default value
4780        */
4781       tmpStr = XmStringCreateLocalized(LINE);
4782     }
4783
4784     XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_FORM ); ac++;
4785     XtSetArg( al[ac], XmNtopAttachment, XmATTACH_FORM ); ac++;
4786     XtSetArg( al[ac], XmNleftAttachment, XmATTACH_FORM ); ac++;
4787
4788     XtSetArg(al[ac], XmNlabelString, tmpStr);   ac++;
4789     XtSetArg(al[ac], XmNfontList, E_labelFontList(parent) ); ac++;
4790     M_status_lineLabel(parent) = (Widget) XmCreateLabelGadget( container, 
4791                                                 "lineLabel", al, ac);
4792     XtManageChild(M_status_lineLabel(parent));
4793     XtAddCallback(M_status_lineLabel(parent), XmNhelpCallback,
4794                   (XtCallbackProc)HelpStatusCurrentLineCB, parent);
4795     XmStringFree(tmpStr);
4796
4797     ac = 0;
4798     XtSetArg(al[ac], XmNcolumns, 6);    ac++;
4799     XtSetArg(al[ac], XmNforeground, foreground); ac++;
4800     XtSetArg(al[ac], XmNbackground, background); ac++;
4801     XtSetArg( al[ac], XmNfontList, E_textFontList(parent)); ac++;
4802     XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_FORM ); ac++;
4803     XtSetArg( al[ac], XmNtopAttachment, XmATTACH_FORM ); ac++;
4804     XtSetArg( al[ac], XmNleftAttachment, XmATTACH_WIDGET ); ac++;
4805     XtSetArg( al[ac], XmNleftWidget, M_status_lineLabel(parent) ); ac++;
4806     M_status_lineText(parent) = XmCreateTextField( container, "lineText", 
4807                                                    al, ac );
4808     XtManageChild(M_status_lineText(parent));
4809     XtAddCallback(M_status_lineText(parent), XmNactivateCallback,
4810                   (XtCallbackProc)PositionActivateCB, parent);
4811     XtAddCallback(M_status_lineText(parent), XmNhelpCallback,
4812                   (XtCallbackProc)HelpStatusCurrentLineCB, parent);
4813
4814     /*
4815      * Create the total lines labels
4816      */
4817     ac = 0;
4818     if (E_status_totalLineCountLabel(parent) != (XmString)DtUNSPECIFIED)
4819     {
4820       /*
4821        * Use the resource value & clear it (to save space).
4822        */
4823       tmpStr = XmStringCopy(E_status_totalLineCountLabel(parent));
4824       E_status_totalLineCountLabel(parent) = (XmString)DtUNSPECIFIED;
4825     }
4826     else {
4827       /*
4828        * The resource has not been set so use its default value
4829        */
4830       tmpStr = XmStringCreateLocalized(TOTAL);
4831     }
4832
4833     XtSetArg(al[ac], XmNlabelString, tmpStr);   ac++;
4834     XtSetArg(al[ac], XmNfontList, E_labelFontList(parent) ); ac++;
4835     XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_FORM ); ac++;
4836     XtSetArg( al[ac], XmNtopAttachment, XmATTACH_FORM ); ac++;
4837     XtSetArg( al[ac], XmNleftAttachment, XmATTACH_WIDGET ); ac++;
4838     XtSetArg( al[ac], XmNleftWidget, M_status_lineText(parent) ); ac++;
4839     M_status_totalLabel(parent) = (Widget) XmCreateLabelGadget( container, 
4840                                                 "totalLabel", al, ac);
4841     XtManageChild(M_status_totalLabel(parent));
4842     XtAddCallback(M_status_totalLabel(parent), XmNhelpCallback,
4843                   (XtCallbackProc)HelpStatusTotalLinesCB, parent);
4844     XmStringFree(tmpStr);
4845
4846     ac = 0;
4847     XtSetArg(al[ac], XmNfontList, E_labelFontList(parent) ); ac++;
4848     XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_FORM ); ac++;
4849     XtSetArg( al[ac], XmNtopAttachment, XmATTACH_FORM ); ac++;
4850     XtSetArg( al[ac], XmNleftAttachment, XmATTACH_WIDGET ); ac++;
4851     XtSetArg( al[ac], XmNleftWidget, M_status_totalLabel(parent) ); ac++;
4852     M_status_totalText(parent) = (Widget) XmCreateLabelGadget( container, 
4853                                                 "totalText", al, ac);
4854     XtManageChild(M_status_totalText(parent));
4855     XtAddCallback(M_status_totalText(parent), XmNhelpCallback,
4856                   (XtCallbackProc)HelpStatusTotalLinesCB, parent);
4857
4858     /*
4859      * Create the overstrike indicator
4860      */
4861     ac = 0;
4862     /* 
4863     XtSetArg(al[ac], XmNrecomputeSize, False); ac++; 
4864     */
4865     XtSetArg(al[ac], XmNmarginLeft, 0); ac++;
4866     XtSetArg(al[ac], XmNmarginRight, 0); ac++;
4867     XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
4868     XtSetArg( al[ac], XmNrightOffset, 3 ); ac++;
4869     XtSetArg(al[ac], XmNfontList, E_labelFontList(parent) ); ac++;
4870     XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_FORM ); ac++;
4871     XtSetArg( al[ac], XmNtopAttachment, XmATTACH_FORM ); ac++;
4872     XtSetArg( al[ac], XmNrightAttachment, XmATTACH_FORM ); ac++;
4873     M_status_overstrikeWidget(parent) = 
4874         (Widget) XmCreateLabelGadget( container, "overstrikeLabel", al, ac);
4875     XtManageChild(M_status_overstrikeWidget(parent));
4876     XtAddCallback(M_status_overstrikeWidget(parent), XmNhelpCallback,
4877                   (XtCallbackProc)HelpStatusOverstrikeCB, parent);
4878
4879     /*
4880      * Create the application message area
4881      */
4882     ac = 0;
4883     XtSetArg(al[ac], XmNbackground, parent->core.background_pixel); ac++;
4884     XtSetArg(al[ac], XmNforeground, foreground); ac++;
4885     XtSetArg( al[ac], XmNfontList, E_textFontList(parent)); ac++;
4886     XtSetArg(al[ac], XmNeditable, False); ac++;
4887     XtSetArg(al[ac], XmNcursorPositionVisible, False); ac++;
4888     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
4889     XtSetArg( al[ac], XmNbottomAttachment, XmATTACH_FORM ); ac++;
4890     XtSetArg( al[ac], XmNtopAttachment, XmATTACH_FORM ); ac++;
4891     XtSetArg( al[ac], XmNleftAttachment, XmATTACH_WIDGET ); ac++;
4892     XtSetArg( al[ac], XmNleftWidget, M_status_totalText(parent) ); ac++;
4893     XtSetArg( al[ac], XmNleftOffset, 17 ); ac++;
4894     XtSetArg( al[ac], XmNrightAttachment, XmATTACH_WIDGET ); ac++;
4895     XtSetArg(al[ac], XmNrightWidget, M_status_overstrikeWidget(parent)); ac++;
4896     M_status_messageText(parent) = 
4897                       XmCreateTextField( container, "messageText", al, ac );
4898
4899     XtManageChild(M_status_messageText(parent));
4900     XtAddCallback(M_status_messageText(parent), XmNhelpCallback,
4901                   (XtCallbackProc)HelpStatusMessageCB, parent);
4902
4903     return( container );
4904
4905 } /* end CreateStatusLine */
4906
4907
4908 /*********************************************************************
4909  *
4910  * The following section contains the procedures related to help
4911  *
4912  *********************************************************************/
4913
4914
4915 static void
4916 CallHelpCallback(
4917         DtEditorWidget  editor,
4918         int             reason)
4919 {
4920     DtEditorHelpCallbackStruct      help_cb;
4921
4922     help_cb.reason = reason;
4923     help_cb.event = (XEvent *) NULL;
4924     XtCallCallbackList( (Widget)editor, M_HelpCB(editor), 
4925                         (XtPointer) &help_cb );
4926
4927 } /* end CallHelpCallback */
4928
4929 /****
4930  * Edit window help callbacks
4931  */
4932
4933 /* ARGSUSED */
4934 static void
4935 HelpEditWindowCB(
4936         Widget w,
4937         caddr_t client_data,
4938         caddr_t call_data )
4939 {
4940     CallHelpCallback((DtEditorWidget)client_data, DtEDITOR_HELP_EDIT_WINDOW);
4941 }
4942
4943 /****
4944  * Status Line help callbacks
4945  */
4946
4947 /* XXX
4948  * Who uses this??
4949  */
4950
4951 /* ARGSUSED */
4952 static void
4953 HelpStatusLineCB(
4954         Widget w,
4955         caddr_t client_data,
4956         caddr_t call_data )
4957 {
4958     CallHelpCallback((DtEditorWidget)client_data, DtEDITOR_HELP_STATUS_LINE);
4959 }
4960
4961 /* ARGSUSED */
4962 static void
4963 HelpStatusCurrentLineCB(
4964         Widget w,
4965         caddr_t client_data,
4966         caddr_t call_data )
4967 {
4968     CallHelpCallback( (DtEditorWidget)client_data, 
4969                       DtEDITOR_HELP_STATUS_CURRENT_LINE );
4970 }
4971
4972 /* ARGSUSED */
4973 static void
4974 HelpStatusTotalLinesCB(
4975         Widget w,
4976         caddr_t client_data,
4977         caddr_t call_data )
4978 {
4979     CallHelpCallback( (DtEditorWidget)client_data, 
4980                       DtEDITOR_HELP_STATUS_TOTAL_LINES );
4981 }
4982
4983 /* ARGSUSED */
4984 static void
4985 HelpStatusMessageCB(
4986         Widget w,
4987         caddr_t client_data,
4988         caddr_t call_data )
4989 {
4990     CallHelpCallback( (DtEditorWidget)client_data, 
4991                       DtEDITOR_HELP_STATUS_MESSAGE );
4992 }
4993
4994 /* ARGSUSED */
4995 static void
4996 HelpStatusOverstrikeCB(
4997         Widget w,
4998         caddr_t client_data,
4999         caddr_t call_data )
5000 {
5001     CallHelpCallback( (DtEditorWidget)client_data, 
5002                       DtEDITOR_HELP_STATUS_OVERSTRIKE );
5003 }
5004
5005 /****
5006  * Format Settings dialog help callbacks
5007  */
5008
5009 /* ARGSUSED */
5010 static void
5011 HelpFormatDialogCB(
5012         Widget w,
5013         caddr_t client_data,
5014         caddr_t call_data )
5015 {
5016     CallHelpCallback((DtEditorWidget)client_data, DtEDITOR_HELP_FORMAT_DIALOG);
5017 }
5018
5019 /* ARGSUSED */
5020 static void
5021 HelpFormatRightMarginCB(
5022         Widget w,
5023         caddr_t client_data,
5024         caddr_t call_data )
5025 {
5026   CallHelpCallback( (DtEditorWidget)client_data, 
5027                     DtEDITOR_HELP_FORMAT_RIGHT_MARGIN);
5028 }
5029
5030 /* ARGSUSED */
5031 static void
5032 HelpFormatLeftMarginCB(
5033         Widget w,
5034         caddr_t client_data,
5035         caddr_t call_data )
5036 {
5037     CallHelpCallback( (DtEditorWidget)client_data, 
5038                       DtEDITOR_HELP_FORMAT_LEFT_MARGIN);
5039 }
5040
5041 /* ARGSUSED */
5042 static void
5043 HelpFormatJustifyButtonsCB(
5044         Widget w,
5045         caddr_t client_data,
5046         caddr_t call_data )
5047 {
5048     CallHelpCallback( (DtEditorWidget)client_data, 
5049                       DtEDITOR_HELP_FORMAT_ALIGNMENT);
5050 }
5051
5052 /****
5053  * Find/Change & Spell dialogs help callbacks
5054  */
5055
5056 /* ARGSUSED */
5057 void
5058 _DtEditorHelpSearchCB(
5059         Widget w,
5060         caddr_t client_data,
5061         caddr_t call_data )
5062 {
5063     DtEditorWidget editor = (DtEditorWidget)client_data;
5064
5065     switch (M_search_dialogMode(editor))
5066     {
5067        case SPELL:
5068           CallHelpCallback( (DtEditorWidget)client_data, 
5069                             DtEDITOR_HELP_SPELL_DIALOG);
5070           break;
5071        case REPLACE:
5072        default:
5073           CallHelpCallback( (DtEditorWidget)client_data, 
5074                              DtEDITOR_HELP_CHANGE_DIALOG);
5075           break;
5076     }
5077 } /* _DtEditorHelpSearchCB */
5078
5079 /* ARGSUSED */
5080 void
5081 _DtEditorHelpSearchFindCB(
5082         Widget w,
5083         caddr_t client_data,
5084         caddr_t call_data )
5085 {
5086     CallHelpCallback( (DtEditorWidget)client_data, 
5087                       DtEDITOR_HELP_CHANGE_FIND);
5088 }
5089 /* ARGSUSED */
5090 void
5091 _DtEditorHelpSearchChangeCB(
5092         Widget w,
5093         caddr_t client_data,
5094         caddr_t call_data )
5095 {
5096     DtEditorWidget editor = (DtEditorWidget)client_data;
5097
5098     switch (M_search_dialogMode(editor))
5099     {
5100        case SPELL:
5101           CallHelpCallback( (DtEditorWidget)client_data, 
5102                             DtEDITOR_HELP_SPELL_CHANGE);
5103           break;
5104        case REPLACE:
5105        default:
5106           CallHelpCallback( (DtEditorWidget)client_data, 
5107                              DtEDITOR_HELP_CHANGE_CHANGE);
5108           break;
5109     }
5110 } /* _DtEditorHelpSearchChangeCB */
5111
5112 /* ARGSUSED */
5113 void
5114 _DtEditorHelpSearchSpellCB(
5115         Widget w,
5116         caddr_t client_data,
5117         caddr_t call_data )
5118 {
5119     CallHelpCallback( (DtEditorWidget)client_data, 
5120                       DtEDITOR_HELP_SPELL_MISSPELLED_WORDS);
5121 }
5122
5123 /*********************************************************************
5124  *
5125  * The following section contains the procedures related to formating
5126  * text and the Format Settings dialog.
5127  *
5128  *********************************************************************/
5129
5130 /*
5131  * Do simple formatting of paragraphs of text.
5132  * Designed for speed, at some cost in complexity and redundancy.
5133  *
5134  * There is a minor undocumented bug in Dump().  It calls Justify() in the
5135  * case where the last word of the last line of a paragraph is an end-of-
5136  * sentence word (typical) and ends just one blank before the margin
5137  * (rare).  This results in one blank being inserted in the line when it's
5138  * not necessary.  It happens because the two trailing blanks after the
5139  * word cause an "ordinary" line dump before Fill() sees the next line and
5140  * knows it has an end of paragraph.  WARNING:  The situation would be
5141  * aggravated if FillWord() ever set blanks to an even larger number.
5142  */
5143
5144 /*
5145 ** This section contains changes for EUC_4B compatibility.
5146 ** WPI interface is used.
5147  */
5148
5149 /* Global Variables and extern declarations */
5150
5151 typedef struct _WORD{           /* describe one word            */
5152         wint_t  *cp;            /* word location in buffer      */
5153         int     inlinenum;      /* word start line in input     */
5154         int     incolumn;       /* word start column in input   */
5155         int     length;         /* size of word                 */
5156         int     score;          /* word + next for jflag        */
5157         int     blanks;         /* output trailing blanks need  */
5158         int     wclen;          /* Length of wide character word */
5159 } WORD;
5160
5161 typedef struct {
5162   wchar_t       Blank;
5163
5164   AdjRecPtr     pAdj;
5165
5166   /* FORMATTING CONTROL */
5167   int           m0flag;
5168   long          fillmargin;
5169   long          centermiddle;
5170   int           tabsize;        /* tab size in use  */
5171   int           centerstartpara; /* expect para. start? in "Center" */
5172
5173   /* Global/static vars used in "Fill" */
5174   wint_t        *wordbuf;       /* see comments for "Fill" for discussion */
5175   wint_t        *wordcp;
5176   wint_t        *wordcpwrap;
5177
5178   WORD          *word;
5179   WORD          *wordbase;
5180   WORD          *wordlimit;
5181
5182   WORD          *wordfirst;
5183   WORD          *wordat;
5184   WORD          *wordnext;
5185
5186   int           inlinenum;
5187   int           incolumn;
5188   int           outlinenum;
5189
5190   int           pendchars;
5191   int           indent1, indent2;
5192 } FormatData;
5193
5194 #define isekinsoku(wc)   iswctype((wc),ekinclass)
5195 #define isbekinsoku(wc)  iswctype((wc),bekinclass)
5196
5197 #define LINESIZE BUFSIZ         /* how big a line can be */
5198 #define WORDMAX LINESIZE        /* see above for discussion */
5199
5200 #define WORDNEXT(d,at) { if (++at == d->wordlimit) at = d->wordbase; }  /* statement */
5201 #define WORDPREV(d,at) (((at == d->wordbase) ? d->wordlimit : at) - 1)  /* function  */
5202
5203 #include <locale.h>
5204 extern int _nl_space_alt;
5205
5206
5207 /*
5208  * Forward declarations
5209  */
5210 static int DoLine (FormatData *data, register FILE *filep);
5211 static void Center (FormatData *data, 
5212                     wint_t *in_line, register wint_t *inlinelim);
5213 static void Fill (FormatData *data, wint_t *in_line, register wint_t *inlinelim);
5214 static void FillWord (FormatData *data);
5215 static void Dump (FormatData *data, int endpara);
5216 static void PrintIndent (FormatData *data, int indent);
5217 static void PrintTag (FormatData *data, WORD *wordpast);
5218 static void PrintWords (FormatData *data, WORD *wordpast);
5219 static void Justify (FormatData *data, register int blanks, WORD *wordpast);
5220 static int CompareWords (const void *, const void *);
5221 static int EkinBekinProc(FormatData *data, WORD **wordpast);
5222 static void postEkinBekinProc(FormatData *data, int *poutchars, WORD *wordpast);
5223
5224 #if defined(sun)
5225 /*
5226  *  A small workaround for systems that don't have wcwidth...
5227  */
5228 static int
5229 sun_wcwidth(
5230         const wchar_t wc)
5231 {
5232     int status;
5233     char mbstr[MB_LEN_MAX + 1];
5234
5235     status = wctomb(mbstr, wc);
5236
5237     if (status > 0)
5238        return(euccol(mbstr));
5239     else
5240        return(status);
5241 }
5242 #endif /*  sun  */
5243
5244 /*
5245  * The following utilities: lineBlank, findNonBlank, and countBlanks all
5246  * require the lineLen parameter to specify the number of characters, not
5247  * bytes, in the line.
5248  */
5249
5250 static Boolean
5251 lineBlank(
5252         char *pLine, 
5253         int lineLen)
5254 {
5255     int byteNum, charNum;
5256     wchar_t wc;
5257     size_t mbCurMax = MB_CUR_MAX;
5258
5259     for(byteNum = charNum = 0; charNum < lineLen; 
5260         byteNum += mblen(&pLine[byteNum], mbCurMax), charNum++)
5261     {
5262         (void) mbtowc(&wc, &pLine[byteNum], mbCurMax);
5263 #if !(defined(sun) && (_XOPEN_VERSION==3)) && !defined(USL) && !defined(__uxp__)
5264         if( !iswctype(wc, _DtEditor_blankClass) )
5265             return False;
5266 #else
5267         if( !iswblank(wc) )
5268             return False;
5269 #endif /* not sun */
5270     }
5271     return True;
5272 }
5273
5274 static char *
5275 findNonBlank(
5276         char *pLine, 
5277         int lineLen)
5278 {
5279     int byteNum, charNum;
5280     wchar_t wc;
5281     size_t mbCurMax = MB_CUR_MAX;
5282
5283     for(byteNum = charNum = 0; charNum < lineLen; 
5284         byteNum += mblen(&pLine[byteNum], mbCurMax), charNum++)
5285     {
5286         (void) mbtowc(&wc, &pLine[byteNum], mbCurMax);
5287 #if !(defined(sun) && (_XOPEN_VERSION==3)) && !defined(USL) && !defined(__uxp__)
5288         if( !iswctype(wc, _DtEditor_blankClass) )
5289             return &pLine[byteNum];
5290 #else
5291         if(! iswblank(wc) )
5292             return &pLine[byteNum];
5293 #endif /* not sun */
5294     }
5295     return &pLine[byteNum];
5296 }
5297
5298 static int
5299 countBlanks(
5300         char *pLine, 
5301         int lineLen)
5302 {
5303     int byteNum, charNum, count;
5304     wchar_t wc;
5305     size_t mbCurMax = MB_CUR_MAX;
5306
5307     for(byteNum = charNum = 0, count = 0; charNum < lineLen; 
5308         byteNum += mblen(&pLine[byteNum], mbCurMax), charNum++)
5309     {
5310         (void) mbtowc(&wc, &pLine[byteNum], mbCurMax);
5311         if(iswcntrl(wc))
5312         {
5313             if(mblen(&pLine[byteNum], mbCurMax) == 1)
5314             {
5315                switch((int) pLine[byteNum]) 
5316                {
5317                    /*
5318                     * I don't really know what to do with weird embedded chars.
5319                     * This is just a guess.  In non-ascii locales this could
5320                     * screw up, but I don't know how else to deal with
5321                     * weird embedded control characters.
5322                     */
5323                    case '\n': /* newline */
5324                    case '\f': /* form feed */
5325                        count++;
5326                        continue;
5327                    case '\t': /* horizontal tab */
5328                        count += 8;
5329                        continue;
5330                    case '\b': /* backspace */
5331                        count--;
5332                        continue;
5333                    case '\r': /* carriage return */
5334                        count = 0;
5335                        continue;
5336                    default:
5337                        return count;
5338                }
5339             }
5340             else
5341                 count++; /* multibyte control chars??? */
5342             continue;
5343         }
5344 #if !(defined(sun) && (_XOPEN_VERSION==3)) && !defined(USL) && !defined(__uxp__)
5345         if(!iswctype(wc, _DtEditor_blankClass))
5346             return count;
5347 #else
5348         if(! iswblank(wc) )
5349             return count;
5350 #endif /* not sun */
5351
5352         count++;
5353     }
5354     return count;
5355 }
5356
5357 /*
5358  * fixLeftMarginAndNewlines - writes out a substring from the text widget,
5359  * inserting leading blanks as needed to set the left margin, and adding
5360  * newlines at all "virtual" (i.e. word-wrapped) lines.  It assumes that the
5361  * specified substring is an integer number of lines - i.e. the substring
5362  * cannot begin or end in the middle of a line.  Non-complying substrings
5363  * are expanded to encompass whole lines.
5364  */
5365 static void
5366 fixLeftMarginAndNewlines(
5367         DtEditorWidget editor,
5368         FILE *fp,
5369         int leftMargin,
5370         int rightMargin,
5371         int startPos,
5372         int endPos)
5373 {
5374     Widget widget = M_text(editor);
5375     register XmTextLineTable lineTable;
5376     register int i;
5377     int lineIndex, lineLen, nextLen, lineIndent, lastIndex,
5378         lineByteLen, total_lines;
5379     Boolean newPara = True;
5380     char *pLine, *pNext, *pFirstNonBlank, *pLastChar;
5381     size_t mbCurMax = MB_CUR_MAX;
5382
5383     lineTable = _XmTextGetLineTable(widget, &total_lines);
5384
5385     if (leftMargin > rightMargin || leftMargin < 0) 
5386       leftMargin = 0;
5387
5388     lineIndent = leftMargin;
5389
5390     /*
5391      * calculate the starting line number and ending line number
5392      * for the [sub]string we're operating upon.
5393      */
5394     lineIndex = _DtEditorGetLineIndex((XmTextWidget)M_text(editor), startPos);
5395
5396     lastIndex = _DtEditorGetLineIndex((XmTextWidget)M_text(editor), endPos);
5397
5398     /*
5399      * This loop terminates with one line unwritten.  This is correct
5400      * if we're not formatting the last line of the file, as that means
5401      * that we must be formatting a paragraph, and the paragraph adjust
5402      * code has trouble locating the end of a paragraph (as opposed to the
5403      * beginning of the next paragraph.  If the last line of the text is
5404      * to be formatted, it is handled after this loop terminates.
5405      */
5406     for(; lineIndex < lastIndex; lineIndex++)
5407     {
5408         /*
5409          * if the current line was word-wrapped, put out a nl.
5410          */
5411         if(lineTable[lineIndex].virt_line)
5412             fwrite("\n", sizeof(char), 1, fp);
5413
5414         lineLen = lineTable[lineIndex + 1].start_pos - 
5415                      lineTable[lineIndex].start_pos;
5416         pLine = _XmStringSourceGetString((XmTextWidget)M_text(editor), 
5417                     lineTable[lineIndex].start_pos, 
5418                     lineTable[lineIndex + 1].start_pos, False);
5419         pLastChar = _DtEditorGetPointer(pLine, lineLen - 1);
5420         lineByteLen = pLastChar - pLine + mblen(pLastChar, mbCurMax);
5421
5422         if(lineBlank(pLine, lineLen))
5423         {
5424             /*
5425              * Blank lines indicate the start of a new paragraph.
5426              * They also don't require any indent adjustment so are
5427              * quick/easy to write out.
5428              */
5429             fwrite( pLine, sizeof(char), 
5430                     _DtEditorGetPointer(pLine, lineLen) - pLine, fp );
5431             newPara = True;
5432             XtFree(pLine);
5433             continue;
5434         }
5435         if(newPara == True)
5436         {
5437             int firstIndent;
5438             /*
5439              * Calc the proper indent for the first line, and
5440              * the indent for the rest of the lines
5441              * in the paragraph.  If there's only one line in the
5442              * paragraph, then the proper indent is adjustStuff.left_margin.
5443              */
5444
5445             /*
5446              * Get the next line.
5447              */
5448             if((total_lines - lineIndex) > 2) 
5449                 nextLen = lineTable[lineIndex + 2].start_pos -
5450                           lineTable[lineIndex + 1].start_pos;
5451             else
5452                 nextLen = XmTextGetLastPosition(widget) - 
5453                                         lineTable[lineIndex + 1].start_pos;
5454             pNext = _XmStringSourceGetString((XmTextWidget)M_text(editor), 
5455                     lineTable[lineIndex + 1].start_pos, 
5456                     lineTable[lineIndex + 1].start_pos + nextLen, False);
5457
5458             if(lineBlank(pNext, nextLen)) /* single line paragraph */
5459                 firstIndent = lineIndent = leftMargin;
5460             else 
5461             {
5462                 int curFirstIndent, curSecondIndent, offset;
5463
5464                 curFirstIndent = countBlanks(pLine, lineLen);
5465                 curSecondIndent = countBlanks(pNext, nextLen);
5466
5467                 offset = curFirstIndent - curSecondIndent;
5468                 if(offset >= 0)
5469                 {
5470                     /* second line is closer to the left margin */
5471
5472                     /*
5473                      * Note, the first line will still be indented even
5474                      * if the remaining words in the paragraph can
5475                      * all fit on the first line.  The end result is a 
5476                      * one line indented paragraph.  I am mentioning
5477                      * this because some may think this is a defect.
5478                      */
5479
5480                     firstIndent = leftMargin + offset;
5481                     lineIndent = leftMargin;
5482                 }
5483                 else
5484                 {
5485                     firstIndent = leftMargin;
5486                     lineIndent = leftMargin - offset;
5487                 }
5488             }
5489             for(i = firstIndent; i-- > 0;)
5490                 fwrite(" ", sizeof(char), 1, fp); /* that's a _space_ */
5491             pFirstNonBlank = findNonBlank(pLine, lineLen);
5492             fwrite(pFirstNonBlank, sizeof(char), lineByteLen - 
5493                    (pFirstNonBlank - pLine), fp);
5494
5495             newPara = False;
5496             XtFree(pLine);
5497             continue;
5498         }
5499         for(i = lineIndent; i-- > 0;)
5500             fwrite(" ", sizeof(char), 1, fp); /* that's a _space_ */
5501         pFirstNonBlank = findNonBlank(pLine, lineLen);
5502         fwrite(pFirstNonBlank, sizeof(char), lineByteLen - 
5503                (pFirstNonBlank - pLine), fp);
5504         XtFree(pLine);
5505     }
5506
5507     if((total_lines - lineIndex) == 1)
5508     {
5509        /*
5510         * Now we have to handle the last line.
5511         */
5512        if(lineTable[lineIndex].virt_line)
5513            fwrite("\n", sizeof(char), 1, fp);
5514     
5515        if((total_lines - lineIndex) > 2) 
5516            lineLen = lineTable[lineIndex + 1].start_pos -
5517                      lineTable[lineIndex].start_pos;
5518        else
5519            lineLen = XmTextGetLastPosition(widget) - 
5520                   lineTable[lineIndex].start_pos;
5521
5522        if(lineLen > 0)
5523        {
5524            for(i = lineIndent; i-- > 0;)
5525                fwrite(" ", sizeof(char), 1, fp); /* that's a _space_ */
5526
5527            pLine = _XmStringSourceGetString((XmTextWidget)M_text(editor), 
5528                     lineTable[lineIndex].start_pos, 
5529                     lineTable[lineIndex].start_pos + lineLen, False);
5530            pLastChar = _DtEditorGetPointer(pLine, lineLen - 1);
5531            lineByteLen = pLastChar - pLine + mblen(pLastChar, mbCurMax);
5532            if(lineBlank(pLine, lineLen))
5533            {
5534                fwrite(pLine, sizeof(char), lineByteLen, fp);
5535            }
5536            else
5537            {
5538                pFirstNonBlank = findNonBlank(pLine, lineLen);
5539                fwrite(pFirstNonBlank, sizeof(char), lineByteLen - 
5540                       (pFirstNonBlank - pLine), fp);
5541            }
5542            XtFree(pLine);
5543        }
5544     }
5545     XtFree((XtPointer)lineTable);
5546 }
5547
5548
5549 /************************************************************************
5550  * FormatText - 
5551  *
5552  * Initialize, check arguments embedded in AdjRec, open and read files,
5553  * and pass a series of lines to lower-level routines.
5554  */
5555
5556 static int 
5557 FormatText ( 
5558         AdjRecPtr 
5559         pAdjRec) 
5560
5561
5562   long          maxmargin;      /* max allowed */ 
5563   register FILE *filep;         /* file to read */ 
5564   int           retVal;
5565   FormatData    data;
5566
5567 /*
5568  * INITIALIZE FOR NLS
5569  */
5570         mbtowc(&data.Blank," ",1);
5571
5572 /*
5573  * Initialize global/statics.
5574  */
5575         if((data.wordbuf = malloc(sizeof(wint_t) * LINESIZE * 3)) == (wint_t *)NULL)
5576                         return 0;
5577         if((data.word  = malloc(sizeof(WORD) * WORDMAX)) == (WORD *)NULL)
5578         {
5579                 retVal = 0;
5580                 goto CleanUp;
5581         }
5582         data.tabsize = 8;                       /* default tab size */
5583         data.centerstartpara = True;
5584
5585         data.fillmargin = data.centermiddle = pAdjRec->margin;
5586         data.m0flag = (data.fillmargin == 0L);
5587
5588         /*
5589          * Initialize global/statics for "Fill".
5590          */
5591         data.wordcp = data.wordbuf;
5592         data.wordcpwrap = data.wordbuf + (LINESIZE * 2);
5593         data.wordbase  = & data.word [0];
5594         data.wordlimit = & data.word [WORDMAX];
5595         data.wordfirst = & data.word [0];
5596         data.wordnext  = & data.word [0];
5597         data.inlinenum  = 0;
5598         data.outlinenum = 1;
5599         data.pendchars = 0;
5600
5601 /*
5602  * CHECK ARGUMENTS:
5603  */
5604
5605         if (pAdjRec->cflag + pAdjRec->jflag + pAdjRec->rflag > 1)
5606         {
5607                         retVal = 0;
5608                         goto CleanUp;
5609         }
5610
5611         maxmargin = pAdjRec->cflag? (LINESIZE / 2) : LINESIZE;
5612         if ((data.fillmargin < 0L) || (data.fillmargin > maxmargin))
5613         {
5614                         retVal = 0;
5615                         goto CleanUp;
5616         }
5617
5618         if ((pAdjRec->tabsize > 0) && (pAdjRec->tabsize <= MAXTABSIZE))
5619                 data.tabsize = pAdjRec->tabsize;
5620
5621 /*
5622  * OPEN AND READ INPUT FILE:
5623  */
5624
5625         filep = pAdjRec->infp;
5626         data.pAdj = pAdjRec; /* set (file) global var to passed in rec */
5627
5628         while (DoLine (&data, filep))
5629                 ;
5630
5631 /*
5632  * DUMP LAST LINE AND EXIT:
5633  */
5634
5635         if (! data.pAdj->cflag)                 /* not centering        */
5636           {
5637             Dump (&data, True);                 /* force end paragraph  */
5638           }
5639
5640         retVal = 1;
5641
5642 CleanUp:
5643         if(data.wordbuf != (wint_t *)NULL)
5644         {
5645                 free(data.wordbuf);
5646         }
5647         if(data.word != (WORD *)NULL)
5648         {
5649                 free(data.word);
5650         }
5651
5652         return retVal;
5653 }
5654
5655
5656 /************************************************************************
5657  * D O   L I N E
5658  *
5659  * Read one input line and do generic processing (read chars from input
5660  * to in_line, crunching backspaces).  Return True if successful, else
5661  * false at end of input file.  This must be done before expanding tabs;
5662  * pass half-processed line to Center() or Fill() for more work.
5663  *
5664  * Assumes getc() is efficient.
5665  * in_line[] is static so it is only allocated once.
5666  */
5667
5668 static int 
5669 DoLine (FormatData      *data,
5670         register FILE   *filep)                 /* open file to read    */
5671 {
5672         wint_t  in_line [LINESIZE];             /* after reading in     */
5673         register wint_t *incp    = in_line;     /* place in in_line     */
5674         register wint_t *incplim = in_line + LINESIZE;  /* limit of in_line */
5675         register wint_t   c;
5676
5677 /*
5678  * READ LINE WITH BACKSPACE CRUNCHING:
5679  */
5680
5681         while (incp < incplim)          /* buffer not full */
5682         {
5683                 c = getwc (filep);      /* get and save wide char */
5684                 switch(c)
5685                 {
5686
5687                         case WEOF:
5688                                 if (incp == in_line)    /* nothing read yet */
5689                                         return (False);
5690
5691                         case L'\0':                     /* fall through  */
5692                         case L'\n':                     /* end of line   */
5693                                 incplim = incp;         /* set limit (quit loop) */
5694                                 break;
5695
5696                         case L'\b':                     /* backspace    */
5697                                 if (incp > in_line)     /* not at start */
5698                                         incp--;         /* just back up */
5699                                 break;
5700
5701                         default:                        /* any other char */
5702                                 *incp++ = c;
5703                                 break;
5704                 }
5705         }
5706         /* now incplim is correctly set to last char + 1 */
5707
5708 /*
5709  * PASS LINE ON FOR MORE WORK:
5710  */
5711
5712         if (data->pAdj->cflag)  Center (data, in_line, incplim);
5713         else    Fill   (data, in_line, incplim);
5714
5715         return (True);                          /* maybe more to read */
5716
5717 } /* DoLine */
5718
5719
5720 /************************************************************************
5721  * C E N T E R
5722  *
5723  * Center text (starting at in_line, ending before inlinelim).  First copy
5724  * chars from in_line to outline skipping nonprintables and expanding tabs.
5725  * For efficiency (at the cost of simplicity), note and skip indentation
5726  * at the same time.  Then, print outline with indentation to center it.
5727  *
5728  * outline[] is static so it is only allocated once; startpara so it is
5729  * used for successive lines.
5730  */
5731
5732 static void
5733 Center (FormatData *data, 
5734         wint_t  *in_line,                       /* start of input line  */
5735         register wint_t *inlinelim)             /* end of line + 1      */
5736 {
5737         register wint_t *incp;          /* pointer in in_line   */
5738         wint_t  outline [LINESIZE + MAXTABSIZE];  /* after generic work */
5739         register wint_t *outcp      = outline;    /* place in outline   */
5740         register wint_t *outlinelim = outline + LINESIZE; /* limit of outline*/
5741
5742         int     haveword  = False;      /* hit word in in_line? */
5743         register wint_t ch;             /* current working char */
5744         register int    needsp;         /* spaces need for tab  */
5745         register int    indent = 0;     /* size of indentation  */
5746         int     textwidth;              /* size of text part    */
5747         int     extwidth = 0;           /* additional width for MBCS */
5748
5749
5750 /*
5751  * SCAN INPUT LINE:
5752  */
5753
5754         for (incp = in_line; (incp < inlinelim) && (outcp < outlinelim); incp++)
5755         {
5756
5757           ch = *incp;
5758
5759 /*
5760  * SKIP WHITE SPACE:
5761  */
5762
5763           if (iswspace(ch))
5764           {
5765             needsp = ((ch != L'\t') && (iswblank(ch))) ? 
5766                      1 : data->tabsize - ((indent + outcp - outline) % data->tabsize);
5767
5768             if (! haveword)             /* indentation */
5769                 indent += needsp;
5770             else                        /* past text */
5771                 for ( ; needsp > 0; needsp--)
5772                   *outcp++ = data->Blank;
5773           }
5774
5775 /*
5776  * CARRY OVER PRINTABLE CHARS AND NOTE INDENTATION:
5777  */
5778
5779           else if (iswprint (ch))       /* note: ch != ' ' */
5780           {
5781              *outcp++ = ch;             /* just copy it over */
5782              haveword = True;
5783             if(MB_CUR_MAX > 1 && wcwidth(ch) > 1)
5784                 extwidth += wcwidth(ch) - 1;
5785           }
5786
5787 /* else do nothing, which tosses other chars */
5788
5789         } /* end for */
5790
5791         /* Now outcp is the new outlinelim */
5792
5793 /*
5794  * HANDLE BLANK LINE (no text):
5795  */
5796
5797         if (! haveword)
5798         {
5799           putc ('\n', data->pAdj->outfp);       /* "eat" any whitespace */
5800           data->centerstartpara = True; /* expect new paragraph */
5801         }
5802
5803 /*
5804  * EAT TRAILING BLANKS, SET TEXTWIDTH:
5805  */
5806
5807         else
5808         {
5809           /* note that outcp > outline */
5810           while ((outcp[-1] != L'\t') && iswblank(outcp [-1]))
5811             outcp--;
5812
5813           textwidth = (outcp - outline);        /* thus textwidth > 0 */
5814
5815 /*
5816  * SET AUTOMARGIN AND PRINT CENTERED LINE:
5817  *
5818  * The equations used depend on truncating division:
5819  *
5820  *              eqn. 1          eqn. 2
5821  *      Margin  Middle  Width   Results
5822  *      odd     exact   odd     exact centering
5823  *      odd     exact   even    extra char to right
5824  *      even    left    odd     extra char to left
5825  *      even    left    even    exact centering (due to "extra" char to right)
5826  *
5827  * When centermiddle is default or given by user, it is the same as the
5828  * first two lines above (middle exactly specified).
5829  */
5830
5831           if (data->centerstartpara)                    /* start of paragraph */
5832           {
5833             data->centerstartpara = False;
5834
5835             if (data->m0flag)                           /* set automargin */
5836               /* 1 */ data->centermiddle = (indent + textwidth + extwidth + 1) / 2;
5837           }
5838
5839           /* 2 */ PrintIndent (data, data->centermiddle - ((textwidth + extwidth + 1) / 2));
5840           {
5841             int i;
5842             for(i = 0; i < textwidth; i++)
5843             {
5844                 putwc(outline[i], data->pAdj->outfp);
5845             }
5846             putc('\n', data->pAdj->outfp);
5847           } 
5848
5849         } /* else */
5850
5851 } /* Center */
5852
5853
5854 /************************************************************************
5855  * WORD DATA STRUCTURES USED TO TRACK WORDS WHILE FILLING:
5856  *
5857  * This complicated scheme is used to minimize the actual data moving
5858  * and manipulation needed to do the job.
5859  *
5860  * Words are kept in wordbuf[] without trailing nulls.  It is large enough
5861  * to accomodate two lines' worth of words plus wrap around to start a new
5862  * word (which might be as big as a line) without overwriting old words
5863  * not yet dumped.  wordcp -> next free location in wordbuf[];
5864  * wordcpwrap -> last place a new word is allowed to start.
5865  *
5866  * Words are pointed to and described by word[] structures.  The array is
5867  * big enough to accomodate two lines' worth of words, assuming each word
5868  * takes at least two characters (including separator).  wordbase and
5869  * wordlimit are the bounds of the array.  wordfirst remembers the first
5870  * word in the array not yet printed.  wordat is the word being worked on
5871  * after wordnext is advanced (and maybe wrapped around).  New elements
5872  * are "allocated" using wordnext, a pointer that is wrapped around as
5873  * needed.
5874  *
5875  * inlinenum and incolumn track the current input line and column per
5876  * paragraph.  outlinenum tracks the next line to print.  All are base 1,
5877  * but inlinenum is preset to zero at the start of each paragraph.
5878  *
5879  * pendchars tracks the number of dumpable characters accrued so far, to
5880  * trigger dumping.  indent1 and indent2 remember the indentations seen
5881  * for the first two lines of each paragraph.
5882  */
5883
5884 /************************************************************************
5885  * F I L L
5886  *
5887  * Parse an input line (in_line to inlinelim) into words and trigger
5888  * FillWord() as needed to finish each word, which in turn can call
5889  * Dump() to dump output lines.  This routine sacrifices simplicity and
5890  * clarity for efficiency.  It uses shared global word data except
5891  * outlinenum and pendchars.
5892  */
5893
5894 static void
5895 Fill (FormatData *data,
5896       wint_t    *in_line,               /* start of input line  */
5897       register wint_t   *inlinelim)     /* end of line + 1      */
5898 {
5899         register wint_t *incp;          /* place in in_line     */
5900         register wint_t ch;             /* current working char */
5901         int     haveword = False;       /* hit word in in_line? */
5902         register int    inword   = False;       /* currently in a word? */
5903 /*
5904  * SCAN INPUT LINE:
5905  */
5906
5907         data->inlinenum++;
5908         data->incolumn = 1;                             /* starting a line */
5909
5910         for (incp = in_line; incp < inlinelim; incp++)
5911         {
5912           ch = *incp;
5913
5914 /*
5915  * AT WHITE SPACE; FINISH PREVIOUS WORD if any, then skip white space:
5916  */
5917
5918           if (iswspace(ch))
5919           {
5920             if (inword)         /* was skipping a word */
5921             {
5922                 inword = False;
5923                 FillWord(data);
5924             }
5925
5926             data->incolumn += ((ch != L'\t') && (iswblank(ch))) ?
5927                                 1 : data->tabsize - ((data->incolumn - 1) % data->tabsize);
5928           }
5929
5930 /*
5931  * AT PART OF WORD; START NEW ONE IF NEEDED:
5932  */
5933
5934           else if (iswprint (ch))
5935           {
5936             if (! inword)               /* start new word */
5937             {
5938                 inword = True;
5939
5940                 if (data->wordcp > data->wordcpwrap)/* past wrap point   */
5941                   data->wordcp = data->wordbuf;/* wraparound buffer */
5942
5943                 data->wordat = data->wordnext;
5944                 WORDNEXT (data,data->wordnext);
5945
5946                 data->wordat->cp = data->wordcp;        /* note start of word */
5947                 data->wordat->inlinenum = data->inlinenum;      /* note input line    */
5948                 data->wordat->incolumn  = data->incolumn;       /* note input column  */
5949                 data->wordat->wclen = 0;
5950
5951                 if (! haveword)
5952                 {
5953                   haveword = True;
5954         
5955                   switch (data->inlinenum)/* note indentations */
5956                   {
5957                     case 1:     
5958                         data->indent1 = data->incolumn - 1; 
5959                         break;
5960                     case 2:     
5961                         data->indent2 = data->incolumn - 1; 
5962                         break;
5963                   }
5964                 }
5965             }
5966
5967 /*
5968  * SAVE ONE CHAR OF WORD:
5969  */
5970             *(data->wordcp++) = ch;
5971             {
5972                 int n = wcwidth(ch);
5973
5974                 if (n > 0) 
5975                 { /* == 0 for a null char */
5976                   data->incolumn += n; 
5977                   data->wordat->wclen++;
5978                 }
5979             }
5980
5981           } /* else */
5982
5983 /* else skip other chars by doing nothing */
5984
5985         } /* for */
5986
5987 /*
5988  * END OF LINE; HANDLE BLANK LINE, OR FINISH WORD AND AUTOMARGIN:
5989  */
5990
5991         if (! haveword)                 /* no text on line */
5992         {
5993           data->inlinenum--;                    /* don't count empty lines */
5994           Dump (data, True);            /* force end paragraph */
5995           fputc ('\n', data->pAdj->outfp);      /* put this empty line */
5996           data->inlinenum = 0;          /* start new paragraph */
5997         }
5998         else                            /* have text on line */
5999         {
6000           if (inword)                   /* line ends in word */
6001                 FillWord(data);
6002           if (data->pendchars > data->fillmargin) 
6003           {                             /* time to dump line    */
6004                 Dump (data, False);     /* not end of paragraph */
6005           }
6006
6007           if (data->m0flag && (data->inlinenum == 1)) /* need to note right margin */
6008                 data->fillmargin = data->wordat->incolumn + data->wordat->length - 1;
6009         }
6010 } /* Fill */
6011
6012
6013 /************************************************************************
6014  * F I L L   W O R D
6015  *
6016  * Save values for the word just finished and dump the output line if
6017  * needed.  Uses shared global word values, but does not touch outlinenum,
6018  * and only increments pendchars.
6019  *
6020  * Trailing blanks (1 or 2) needed after a word are figured here.
6021  * wordlen is the total length (nonzero) and wordcp points to the char
6022  * past the end of the word.  Two blanks are needed after words ending in:
6023  *
6024  *      <terminal>[<quote>][<close>]
6025  *
6026  * where <terminal> is any of   . : ? !
6027  *       <quote>    is any of   ' "
6028  *       <close>    is any of   ) ] }
6029  *
6030  * For efficiency, this routine avoids calling others to do character
6031  * matching; it does them in line.
6032  */
6033
6034 static void
6035 FillWord (FormatData *data)
6036 {
6037   int   wordlen;                /* length of word to fill */
6038   int   blanks = 1;             /* trailing blanks needed */
6039   register wint_t       ch1, ch2, ch3;          /* last chars of word     */
6040
6041   data->wordat->length = (data->incolumn - data->wordat->incolumn);
6042   wordlen = data->wordat->wclen;
6043
6044   /*
6045    * CHECK FOR SPECIAL END OF WORD:
6046    */
6047
6048   ch3 = data->wordcp [-1];
6049
6050   if ((ch3 == L'.') || (ch3 == L':') || (ch3 == L'?') || (ch3 ==L'!'))
6051   {
6052         blanks = 2;                     /* <terminal> */
6053   }
6054
6055   else if (wordlen >= 2)
6056   {
6057     ch2 = data->wordcp [-2];
6058
6059     if( ((ch2 == L'.')  || (ch2 == L':') || (ch2 ==L'?') || (ch2 == L'!')) &&
6060         ((ch3 == L'\'') || (ch3 == L'"') || (ch3 ==L')')  || (ch3 == L']') 
6061          || (ch3 == L'}'))
6062       )
6063     {
6064       blanks = 2;               /* <terminal><quote or close> */
6065     }
6066     else if (wordlen >= 3)
6067     {
6068       ch1 = data->wordcp [-3];
6069
6070       if( ((ch1 == L'.')  || (ch1 == L':') || (ch1 == L'?') || (ch1 == L'!'))
6071           && ((ch2 == L'\'') || (ch2 == L'"'))
6072           && ((ch3 == L')')  || (ch3 == L']') || (ch3 == L'}')) )
6073       {
6074         blanks = 2;             /* <terminal><quote><close> */
6075       }
6076     }
6077
6078   } /* else */
6079
6080 /*
6081  * SAVE VALUES
6082  */
6083
6084     data->pendchars += wordlen + (data->wordat->blanks = blanks);
6085
6086 } /* FillWord */
6087
6088
6089 /************************************************************************
6090  * D U M P
6091  *
6092  * Print output line(s), with all necessary indentation and formatting,
6093  * if required (at end of paragraph) or if permissible.  If required,
6094  * indent1 is used if indent2 is not set yet (not on second line of
6095  * input).  Otherwise, if not at end of paragraph, dumping is only
6096  * permissible after beginning the second input line, so fillmargin and
6097  * indent2 are known, so tagged paragraphs are done right.
6098  *
6099  * Whenever dumping, all "full" lines are dumped, which means more than
6100  * just one may be printed per call.  jflag or rflag formatting is
6101  * applied to all lines, except that jflag is ignored for the last line
6102  * of each paragraph.
6103  *
6104  * Uses shared global word data, but does not touch inlinenum, incolumn,
6105  * indent1, or indent2.  
6106  */
6107
6108 static void
6109 Dump (FormatData *data, 
6110       int endpara)              /* end of paragraph? */
6111 {
6112   int   haveindent2 = (data->inlinenum >= 2);   /* indent2 known?       */
6113   int   startpara;                      /* start of paragraph?  */
6114   int   normal;                         /* non-tagged line?     */
6115   WORD  *wordpast = data->wordfirst;            /* past last to dump    */
6116   register int  wordlen;                /* length of one word   */
6117   int   indent;                         /* local value          */
6118   register int  outneed;                /* chars need to dump   */
6119   int   outchars;                       /* chars found to dump  */
6120
6121 /*
6122  * IF DUMPING NEEDED, DUMP LINES TILL DONE:
6123  */
6124
6125    if (! (endpara || haveindent2))                      /* not time to dump */
6126       return;
6127
6128    while (    (data->pendchars > data->fillmargin)      /* line is full */
6129            || (endpara && (data->wordfirst != data->wordnext)) )        /* more to dump */
6130    {
6131       startpara = (data->outlinenum < 2);
6132       indent    = (startpara || (! haveindent2)) ? data->indent1 : data->indent2;
6133
6134 /*
6135  * CHECK FOR TAGGED PARAGRAPH if needed:
6136  */
6137
6138       normal = True;                            /* default == no tag */
6139
6140       if (startpara && haveindent2 && (data->indent1 < data->indent2))
6141       {
6142         int     incol2 = data->indent2 + 1;     /* column needed */
6143
6144         while (   (wordpast != data->wordnext)  /* more words */
6145                && (wordpast->inlinenum == 1))   /* from line 1 */
6146         {
6147            if (wordpast->incolumn == incol2)    /* bingo */
6148            {
6149               normal = False;
6150               break;
6151            }
6152            WORDNEXT (data,wordpast);
6153         }
6154
6155         if (normal)
6156           wordpast = data->wordfirst;           /* reset value */
6157
6158 /*
6159  * PRINT TAG PART OF TAGGED PARAGRAPH:
6160  */
6161
6162         else
6163         {
6164           WORD *wordat = data->wordfirst;       /* local value */
6165
6166           while (wordat != wordpast)    /* decrement pendchars */
6167           {
6168              data->pendchars -= wordat->length + wordat->blanks;
6169              WORDNEXT (data,wordat);
6170           }
6171                                 
6172           PrintIndent (data, indent);
6173           PrintTag  (data, wordpast);   /* preceding words   */
6174           data->wordfirst = wordpast;   /* do rest of line   */
6175           indent    = data->indent2;    /* as if second line */
6176         }
6177       } /* if */
6178
6179  /*
6180   * FIND WORDS WHICH FIT ON [REST OF] LINE:
6181   */
6182
6183       if (indent >= data->fillmargin)           /* don't over indent */
6184         indent  = data->fillmargin - 1;
6185
6186       outneed   = data->fillmargin - indent;    /* always greater than zero */
6187       outchars  = 0;
6188       wordlen   = wordpast->length;
6189
6190       do {                              /* always consume one */
6191            outchars += wordlen + wordpast->blanks;
6192            WORDNEXT (data,wordpast);
6193       } while (    (wordpast != data->wordnext) /* not last word */
6194                 && (outchars + (wordlen = wordpast->length) <= outneed)
6195                 );
6196       /* next will fit */
6197
6198
6199       /*
6200       ** BEKINSOKU/EKINSOKU PROCESSING
6201       */
6202       if( EkinBekinProc(data, &wordpast) )
6203         postEkinBekinProc(data, &outchars,wordpast);
6204       data->pendchars -= outchars;              /* pendchars to consume */
6205
6206       /* from now on, don't include trailing blanks on last word */
6207       outchars -= (WORDPREV (data,wordpast) -> blanks);
6208
6209       /* now wordfirst and wordpast specify the words to dump */
6210 /*
6211  * PRINT INDENTATION AND PREPARE JUSTIFICATION:
6212  */
6213
6214       if (data->pAdj->rflag)                    /* right-justify only */
6215       {
6216         if (normal)             /* nothing printed yet */
6217           PrintIndent (data, data->fillmargin - outchars);
6218         else    /* indent + tag printed */
6219         {
6220         int blanks = data->fillmargin - outchars - indent;
6221
6222         while (blanks-- > 0)            /* can't use PrintIndent()*/
6223           putwc(data->Blank, data->pAdj->outfp);
6224         }
6225       }
6226       else
6227       {
6228         if (normal)                     /* not already done */
6229           PrintIndent (data, indent);
6230
6231         if (data->pAdj->jflag && ! (endpara && (wordpast == data->wordnext)))
6232           Justify (data, outneed - outchars, wordpast);
6233       }
6234
6235 /*
6236  * PRINT REST OF LINE:
6237  */
6238
6239       PrintWords (data, wordpast);
6240       putwc('\n', data->pAdj->outfp);
6241       data->wordfirst = wordpast;
6242       data->outlinenum++;                               /* affects startpara */
6243
6244    } /* while */
6245
6246    if (endpara)
6247      data->outlinenum = 1;
6248
6249 } /* Dump */
6250
6251
6252 /************************************************************************
6253  * P R I N T   I N D E N T
6254  *
6255  * Print line indentation (if > 0), optionally using tabs where possible.
6256  * Does not print a newline.
6257  */
6258
6259 static void
6260 PrintIndent (FormatData *data,
6261              int        indent)         /* leading indentation */
6262 {
6263    if (indent > 0)              /* indentation needed */
6264    {
6265       if (! data->pAdj->bflag)  /* unexpand leading blanks */
6266       {
6267          while (indent >= data->tabsize)
6268          {
6269            putc ('\t', data->pAdj->outfp);
6270            indent -= data->tabsize;
6271          }
6272       }
6273    fprintf (data->pAdj->outfp, "%*s", indent, "");/*[remaining] blanks */
6274    }
6275 } /* PrintIndent */
6276
6277
6278 /************************************************************************
6279  * P R I N T   T A G
6280  *
6281  * Print paragraph tag words from word[] array beginning with (global)
6282  * wordfirst and ending before (parameter) wordpast, using input column
6283  * positions in each word's data.  Assumes indentation of indent1 was
6284  * already printed on the line.  Assumes *wordpast is the next word on
6285  * the line and its column position is valid, and appends spaces up to
6286  * the start of that word.   Doesn't print a newline.
6287  *
6288  * Line indentation must already be done, as this routine doesn't know
6289  * how to print leading tabs, only blanks.
6290  */
6291
6292 static void
6293 PrintTag (FormatData *data, 
6294           WORD  *wordpast)              /* past last to print */
6295 {
6296    register WORD        *wordat = data->wordfirst;      /* local value    */
6297    register int outcol = data->indent1 + 1;     /* next column    */
6298    int  wordcol;                /* desired column */
6299    register wint_t      *wordcp;                /* place in word  */
6300    wint_t       *wordcplim;             /* limit of word  */
6301
6302    while (True)                         /* till break */
6303    {
6304      wordcol = wordat->incolumn;
6305
6306         while (outcol < wordcol)/* space over to word */
6307         {
6308            putwc(data->Blank, data->pAdj->outfp);
6309            outcol++;
6310         }
6311
6312         if (wordat == wordpast)         /* past last word */
6313            break;                       /* quit the loop  */
6314
6315         wordcp = wordat->cp;
6316
6317         wordcplim = wordcp + wordat->wclen;
6318
6319         while (wordcp < wordcplim)              /* print word */
6320            putwc(*wordcp++, data->pAdj->outfp);
6321
6322         outcol += wordat->length;
6323         WORDNEXT (data,wordat);
6324    }
6325 } /* PrintTag */
6326
6327
6328 /************************************************************************
6329  * P R I N T   W O R D S
6330  *
6331  * Print words from word[] array beginning with (global) wordfirst and
6332  * ending before (parameter) wordpast, using word sizes and trailing
6333  * blanks (except for last word on line).  Doesn't print a newline.
6334  */
6335
6336 static void
6337 PrintWords (FormatData *data,
6338             WORD       *wordpast)               /* past last to print */
6339 {
6340    register WORD        *wordat = data->wordfirst;      /* local value   */
6341    register wint_t      *wordcp;                /* place in word */
6342    wint_t       *wordcplim;             /* limit of word */
6343    register int blanks;                 /* after a word  */
6344
6345    while (True)                         /* till break */
6346    {
6347      wordcp    = wordat->cp;
6348      wordcplim = wordcp + wordat->wclen;
6349      blanks    = wordat->blanks;        /* set before do WORDNEXT() */
6350
6351      while (wordcp < wordcplim)         /* print word */
6352      {
6353         putwc(*wordcp++, data->pAdj->outfp);
6354      }
6355
6356      wordat->wclen = 0;
6357      WORDNEXT (data,wordat);
6358
6359      if (wordat == wordpast)            /* just did last word */
6360         break;
6361
6362      while (blanks-- > 0)               /* print trailing blanks */
6363         putwc(data->Blank, data->pAdj->outfp);
6364    }
6365
6366 } /* PrintWords */
6367
6368
6369 /************************************************************************
6370  * J U S T I F Y
6371  *
6372  * Do left/right justification of [part of] a line in the word[] array
6373  * beginning with (global) wordfirst and ending before (parameter)
6374  * wordpast, by figuring where to insert blanks.
6375  *
6376  * Gives each word (except the last on the line) a score based on its
6377  * size plus the size of the next word.  Quicksorts word indices into
6378  * order of current trailing blanks (least first), then score (most
6379  * first).  Cycles through this list adding trailing blanks to word[]
6380  * entries such that words will space out nicely when printed.
6381  */
6382
6383 static void
6384 Justify (FormatData *data, 
6385          register int blanks,                   /* blanks to insert   */
6386          WORD   *wordpast)              /* past last to print */
6387 {
6388    register WORD        *wordat;                /* local value          */
6389    register int sortat;                 /* place in sort[]      */
6390    register int wordlen;                /* size of this word    */
6391    register int nextlen;                /* size of next word    */
6392    int  level;                  /* current blanks level */
6393
6394    WORD *sort [WORDMAX];        /* sorted pointers */
6395    int  words;                  /* words in sort[] */
6396
6397    wordat = WORDPREV (data,wordpast);           /* last word on line */
6398
6399    if ((blanks < 1) || (wordat == data->wordfirst))
6400       return;                           /* can't do anything */
6401
6402    /*
6403  * COMPUTE SCORES FOR WORDS AND SORT INDICES:
6404  *
6405  * March backwards through the words on line, starting with next to last.
6406  */
6407
6408    words        = 0;
6409    nextlen      = wordat->length;               /* length of last word */
6410
6411    do {                                 /* always at least one */
6412       wordat  = WORDPREV (data,wordat);
6413       wordlen = wordat->length;
6414       wordat->score = wordlen + nextlen;        /* this plus next */
6415       nextlen = wordlen;
6416       sort [words++] = wordat;          /* prepare for sorting */
6417    }    while (wordat != data->wordfirst);
6418
6419    qsort ((wint_t *) sort, words, sizeof (WORD *), CompareWords);
6420
6421 /*
6422  * ADD TRAILING BLANKS TO PAD OUT WORDS:
6423  *
6424  * Each pass through the sorted list adds one trailing blank to each word
6425  * not already past the current level.  Thus all one-blank words are brought
6426  * up to two; then all twos up to three; etc.
6427  */
6428
6429    level = 0;
6430
6431    while (True)                                 /* till return */
6432    {
6433       level++;
6434
6435       for (sortat = 0; sortat < words; sortat++)
6436       {
6437         wordat = sort [sortat];
6438         if (wordat->blanks > level)             /* end of this level */
6439           break;                                /* start next level  */
6440
6441         wordat->blanks++;
6442         if (--blanks <= 0)                      /* no more needed */
6443           return;
6444       }
6445    }
6446
6447 } /* Justify */
6448
6449
6450 /************************************************************************
6451  * C O M P A R E   W O R D S
6452  *
6453  * Compare two word[] entries based on pointers to (WORD *), as called
6454  * from qsort(3).  Tell which entry has priority for receiving inserted
6455  * blanks (least trailing blanks first, then highest scores), by returning
6456  * -1 for the first entry, +1 for second entry, or 0 if no difference.
6457  * (-1 literally means first entry < second entry, so it sorts first.)
6458  */
6459
6460 static int
6461 CompareWords (const void *p1, const void *p2)
6462 {
6463    WORD *word1  = *((WORD **)p1);       /* (WORD *) pointers */
6464    WORD *word2  = *((WORD **)p2);
6465    int  blanks1 = word1->blanks;        /* trailing blanks */
6466    int  blanks2 = word2->blanks;
6467
6468    if (blanks1 == blanks2)              /* commonest case */
6469    {
6470       int       score1 = word1->score;  /* word scores */
6471       int       score2 = word2->score;
6472
6473       if (score1 > score2) return (-1); /* word1 has priority */
6474         else if (score1 < score2)       return ( 1);
6475         else    return (0);
6476    }
6477    else if (blanks1 < blanks2)  return (-1);    /* word1 has priority */
6478      else return ( 1);
6479
6480 } /* CompareWords */
6481
6482
6483 /*
6484 ** BKINSOKU and EKINSOKU processing for Japanese text
6485 **
6486 ** The function scans the wordlist that are ready for printing
6487 ** and updates the "wordpast" pointer based on the rules of
6488 ** BKINSOKU and EKINSOKU characters.
6489 **
6490 ** The code does not split a line just after a "gyomatu kinsoku" 
6491 ** character and just before a "gyoto kinsoku" character.
6492 ** "Gyomatsu kinsoku" (e-kinsoku) are characters which cannot be 
6493 ** placed at the end of a line.  "Gyoto kinsoku" (b-kinsoku) are
6494 ** characters which can not be placed at the top of a line.
6495 **
6496 ** Global variables used:
6497 **      wordfirst       - beginning the word list (buffer of pending lines)
6498 **      wordnext        - next available spot in the pending buffer (i.e. 
6499 **                        end of the buffer).
6500 **
6501 ** Global variables modified:
6502 **      None.
6503 **      
6504 ** Return Values:
6505 **      0 - No Post processing is required.
6506 **      1 - Post processing is required
6507 */
6508
6509 #if !(defined(sun) && (_XOPEN_VERSION==3)) 
6510 static int
6511 EkinBekinProc(FormatData *data, 
6512               WORD      **wordpast)
6513 {
6514    WORD *curword,*compword,*prevword;
6515    int  ekinflag = False, margin;
6516
6517    /*
6518     * curword points to the last word of the first line.
6519     * compword points to the first word of the next line or to the next
6520     * available spot if there is no next line.
6521     */
6522    compword = *wordpast;
6523    curword = WORDPREV(data,compword);
6524
6525    /*
6526     * If the length of the current word is > fillmargin
6527     * or it is the only word then return.
6528     */
6529    if (curword->length > data->fillmargin || (curword == data->wordfirst))
6530         return False;
6531
6532    /*
6533     * EKINSOKU processing
6534     * If this character set supports ekinclass (can't end a line) char,
6535     * start at the end of the line and search back until 
6536     * 1) we find a non-ekinsoku character, or 
6537     * 2) come to the beginning of the pending buffer.
6538     */
6539    if (ekinclass) 
6540    {
6541       while (isekinsoku(*(curword->cp+curword->wclen-1))) 
6542       {
6543         ekinflag = True;
6544         if (curword == data->wordfirst) /* Boundary Condition */
6545           break;
6546         curword = WORDPREV(data,curword);
6547       }
6548
6549       /*
6550        * Post EKIN processing (i.e. we found an ekinsoku character in 
6551        * the line before finding an non-ekinsoku).
6552        */
6553       if (ekinflag) {
6554
6555          if (curword != data->wordfirst) {
6556             /* 
6557              * We found a non-ekinsoku after we found the ekinsoku.
6558              * Move the end of line to just after the non-ekinsoku.
6559              */
6560             WORDNEXT(data,curword);
6561             *wordpast = curword;
6562             return True;
6563          }
6564          else { /* Boundary condition */
6565             /*
6566              * Reached the beginning of the buffer without finding a
6567              * non-ekinsoku.  If the last word in the line can begin
6568              * a line (i.e. non-bkinsoku) make it the first word of 
6569              * the next line.
6570              */
6571             curword = WORDPREV(data,compword);
6572             if (!isbekinsoku(*curword->cp)) {
6573                *wordpast = curword;
6574                return True;
6575             }
6576             return False;
6577          }
6578       } 
6579    } 
6580
6581    /* 
6582     * If we reached this point then:
6583     * 1) the character set does not support ekinclass characters, or
6584     * 2) the last character in the line is non-ekinsoku.
6585     * Now, need to see if we can begin the next line with the first 
6586     * character on that line.
6587     */
6588
6589    /*
6590     * BEKINSOKU processing
6591     * If this character set supports bekinclass (can't begin a line) char,
6592     * search forward from the begining of the next line (curword) to the
6593     * end of the buffer (wordnext) until:
6594     * 1) A non-bekinsoku word is found,
6595     * 2) if the line limit exceeds the set value, or
6596     * 3) we reach the end of the buffer.
6597     */
6598
6599    if (bekinclass) 
6600    {
6601       /*
6602        * compword points to the first word of the next line.
6603        */
6604       curword = compword;
6605       margin = data->indent2;
6606
6607       while (curword != data->wordnext) 
6608       {
6609          if (!isbekinsoku(*curword->cp))
6610            break;
6611          margin += (curword->length + curword->blanks);
6612          if (margin >= data->fillmargin)
6613             return False;
6614          WORDNEXT(data,curword);
6615       }
6616
6617       if (curword != data->wordnext && curword != compword) 
6618       {
6619         /* 
6620          * The first word of the second line is bekinsoku so search
6621          * backwards from end of first line until we are:
6622          * 1) not at the first word of the buffer, and
6623          * 2) not in between either an ekinsoku or bekinsoku character.
6624          */ 
6625
6626         /*
6627          * compword points to the first word of the next line.
6628          * curword points to the last word of the first line.
6629          */
6630         curword = WORDPREV(data,compword);
6631         prevword = WORDPREV(data,curword);
6632         while ( (curword != data->wordfirst) && 
6633                 (isbekinsoku(*curword->cp) || 
6634                  isekinsoku(*(prevword->cp+prevword->wclen-1)))
6635               ) 
6636         {
6637            margin += curword->length + curword->blanks;
6638            if (margin >= data->fillmargin)
6639              return False;
6640            curword = prevword;
6641            prevword = WORDPREV(data,curword);
6642         }
6643
6644         if (curword != data->wordfirst) {
6645           /* 
6646            * Did not reach the beginning of the buffer so we are between
6647            * two non-ekinsoku & non-bekinsoku characters.  Move the end
6648            * of the first line here.
6649            */
6650
6651           *wordpast = curword;
6652           return True;
6653         }
6654
6655       }
6656       return False;
6657    }
6658
6659    return False;
6660
6661 } /* end EkinBekinProc */
6662
6663 #else
6664
6665 static int
6666 EkinBekinProc(FormatData *data, 
6667               WORD      **wordpast)
6668 {
6669    WORD *curword,*compword,*prevword,*nextword;
6670    int  margin = data->indent2;
6671
6672    /*
6673     * prevword points to the last word of the first line.
6674     * compword & curword point to the first word of the next line or
6675     * to the next available spot in the buffer if there is no next line.
6676     */
6677    compword = *wordpast;
6678    curword = compword;
6679    prevword = WORDPREV(data,curword);
6680
6681    /*
6682     * If the length of the previous word is > fillmargin
6683     * or it is the only word in the line then return.
6684     * wordfirst points to the beginning of the buffer of pending lines.
6685     */
6686    if (prevword->length > data->fillmargin || (prevword == data->wordfirst))
6687         return False;
6688
6689    /*
6690     * Starting at the beginning of the next line, search backwards
6691     * until:
6692     * 1) we find two words we can split between lines, or
6693     * 2) we reach the beginning of the buffer.
6694     * 
6695     * If there is no next line start with the last two words of this line
6696     * (wordnext points to the next available space in the buffer (i.e
6697     * the end of the buffer).
6698     */
6699
6700     if (curword == data->wordnext) {
6701       curword = prevword;
6702       prevword = WORDPREV(data,curword);
6703     }
6704
6705     while ( (curword != data->wordfirst) && 
6706             (wdbindf(*(prevword->cp+prevword->wclen-1), *curword->cp, 1) >4)
6707           ) 
6708     {
6709       curword = prevword;
6710       prevword = WORDPREV(data,curword);
6711     }
6712
6713     if (curword != data->wordfirst) {
6714
6715       /* 
6716        * Did not reach the beginning of the buffer so we are between
6717        * two non-ekinsoku & non-bekinsoku characters.  Move the end
6718        * of the first line here.
6719        */
6720
6721       *wordpast = curword;
6722       return True;
6723
6724     } 
6725     else {
6726
6727       /* 
6728        * Reached the beginning of the buffer so search forward
6729        * from the beginning of the second line until:
6730        * 1) we find two words we can split between lines, 
6731        * 2) we reach the end of the buffer, or
6732        * 3) the line becomes too long.
6733        * 
6734        * If there is no next line then just exit.
6735        */
6736
6737       /*
6738        * compword points to the first word of the next line or to the
6739        *   next available spot in the buffer if there is no next line.
6740        * nextword points to the second word of the next line.
6741        * wordnext points to the next available space in the buffer (i.e
6742        * the end of the buffer)
6743        */
6744       curword = compword;
6745       nextword = compword;
6746       WORDNEXT(data,nextword);
6747
6748       if (curword == data->wordnext)
6749         return False;
6750
6751       while (nextword != data->wordnext) 
6752       {
6753
6754          if (wdbindf(*(curword->cp+curword->wclen-1), *nextword->cp, 1) < 5)
6755            break;
6756          margin += (curword->length + curword->blanks);
6757          if (margin >= data->fillmargin)
6758             return False;
6759          curword = nextword;
6760          WORDNEXT(data,nextword);
6761       }
6762
6763       if (nextword != data->wordnext) {
6764
6765         /* 
6766          * Did not reach the end of the buffer so we are between
6767          * two non-ekinsoku & non-bekinsoku characters.  Move the end
6768          * of the first line here.
6769          */
6770         *wordpast = nextword;
6771         return True;
6772       }
6773
6774       return False;
6775
6776     } 
6777
6778 } /* end EkinBekinProc */
6779
6780 #endif /* not sun */
6781
6782 static void
6783 postEkinBekinProc(FormatData *data, 
6784                   int   *poutchars,
6785                   WORD  *wordpast)
6786 {
6787    WORD *curword;
6788    int  colvalue,curlineno;
6789
6790 /*
6791  * Recompute the value of *poutchars
6792  */
6793
6794    (*poutchars) = 0;
6795
6796    curword = data->wordfirst;
6797    while (curword != wordpast) 
6798    {
6799         (*poutchars) +=  curword->length + curword->blanks;
6800         WORDNEXT(data,curword);
6801    }
6802
6803    /*
6804    ** Adjust the word parameters -
6805    ** inlinenum,incolumn of all the words
6806    ** from 'curword' till 'wordnext'
6807    */
6808
6809    curword = wordpast;
6810    curlineno = curword->inlinenum+1;
6811    colvalue = data->indent2;
6812    while (curword != data->wordnext) 
6813    {
6814      curword->inlinenum = curlineno;
6815      curword->incolumn = colvalue;
6816      colvalue += curword->length + curword->blanks;
6817      if (colvalue > data->fillmargin) 
6818      {
6819        colvalue = data->indent2;
6820        curlineno++;
6821      }
6822      WORDNEXT(data,curword);
6823    }
6824    data->incolumn = colvalue;
6825    data->inlinenum = curlineno;
6826 }
6827
6828 #ifdef DEBUG
6829
6830 static
6831 prnword(pword)
6832 WORD    *pword;
6833 {
6834    int i = 0;
6835
6836    if (pword == NULL)
6837      return;
6838    for (i=0; i < pword->wclen; i++)
6839      fprintf(stderr,(const char *)"%c",(char)*(pword->cp+i));
6840    fprintf(stderr,"Word Length :%d\n",pword->wclen);
6841 }
6842
6843 #endif /* DEBUG */
6844
6845 /* ARGSUSED */
6846 static void
6847 AdjustParaCB(
6848         Widget w,
6849         caddr_t client_data,
6850         caddr_t call_data )
6851 {
6852
6853     DtEditorFormat( (Widget)client_data, (DtEditorFormatSettings *)NULL,
6854                     DtEDITOR_FORMAT_PARAGRAPH );
6855
6856 } /* AdjustParaCB */
6857
6858 /* ARGSUSED */
6859 static void
6860 AdjustAllCB(
6861         Widget w,
6862         caddr_t client_data,
6863         caddr_t call_data )
6864 {
6865
6866     DtEditorFormat( (Widget)client_data, (DtEditorFormatSettings *)NULL,
6867                     DtEDITOR_FORMAT_ALL );
6868
6869 } /* AdjustAllCB */
6870
6871
6872 /*********
6873  *
6874  * DoAdjust - given left & right margin values & an alignment style, formats
6875  *            the text from one specified text position to another.
6876  *
6877  *            Returns: 
6878  *              DtEDITOR_NO_ERRORS    if the text was formatted successfully.
6879  *              DtEDITOR_ILLEGAL_SIZE if the left & right margins don't make 
6880  *                                    sense.
6881  *              DtEDITOR_NO_TMP_FILE  if the 2 temporary files cannot be 
6882  *                                    created.
6883  *              DtEDITOR_INVALID_TYPE if specified alignment is
6884  *                                    unrecognized
6885  *
6886  */
6887 static DtEditorErrorCode
6888 DoAdjust(
6889         DtEditorWidget  editor,
6890         int             leftMargin,
6891         int             rightMargin,
6892         unsigned int    alignment,
6893         XmTextPosition  start,
6894         XmTextPosition  end)
6895 {
6896     char tempName1[L_tmpnam], tempName2[L_tmpnam];
6897     DtEditorErrorCode returnVal;
6898     AdjRec adjRec;
6899
6900     /* 
6901      * Check that valid margin values were passed in
6902      */
6903     if( leftMargin >= 0 && 
6904         rightMargin > 0 &&
6905         rightMargin < 1025 &&
6906         leftMargin <= rightMargin ) 
6907     { 
6908        /* 
6909         * Set up 
6910         */
6911        _DtTurnOnHourGlass(M_topLevelShell(editor));
6912        if (M_format_dialog(editor) != (Widget)NULL)
6913          _DtTurnOnHourGlass(M_format_dialog(editor));
6914
6915        memset(&adjRec, 0, sizeof(AdjRec));
6916
6917       /* The adjust text formatting code works with a data 
6918          representation to the screen of 1 byte per column for
6919          multibyte environment.  The Motif text Widget has a data
6920          representation of 2 bytes per column in multibyte, so we must
6921          fool the adjust code into thinking the margins are twice the
6922          size in a multibyte environment.
6923       */
6924   
6925        if (MB_CUR_MAX > 1)
6926        {
6927          rightMargin = rightMargin * 2;
6928          leftMargin = leftMargin * 2;
6929        }
6930
6931        switch (alignment)
6932        {
6933          case DtEDITOR_ALIGN_CENTER:
6934          {
6935            adjRec.cflag = 1;
6936            adjRec.margin = (rightMargin + leftMargin) / 2;
6937            break;
6938          }
6939
6940          case DtEDITOR_ALIGN_JUSTIFY:
6941          {
6942            adjRec.jflag = 1;
6943            adjRec.margin = rightMargin;
6944            break;
6945          }
6946
6947          case DtEDITOR_ALIGN_RIGHT:
6948          {
6949            adjRec.rflag = 1;
6950            adjRec.margin = rightMargin;
6951            break;
6952          }
6953
6954          case DtEDITOR_ALIGN_LEFT:
6955          {
6956            adjRec.margin = rightMargin;
6957            break;
6958          }
6959
6960          default:
6961          {
6962            returnVal = DtEDITOR_INVALID_TYPE;
6963          }
6964   
6965        } /* end switch */
6966
6967        /*
6968         * Turn off converting leading spaces into tabs if we are 
6969         * working in a multi-byte locale.  This is necessary
6970         * because a tab may not equal (be as wide as) 8 spaces in 
6971         * a multi-byte locale.
6972         */
6973        adjRec.tabsize = 8;
6974
6975        if (MB_CUR_MAX > 1)
6976          adjRec.bflag = True;
6977        else
6978          adjRec.bflag = False;
6979
6980
6981        /*
6982         * Create the two temp files
6983         */
6984        (void)tmpnam(tempName1);
6985        (void)tmpnam(tempName2);
6986        if ((adjRec.infp = fopen(tempName1, "w+")) != (FILE *)NULL) {
6987
6988          /* 
6989           * Successfully opened the first temporary file 
6990           */
6991
6992          if((adjRec.outfp = fopen(tempName2, "w")) != (FILE *)NULL) {
6993
6994             /* 
6995              * Successfully opened the second temporary file, so do the
6996              * formatting.
6997              */ 
6998             returnVal = DtEDITOR_NO_ERRORS;
6999
7000             fixLeftMarginAndNewlines( editor, adjRec.infp, leftMargin, 
7001                                       rightMargin, (int)start, (int)end );
7002             fflush(adjRec.infp);
7003             rewind(adjRec.infp);
7004
7005             FormatText(&adjRec);
7006
7007             fclose(adjRec.infp);
7008             unlink(tempName1);
7009
7010             fclose(adjRec.outfp);
7011             returnVal =
7012               DtEditorReplaceFromFile( (Widget)editor, start, end, tempName2 );
7013             unlink(tempName2);
7014
7015          } 
7016          else {
7017            /*
7018             * Could not open second temporary file, so clean up first one
7019             */
7020            fclose(adjRec.infp);
7021            unlink(tempName1);
7022            returnVal = DtEDITOR_NO_TMP_FILE;
7023          }
7024
7025        } /* end creating temporary files */ 
7026        else
7027          returnVal = DtEDITOR_NO_TMP_FILE;
7028
7029        /*
7030         * Clean up
7031         */
7032        _DtTurnOffHourGlass(M_topLevelShell(editor));
7033        if (M_format_dialog(editor) != (Widget)NULL)
7034          _DtTurnOffHourGlass(M_format_dialog(editor));
7035
7036     } /* end check for valid margins */ 
7037     else
7038       returnVal = DtEDITOR_ILLEGAL_SIZE;
7039
7040     return (returnVal);
7041 }
7042
7043 /* ARGSUSED */
7044 static void
7045 AdjustCloseCB(
7046         Widget w,
7047         caddr_t client_data,
7048         caddr_t call_data )
7049 {
7050     DtEditorWidget editor = (DtEditorWidget )client_data;
7051     XtUnmanageChild (M_format_dialog(editor));
7052 }
7053
7054 /* ARGSUSED */
7055 static int 
7056 ComputeRightMargin(
7057         DtEditorWidget editor)
7058 {
7059     Dimension text_width, highlight_thickness, shadow_thickness,
7060                margin_width;
7061     int rightMargin;
7062     Arg al[5];             /* arg list */
7063     register    int ac;    /* arg count */
7064
7065     ac=0;
7066     XtSetArg(al[ac], XmNwidth, &text_width); ac++;
7067     XtSetArg(al[ac], XmNhighlightThickness, &highlight_thickness); ac++;
7068     XtSetArg(al[ac], XmNshadowThickness, &shadow_thickness); ac++;
7069     XtSetArg(al[ac], XmNmarginWidth, &margin_width); ac++;
7070     XtGetValues(M_text(editor), al, ac);
7071
7072     if (M_fontWidth(editor) != 0)
7073       rightMargin = ( (int)text_width - 
7074                       (2 * ((int)highlight_thickness + 
7075                             (int)shadow_thickness + (int)margin_width)) 
7076                     ) / M_fontWidth(editor);
7077     else
7078       rightMargin = (int)text_width - 
7079                     (2 * ((int)highlight_thickness + 
7080                           (int)shadow_thickness + (int)margin_width)); 
7081
7082     return( rightMargin );
7083
7084 } /* end ComputeRightMargin */
7085
7086 /* ARGSUSED */
7087 static void 
7088 UpdateAdjust(
7089         Widget widget,
7090         XtPointer *client_data,
7091         XConfigureEvent *event )
7092 {
7093     Dimension width;
7094     DtEditorWidget editor = (DtEditorWidget) client_data;
7095     char orgnum[20];        /* original margin size string */
7096     Arg al[2];
7097
7098     XtSetArg(al[0], XmNwidth, &width);
7099     XtGetValues(M_text(editor), al, 1);
7100
7101     if (width == M_textWidth(editor))
7102         return;
7103
7104     M_textWidth(editor) = width;
7105
7106     sprintf( orgnum, "%d", ComputeRightMargin(editor) );
7107     XmTextFieldSetString(M_format_rightMarginField(editor), orgnum);
7108 }
7109
7110 /************************************************************************
7111  *
7112  *  SetFormatDialogTitle - Change the title for the Format Settings dialog
7113  *
7114  ************************************************************************/
7115
7116 static void
7117 SetFormatDialogTitle(
7118         DtEditorWidget editor)
7119 {
7120   Arg al[2];
7121
7122   /*
7123    * If the Format Settings dialog has been created, change its title
7124    */
7125   if( M_format_dialog(editor) != (Widget)NULL )
7126   {
7127
7128        /*
7129         * Prepend the DialogTitle resource, if it has been set
7130         */
7131        if( E_dialogTitle(editor) != (XmString)NULL ) {
7132          XmString titleStr;
7133
7134          /*
7135           * Add the "functional title" to the DialogTitle
7136           */
7137          titleStr = XmStringConcat( E_dialogTitle(editor), 
7138                                     E_format_dialogTitle(editor) );
7139
7140          XtSetArg( al[0], XmNdialogTitle, titleStr );
7141          XtSetValues(M_format_dialog(editor), al, 1);
7142
7143          XmStringFree( titleStr );
7144
7145      }
7146      else {
7147          XtSetArg( al[0], XmNdialogTitle, E_format_dialogTitle(editor) );
7148          XtSetValues(M_format_dialog(editor), al, 1);
7149      }
7150
7151   }
7152
7153 } /* end SetFormatDialogTitle */
7154
7155 /************************************************************************
7156  *
7157  *  ResetFormatDialog - Reset margins & alignment of the Format Settings 
7158  *                      dialog
7159  *
7160  ************************************************************************/
7161
7162 static void
7163 ResetFormatDialog(
7164         DtEditorWidget editor)
7165 {
7166     char orgnum[20];        /* original margin size string */
7167
7168     /*
7169      * Reset the margins to default values
7170      */
7171
7172     /* Right margin default value */
7173     sprintf( orgnum, "%d", ComputeRightMargin(editor) );
7174     XmTextFieldSetString(M_format_rightMarginField(editor), orgnum);
7175
7176     /* Left margin default value */
7177     sprintf(orgnum, "%d", 0);
7178     XmTextFieldSetString(M_format_leftMarginField(editor), orgnum);
7179
7180     /*
7181      * Reset the alignment style to default value
7182      */
7183     XmToggleButtonGadgetSetState(M_format_leftJust(editor), True, True);
7184
7185 } /* end ResetFormatDialog */
7186
7187
7188 /************************************************************************
7189  *
7190  *  CreateFormatDialog - Create & initialize the Format Settings dialog
7191  *
7192  ************************************************************************/
7193
7194 static void
7195 CreateFormatDialog(
7196         DtEditorWidget editor)
7197 {
7198     Arg         al[15];        /* arg list */
7199     register    int ac;        /* arg count */
7200     Pixel       textBackground, textForeground;
7201     XmString    tempString = (XmString)NULL;
7202
7203        /* 
7204         * Match the background & foreground colors of the edit window
7205         * Don't use DtNtextBackground/Foreground directly because they 
7206         * will be DtUNSPECIFIED.
7207         */
7208        ac = 0;
7209        XtSetArg(al[ac], XmNforeground, &textForeground); ac++;
7210        XtSetArg(al[ac], XmNbackground, &textBackground); ac++;
7211        XtGetValues(M_text(editor), al, ac);
7212
7213        ac = 0;
7214
7215        /* 
7216         * First, create the dialog's title, prepending the 
7217         * DtNdialogTitle resource, if it is set
7218         */
7219        if( E_dialogTitle(editor) != (XmString)NULL ) {
7220
7221          /*
7222           * Add the "functional title" to the DialogTitle
7223           */
7224          tempString = XmStringConcat( E_dialogTitle(editor), 
7225                                       E_format_dialogTitle(editor) );
7226          XtSetArg (al[ac], XmNdialogTitle, tempString ); ac++;
7227  
7228        }
7229        else {
7230          XtSetArg(al[ac], XmNdialogTitle, E_format_dialogTitle(editor)); ac++;
7231        }
7232
7233        XtSetArg (al[ac], XmNautoUnmanage, False);         ac++;
7234        XtSetArg (al[ac], XmNmarginWidth, 5);              ac++;
7235        XtSetArg (al[ac], XmNmarginHeight, 5);             ac++;
7236        XtSetArg (al[ac], XmNshadowThickness, 1);          ac++;
7237        XtSetArg (al[ac], XmNshadowType, XmSHADOW_OUT);    ac++;
7238        XtSetArg (al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
7239        M_format_dialog(editor) = XmCreateFormDialog(
7240                                 M_topLevelShell(editor), "ad_dial", al, ac);
7241        if (tempString != (XmString)NULL)
7242          XmStringFree( tempString );
7243
7244        XtAddCallback(M_format_dialog(editor), XmNhelpCallback,
7245                      (XtCallbackProc)HelpFormatDialogCB, (XtPointer)editor);
7246
7247
7248        /*
7249         * When creating the fields & buttons use the appropriate label
7250         * resource (e.g. DtNcenterToggleLabel), if it has been set, then
7251         * clear the resource to save space.  The field or button widget 
7252         * will contain the actual value & it can be gotten from there, 
7253         * if it is needed.
7254         *
7255         * If the appropriate resource has not been set, use its default 
7256         * value from the message catalog.
7257         */
7258
7259        /*
7260         * create the left margin label and text field
7261         */
7262
7263        ac = 0;
7264        if (E_format_leftMarginFieldLabel(editor) != (XmString) DtUNSPECIFIED) { 
7265          /*
7266           * Use the resource value & clear it (to save space).
7267           */
7268          tempString = XmStringCopy(E_format_leftMarginFieldLabel(editor));
7269          E_format_leftMarginFieldLabel(editor) = (XmString) DtUNSPECIFIED;
7270        }
7271        else { 
7272          /*
7273           * The resource has not been set so use its default value
7274           */
7275          tempString = XmStringCreateLocalized(LEFT_MARGIN);
7276        }
7277
7278        XtSetArg(al[ac], XmNlabelString, tempString); ac++;
7279        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_POSITION);  ac++;
7280        XtSetArg (al[ac], XmNleftPosition, 2);                    ac++;
7281        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_FORM);       ac++;
7282        XtSetArg (al[ac], XmNtopOffset, 10);                      ac++;
7283        XtSetArg (al[ac], XmNfontList, E_labelFontList(editor));  ac++;
7284        M_format_leftLabel(editor) = (Widget) XmCreateLabelGadget (
7285                              M_format_dialog(editor), "left_label", al, ac);
7286        XtManageChild (M_format_leftLabel(editor));
7287        XmStringFree (tempString);
7288
7289        XtAddCallback(M_format_leftLabel(editor), XmNhelpCallback,
7290                      (XtCallbackProc)HelpFormatLeftMarginCB, (XtPointer)editor);
7291
7292        ac = 0;
7293        XtSetArg (al[ac], XmNbackground, textBackground);   ac++;
7294        XtSetArg (al[ac], XmNforeground, textForeground);   ac++;
7295        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_WIDGET);   ac++;
7296        XtSetArg (al[ac], XmNleftWidget, M_format_leftLabel(editor));  ac++;
7297        XtSetArg (al[ac], XmNleftOffset, 3);                     ac++;
7298        XtSetArg (al[ac], XmNrightAttachment, XmATTACH_POSITION);   ac++;
7299        XtSetArg (al[ac], XmNrightPosition, 45);   ac++;
7300        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_FORM);     ac++;
7301        XtSetArg (al[ac], XmNtopOffset, 5);                     ac++;
7302        XtSetArg (al[ac], XmNtraversalOn, True);                ac++;
7303        XtSetArg (al[ac], XmNcolumns, 3);                       ac++;
7304        XtSetArg (al[ac], XmNfontList, E_textFontList(editor)); ac++;
7305        M_format_leftMarginField(editor) = (Widget) XmCreateTextField (
7306                                 M_format_dialog(editor), "left_text", al, ac);
7307        XtManageChild (M_format_leftMarginField(editor));
7308        XtAddCallback(M_format_leftMarginField(editor), XmNhelpCallback,
7309                      (XtCallbackProc)HelpFormatLeftMarginCB, (XtPointer)editor);
7310        /*
7311         * create the right margin label and text field
7312         */
7313        ac = 0;
7314        if (E_format_rightMarginFieldLabel(editor) != (XmString) DtUNSPECIFIED)
7315        { 
7316          /*
7317           * Use the resource value & clear it (to save space).
7318           */
7319          tempString = XmStringCopy(E_format_rightMarginFieldLabel(editor));
7320          E_format_rightMarginFieldLabel(editor) = (XmString) DtUNSPECIFIED;
7321        }
7322        else
7323        { 
7324          /*
7325           * The resource has not been set so use its default value
7326           */
7327          tempString = XmStringCreateLocalized(RIGHT_MARGIN);
7328        }
7329        XtSetArg(al[ac], XmNlabelString, tempString); ac++;
7330        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
7331        XtSetArg (al[ac], XmNleftPosition, 55);                  ac++;
7332        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_FORM);      ac++;
7333        XtSetArg (al[ac], XmNtopOffset, 10);                     ac++;
7334        XtSetArg (al[ac], XmNfontList, E_labelFontList(editor)); ac++;
7335        M_format_rightLabel(editor)= (Widget) XmCreateLabelGadget (
7336                         M_format_dialog(editor), "right_label", al, ac);
7337        XtManageChild (M_format_rightLabel(editor));
7338        XmStringFree (tempString);
7339        XtAddCallback(M_format_rightLabel(editor), XmNhelpCallback,
7340                      (XtCallbackProc)HelpFormatRightMarginCB, 
7341                      (XtPointer)editor);
7342        ac = 0;
7343        XtSetArg (al[ac], XmNbackground, textBackground);   ac++;
7344        XtSetArg (al[ac], XmNforeground, textForeground);   ac++;
7345        XtSetArg (al[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
7346        XtSetArg (al[ac], XmNrightPosition, 98);                 ac++;
7347        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_WIDGET);   ac++;
7348        XtSetArg (al[ac], XmNleftWidget, M_format_rightLabel(editor));   ac++;
7349        XtSetArg (al[ac], XmNleftOffset, 3);                     ac++;
7350        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_FORM);      ac++;
7351        XtSetArg (al[ac], XmNtopOffset, 5);                      ac++;
7352        XtSetArg (al[ac], XmNtraversalOn, True);                 ac++;
7353        XtSetArg (al[ac], XmNcolumns, 3);                        ac++;
7354        XtSetArg (al[ac], XmNfontList, E_textFontList(editor)); ac++;
7355        M_format_rightMarginField(editor) = (Widget) XmCreateTextField (
7356                                                 M_format_dialog(editor),
7357                                                 "right_text", al, ac);
7358        XtManageChild (M_format_rightMarginField(editor));
7359        XtAddCallback(M_format_rightMarginField(editor), XmNhelpCallback,
7360                      (XtCallbackProc)HelpFormatRightMarginCB, 
7361                      (XtPointer)editor);
7362
7363        /*
7364         * create the radio box for justification choices
7365         */
7366        ac = 0;
7367        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_FORM);     ac++;
7368        XtSetArg (al[ac], XmNleftOffset, 5);                     ac++;
7369        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_WIDGET);    ac++;
7370        XtSetArg (al[ac], XmNtopWidget, M_format_leftMarginField(editor));  ac++;
7371        XtSetArg (al[ac], XmNtopOffset, 5);                     ac++;
7372        XtSetArg (al[ac], XmNrightAttachment, XmATTACH_FORM);    ac++;
7373        XtSetArg (al[ac], XmNrightOffset, 5);                    ac++;
7374        XtSetArg (al[ac], XmNtraversalOn, True);                 ac++;
7375        M_format_radioBox(editor) = (Widget) XmCreateRadioBox(
7376                                 M_format_dialog(editor), "radioBox", al, ac);
7377        XtAddCallback(M_format_radioBox(editor), XmNhelpCallback,
7378                      (XtCallbackProc)HelpFormatJustifyButtonsCB,
7379                      (XtPointer)editor);
7380        XtManageChild(M_format_radioBox(editor));
7381
7382        /* Create Left Align toggle */
7383        ac = 0;
7384        if (E_format_leftAlignToggleLabel(editor) != (XmString) DtUNSPECIFIED) { 
7385          /*
7386           * Use the resource value & clear it (to save space).
7387           */
7388          tempString = XmStringCopy(E_format_leftAlignToggleLabel(editor));
7389          E_format_leftAlignToggleLabel(editor) = (XmString) DtUNSPECIFIED;
7390        }
7391        else { 
7392          /*
7393           * The resource has not been set so use its default value
7394           */
7395          tempString = XmStringCreateLocalized(LEFT_ALIGN);
7396        }
7397        XtSetArg(al[ac], XmNlabelString, tempString); ac++;
7398        XtSetArg (al[ac], XmNfontList, E_buttonFontList(editor)); ac++;
7399        M_format_leftJust(editor) = (Widget) XmCreateToggleButtonGadget(
7400                         M_format_radioBox(editor), "left_just", al, ac);
7401        XmStringFree (tempString);
7402        XtManageChild(M_format_leftJust(editor));
7403
7404        /* Create Right Align toggle */
7405        ac = 0;
7406        if(E_format_rightAlignToggleLabel(editor) != (XmString)DtUNSPECIFIED) { 
7407          /*
7408           * Use the resource value & clear it (to save space).
7409           */
7410          tempString = XmStringCopy(E_format_rightAlignToggleLabel(editor));
7411          E_format_rightAlignToggleLabel(editor) = (XmString) DtUNSPECIFIED;
7412        }
7413        else { 
7414          /*
7415           * The resource has not been set so use its default value
7416           */
7417          tempString = XmStringCreateLocalized(RIGHT_ALIGN);
7418        }
7419        XtSetArg(al[ac], XmNlabelString, tempString); ac++;
7420        XtSetArg (al[ac], XmNfontList, E_buttonFontList(editor)); ac++;
7421        M_format_rightJust(editor) = (Widget) XmCreateToggleButtonGadget(
7422                         M_format_radioBox(editor), "right_just", al, ac);
7423        XmStringFree (tempString);
7424        XtManageChild(M_format_rightJust(editor));
7425
7426        /* Create Justify toggle */
7427        ac = 0;
7428        if (E_format_justifyToggleLabel(editor) != (XmString) DtUNSPECIFIED) { 
7429          /*
7430           * Use the resource value & clear it (to save space).
7431           */
7432          tempString = XmStringCopy(E_format_justifyToggleLabel(editor));
7433          E_format_justifyToggleLabel(editor) = (XmString) DtUNSPECIFIED;
7434        }
7435        else { 
7436          /*
7437           * The resource has not been set so use its default value
7438           */
7439          tempString = XmStringCreateLocalized( JUSTIFY );
7440        }
7441        XtSetArg(al[ac], XmNlabelString, tempString); ac++;
7442        XtSetArg (al[ac], XmNfontList, E_buttonFontList(editor)); ac++;
7443        M_format_bothJust(editor) = (Widget) XmCreateToggleButtonGadget(
7444                                 M_format_radioBox(editor), "both_just", al, ac);
7445        XmStringFree (tempString);
7446        XtManageChild(M_format_bothJust(editor));
7447
7448        /* Create Center align toggle */
7449        ac = 0;
7450        if (E_format_centerToggleLabel(editor) != (XmString) DtUNSPECIFIED) { 
7451          /*
7452           * Use the resource value & clear it (to save space).
7453           */
7454          tempString = XmStringCopy(E_format_centerToggleLabel(editor));
7455          E_format_centerToggleLabel(editor) = (XmString) DtUNSPECIFIED;
7456        }
7457        else { 
7458          /*
7459           * The resource has not been set so use its default value
7460           */
7461          tempString = XmStringCreateLocalized(CENTER); 
7462        }
7463        XtSetArg(al[ac], XmNlabelString, tempString); ac++;
7464        XtSetArg (al[ac], XmNfontList, E_buttonFontList(editor)); ac++;
7465        M_format_center(editor) = (Widget) XmCreateToggleButtonGadget(
7466                                 M_format_radioBox(editor), "center", al, ac);
7467        XmStringFree(tempString);
7468        XtManageChild(M_format_center(editor));
7469
7470        /*  Create a separator between the radio box and buttons  */
7471
7472        ac = 0;
7473        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_FORM);     ac++;
7474        XtSetArg (al[ac], XmNrightAttachment, XmATTACH_FORM);    ac++;
7475        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_WIDGET);    ac++;
7476        XtSetArg (al[ac], XmNtopWidget, M_format_radioBox(editor));    ac++;
7477        XtSetArg (al[ac], XmNtopOffset, 15);                     ac++;
7478        M_format_separator(editor) =  (Widget) XmCreateSeparatorGadget (
7479                                 M_format_dialog(editor), "separator", al, ac);
7480        XtManageChild (M_format_separator(editor));
7481
7482        /* Create Format Paragraph button */
7483        ac = 0;
7484        if ( E_format_formatParagraphButtonLabel(editor) != 
7485             (XmString) DtUNSPECIFIED ) { 
7486          /*
7487           * Use the resource value & clear it (to save space).
7488           */
7489          tempString = XmStringCopy(E_format_formatParagraphButtonLabel(editor));
7490          E_format_formatParagraphButtonLabel(editor) = (XmString) DtUNSPECIFIED;
7491        }
7492        else { 
7493          /*
7494           * The resource has not been set so use its default value
7495           */
7496          tempString =  XmStringCreateLocalized(PARAGRAPH);
7497        }
7498        XtSetArg(al[ac], XmNlabelString, tempString); ac++;
7499        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_POSITION);    ac++;
7500        XtSetArg (al[ac], XmNleftPosition, 2);                      ac++;
7501        XtSetArg (al[ac], XmNrightAttachment, XmATTACH_POSITION);   ac++;
7502        XtSetArg (al[ac], XmNrightPosition, 25);                    ac++;
7503        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_WIDGET);       ac++;
7504        XtSetArg (al[ac], XmNtopWidget, M_format_separator(editor));  ac++;
7505        XtSetArg (al[ac], XmNtopOffset, 5);                         ac++;
7506        XtSetArg (al[ac], XmNbottomAttachment, XmATTACH_FORM);      ac++;
7507        XtSetArg (al[ac], XmNbottomOffset, 5);                      ac++;
7508        XtSetArg (al[ac], XmNmarginWidth, 4);                       ac++;
7509        XtSetArg (al[ac], XmNmarginHeight, 4);                      ac++;
7510        XtSetArg (al[ac], XmNfontList, E_buttonFontList(editor)); ac++;
7511        M_format_paragraph(editor) = (Widget) XmCreatePushButtonGadget (
7512                                 M_format_dialog(editor), "para", al, ac);
7513        XtManageChild (M_format_paragraph(editor));
7514        XmStringFree (tempString);
7515        XtAddCallback (M_format_paragraph(editor), XmNactivateCallback,
7516                        (XtCallbackProc) AdjustParaCB, (XtPointer) editor);
7517
7518        /* Create Format All button */
7519        ac = 0;
7520        if (E_format_formatAllButtonLabel(editor) != (XmString)DtUNSPECIFIED) { 
7521          /*
7522           * Use the resource value & clear it (to save space).
7523           */
7524          tempString = XmStringCopy(E_format_formatAllButtonLabel(editor));
7525          E_format_formatAllButtonLabel(editor) = (XmString) DtUNSPECIFIED;
7526        }
7527        else { 
7528          /*
7529           * The resource has not been set so use its default value
7530           */
7531          tempString = XmStringCreateLocalized(ALL);
7532        }
7533        XtSetArg(al[ac], XmNlabelString, tempString); ac++;
7534        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_POSITION);    ac++;
7535        XtSetArg (al[ac], XmNleftPosition, 27);                     ac++;
7536        XtSetArg (al[ac], XmNrightAttachment, XmATTACH_POSITION);   ac++;
7537        XtSetArg (al[ac], XmNrightPosition, 49);                    ac++;
7538        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_WIDGET);       ac++;
7539        XtSetArg (al[ac], XmNtopWidget, M_format_separator(editor));  ac++;
7540        XtSetArg (al[ac], XmNtopOffset, 5);                         ac++;
7541        XtSetArg (al[ac], XmNbottomAttachment, XmATTACH_FORM);      ac++;
7542        XtSetArg (al[ac], XmNbottomOffset, 5);                      ac++;
7543        XtSetArg (al[ac], XmNmarginWidth, 4);                       ac++;
7544        XtSetArg (al[ac], XmNmarginHeight, 4);                      ac++;
7545        XtSetArg (al[ac], XmNfontList, E_buttonFontList(editor)); ac++;
7546        M_format_all(editor) = (Widget) XmCreatePushButtonGadget(
7547                                      M_format_dialog(editor), "all", al, ac);
7548        XtManageChild (M_format_all(editor));
7549        XmStringFree (tempString);
7550        XtAddCallback (M_format_all(editor), XmNactivateCallback,
7551                        (XtCallbackProc) AdjustAllCB, (XtPointer) editor);
7552
7553        /* Create Close button */
7554        tempString = XmStringCreateLocalized(CLOSE_BUTTON);
7555        ac = 0;
7556        XtSetArg (al[ac], XmNlabelString, tempString);  ac++;
7557        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_POSITION);    ac++;
7558        XtSetArg (al[ac], XmNleftPosition, 51);                     ac++;
7559        XtSetArg (al[ac], XmNrightAttachment, XmATTACH_POSITION);   ac++;
7560        XtSetArg (al[ac], XmNrightPosition, 73);                    ac++;
7561        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_WIDGET);       ac++;
7562        XtSetArg (al[ac], XmNtopWidget, M_format_separator(editor)); ac++;
7563        XtSetArg (al[ac], XmNtopOffset, 5);                         ac++;
7564        XtSetArg (al[ac], XmNbottomAttachment, XmATTACH_FORM);      ac++;
7565        XtSetArg (al[ac], XmNbottomOffset, 5);                      ac++;
7566        XtSetArg (al[ac], XmNmarginWidth, 4);                       ac++;
7567        XtSetArg (al[ac], XmNmarginHeight, 4);                      ac++;
7568        XtSetArg (al[ac], XmNfontList, E_buttonFontList(editor));   ac++;
7569        M_format_close(editor) = (Widget) XmCreatePushButtonGadget (
7570                         M_format_dialog(editor), "close", al, ac);
7571        XtManageChild (M_format_close(editor));
7572        XmStringFree (tempString);
7573        XtAddCallback (M_format_close(editor), XmNactivateCallback,
7574                        (XtCallbackProc) AdjustCloseCB, (XtPointer) editor);
7575
7576        tempString = XmStringCreateLocalized(HELP_BUTTON);
7577        ac = 0;
7578        XtSetArg (al[ac], XmNlabelString, tempString);              ac++;
7579        XtSetArg (al[ac], XmNleftAttachment, XmATTACH_POSITION);    ac++;
7580        XtSetArg (al[ac], XmNleftPosition, 75);                     ac++;
7581        XtSetArg (al[ac], XmNrightAttachment, XmATTACH_POSITION);   ac++;
7582        XtSetArg (al[ac], XmNrightPosition, 98);                    ac++;
7583        XtSetArg (al[ac], XmNtopAttachment, XmATTACH_WIDGET);       ac++;
7584        XtSetArg (al[ac], XmNtopWidget, M_format_separator(editor));  ac++;
7585        XtSetArg (al[ac], XmNtopOffset, 5);                         ac++;
7586        XtSetArg (al[ac], XmNbottomAttachment, XmATTACH_FORM);      ac++;
7587        XtSetArg (al[ac], XmNbottomOffset, 5);                      ac++;
7588        XtSetArg (al[ac], XmNmarginWidth, 4);                       ac++;
7589        XtSetArg (al[ac], XmNmarginHeight, 4);                      ac++;
7590        XtSetArg (al[ac], XmNfontList, E_buttonFontList(editor));   ac++;
7591        M_format_help(editor) = (Widget) XmCreatePushButtonGadget(
7592                                 M_format_dialog(editor), "help", al, ac);
7593        XtManageChild (M_format_help(editor));
7594        XmStringFree (tempString);
7595        XtAddCallback( M_format_help(editor), XmNactivateCallback,
7596                       (XtCallbackProc) HelpFormatDialogCB, (XtPointer) editor);
7597
7598        /*
7599         * set the default/activation button.
7600         */
7601        XtSetArg(al[0], XmNdefaultButton, M_format_close(editor));
7602        XtSetValues(M_format_dialog(editor), al, 1);
7603
7604        XtRealizeWidget (M_format_dialog(editor));
7605
7606        /*
7607         * Initialize the margins & alignment toggles
7608         */
7609        ResetFormatDialog(editor);
7610
7611        XtSetArg(al[0], XmNwidth, &(M_textWidth(editor)));
7612        XtGetValues(M_text(editor), al, 1);
7613
7614        XtAddEventHandler(M_text(editor), StructureNotifyMask, False,
7615                             (XtEventHandler) UpdateAdjust, (XtPointer) editor);
7616
7617 } /* end CreateFormatDialog */
7618
7619 /************************************************************************
7620  *
7621  *  GetAdjustSettings - Read the alignment settings from the Format
7622  *                      Settings dialog.
7623  *
7624  ************************************************************************/
7625
7626 static void
7627 GetAdjustSettings(
7628         DtEditorWidget editor,
7629         DtEditorFormatSettings  *formatSettings)
7630 {
7631
7632     if( M_format_dialog(editor)!= (Widget)NULL ) {
7633
7634       /*
7635        * Read the current alignment settings from the Format Settings
7636        * dialog.
7637        */
7638       char *num;
7639
7640       /* 
7641        * Get current type of alignment 
7642        */
7643       if (XmToggleButtonGadgetGetState(M_format_leftJust(editor)))
7644           formatSettings->alignment = DtEDITOR_ALIGN_LEFT;
7645       else if (XmToggleButtonGadgetGetState(M_format_rightJust(editor)))
7646           formatSettings->alignment = DtEDITOR_ALIGN_RIGHT;
7647       else if (XmToggleButtonGadgetGetState(M_format_bothJust(editor)))
7648           formatSettings->alignment = DtEDITOR_ALIGN_JUSTIFY;
7649       else
7650           formatSettings->alignment = DtEDITOR_ALIGN_CENTER;
7651
7652       /* 
7653        * Get current margin settings 
7654        */
7655       num = (char *) XmTextFieldGetString( 
7656                                 (Widget)M_format_rightMarginField(editor) );
7657       formatSettings->rightMargin = atoi(num);
7658       XtFree(num);
7659       num = (char *) XmTextFieldGetString( 
7660                                 (Widget)M_format_leftMarginField(editor) );
7661       formatSettings->leftMargin = atoi(num);
7662       XtFree(num);
7663
7664     } 
7665     else {
7666
7667       /* 
7668        * The Format Settings dialog box has not been created so use the
7669        * default values.
7670        */
7671       formatSettings->leftMargin = 0;
7672       formatSettings->rightMargin = ComputeRightMargin(editor);
7673       formatSettings->alignment = DtEDITOR_ALIGN_LEFT;
7674
7675     }
7676 }
7677
7678 /****************************************************************
7679  *
7680  *  Public Procs 
7681  *
7682  ****************************************************************/
7683
7684
7685
7686 /*********************************************************
7687  *
7688  *  DtCreateEditor
7689  *      Create an instance of an editor and return the widget id.
7690  */
7691
7692 Widget
7693 DtCreateEditor(
7694         Widget parent,
7695         char *name,
7696         ArgList arglist,
7697         Cardinal argcount )
7698 {
7699   return( XtCreateWidget(name,dtEditorWidgetClass,parent,arglist,argcount) );
7700 }
7701
7702 Boolean
7703 DtEditorCheckForUnsavedChanges(
7704         Widget widget)
7705 {
7706   DtEditorWidget editor = (DtEditorWidget) widget;
7707   Boolean result;
7708   _DtWidgetToAppContext(widget);
7709
7710   _DtAppLock(app);
7711   result = M_unreadChanges( editor );
7712   _DtAppUnlock(app);
7713
7714   return result;
7715 } /* end DtEditorCheckForUnsavedChanges */
7716
7717
7718 Boolean
7719 DtEditorDeleteSelection(
7720         Widget widget)
7721 {
7722     XmTextPosition first, last;
7723     DtEditorWidget editor = (DtEditorWidget) widget;
7724     Boolean result;
7725     _DtWidgetToAppContext(widget);
7726     _DtAppLock(app);
7727
7728     /* 
7729      * Check for a non-null selection
7730      */
7731     if ( XmTextGetSelectionPosition(M_text(editor), &first, &last) &&
7732          first != last )
7733     {
7734       XmTextRemove(M_text(editor));
7735       result = True;
7736     }
7737     else
7738       result = False;
7739
7740     _DtAppUnlock(app);
7741     return result;
7742 } /* end DtEditorDeleteSelection */
7743
7744
7745 /*
7746  * DtEditorClearSelection replaces the currently selected text with
7747  * spaces.  It requires an event because the underlying text widget
7748  * routines require one to look at the time stamp within.
7749  */
7750 Boolean
7751 DtEditorClearSelection(
7752         Widget widget)
7753 {
7754     DtEditorWidget editor = (DtEditorWidget) widget;
7755     char *params=(char *)NULL;
7756     Cardinal num_params = 0;
7757     XEvent event;
7758     _DtWidgetToAppContext(widget);
7759     _DtAppLock(app);
7760
7761     /*
7762      * Create an event with a correct timestamp
7763      */
7764     event.xkey.time = XtLastTimestampProcessed( M_display(editor) );
7765
7766     /*
7767      * Call routine to clear primary selection
7768      */
7769     ClearSelection( widget, &event, &params, &num_params );
7770
7771     _DtAppUnlock(app);
7772     return(True);
7773 } /* end DtEditorClearSelection */
7774
7775
7776 /*
7777  *
7778  * DtEditorDeselect - Unselects any selected text of an Editor widget
7779  *
7780  */
7781 Boolean 
7782 DtEditorDeselect( 
7783         Widget widget)
7784 {
7785   DtEditorWidget editor = (DtEditorWidget) widget;
7786   char *params=(char *)NULL;
7787   Cardinal num_params = 0;
7788   XEvent event;
7789   _DtWidgetToAppContext(widget);
7790   _DtAppLock(app);
7791
7792   /*
7793    * Create an event with a correct timestamp
7794    */
7795   event.xkey.time = XtLastTimestampProcessed( M_display(editor) );
7796
7797   DeselectAll( widget, &event, &params, &num_params );
7798
7799   _DtAppUnlock(app);
7800   return(True);
7801
7802 } /* end DtEditorDeselect */
7803
7804
7805 /*
7806  *
7807  * DtEditorDisableRedisplay - Temporarily prevent visual update of a
7808  *                            Editor widget
7809  *
7810  */
7811 void 
7812 DtEditorDisableRedisplay( 
7813         Widget widget)
7814 {
7815   DtEditorWidget editor = (DtEditorWidget) widget;
7816   _DtWidgetToAppContext(widget);
7817   _DtAppLock(app);
7818
7819   XmTextDisableRedisplay( M_text(editor) );
7820   _DtAppUnlock(app);
7821 } /* end DtEditorDisableRedisplay */
7822
7823 /*
7824  *
7825  * DtEditorEnableRedisplay - Force visual update of an Editor widget 
7826  *
7827  */
7828 void 
7829 DtEditorEnableRedisplay( 
7830         Widget widget)
7831 {
7832   DtEditorWidget editor = (DtEditorWidget) widget;
7833   _DtWidgetToAppContext(widget);
7834   _DtAppLock(app);
7835
7836   XmTextEnableRedisplay( M_text(editor) );
7837   _DtAppUnlock(app);
7838 } /* end DtEditorEnableRedisplay */
7839
7840
7841 /*********
7842  *
7843  * DtEditorFormat 
7844  *              Given left & right margin values & an alignment style, 
7845  *              formats either the current paragraph or the entire document,
7846  *              as specified.  If margin values & alignment style are not
7847  *              provided, DtEditorFormat will use the current values from
7848  *              the Format Settings dialog.
7849  *
7850  *            Returns: 
7851  *              DtEDITOR_NO_ERRORS    if the text was formatted successfully.
7852  *              DtEDITOR_NO_TMP_FILE  if the 2 temporary files cannot be 
7853  *                                    created.
7854  *              DtEDITOR_ILLEGAL_SIZE if the left & right margins don't make 
7855  *                                    sense.
7856  *              DtEDITOR_INVALID_RANGE if specified amount to format is
7857  *                                    unrecognized
7858  *              DtEDITOR_INVALID_TYPE if specified alignment is
7859  *                                    unrecognized
7860  *
7861  */
7862 DtEditorErrorCode
7863 DtEditorFormat(
7864         Widget                  widget,
7865         DtEditorFormatSettings  *formatSettings,
7866         unsigned int            amountToFormat )
7867 {
7868
7869   DtEditorWidget editor = (DtEditorWidget) widget;
7870   DtEditorErrorCode error;
7871   int   leftMargin, rightMargin, alignment;
7872   _DtWidgetToAppContext(widget);
7873   _DtAppLock(app);
7874
7875   /* 
7876    * Check to see if we should use the format settings from the 
7877    * Format Settings dialog.
7878    */
7879   if( formatSettings == (DtEditorFormatSettings *) NULL )
7880   {
7881
7882     DtEditorFormatSettings tmpFormatSettings;
7883
7884     /* 
7885      * Get the format settings from the Format Settings dialog
7886      */
7887     GetAdjustSettings(editor, &tmpFormatSettings);
7888
7889     /*
7890      * Set up the correct format settings
7891      */
7892     leftMargin = tmpFormatSettings.leftMargin;
7893     rightMargin = tmpFormatSettings.rightMargin;
7894     alignment = tmpFormatSettings.alignment;
7895
7896   }
7897   else {
7898     leftMargin = formatSettings->leftMargin;
7899     rightMargin = formatSettings->rightMargin;
7900     alignment = formatSettings->alignment;
7901   }
7902
7903   /*
7904    * Now, do the formatting
7905    */
7906
7907   switch (amountToFormat)
7908   {
7909     case DtEDITOR_FORMAT_ALL: 
7910     {
7911        error = DoAdjust( editor, leftMargin, rightMargin, alignment,  
7912                          0, XmTextGetLastPosition(M_text(editor)) );
7913        break;
7914     }
7915
7916     case DtEDITOR_FORMAT_PARAGRAPH: 
7917     {
7918        XmTextPosition start, end;
7919        char *params=(char *)NULL;
7920        Cardinal num_params = 0;
7921
7922        /*
7923         * Create an event with a correct timestamp
7924         */
7925        XEvent event;
7926        event.xkey.time = XtLastTimestampProcessed( M_display(editor) );
7927
7928        /* 
7929         * Get the beginning & ending positions of the current paragraph
7930         */
7931        ForwardPara( widget, &event, &params, &num_params );
7932        end = XmTextGetInsertionPosition(M_text(editor));
7933        if( end != XmTextGetLastPosition(M_text(editor)) ) {
7934           /*
7935            * If we're not at the end, then we need to back up to the
7936            * start of this line, otherwise we'll disturb the first line
7937            * of the following paragraph.  If we are at the end, then "end"
7938            * must point to the end of the line, or we'll leave the last
7939            * line along with the formatted text.
7940            */
7941           BeginningOfLine( widget, &event, &params, &num_params );
7942           end = XmTextGetInsertionPosition(M_text(editor));
7943        }
7944
7945        BackwardPara( widget, &event, &params, &num_params );
7946        BeginningOfLine( widget, &event, &params, &num_params );
7947        start = XmTextGetInsertionPosition(M_text(editor));
7948
7949        /*
7950         * Pass in beginning & ending positions to adjust the current 
7951         * paragraph
7952         */
7953        error = DoAdjust( editor, leftMargin, rightMargin, alignment, 
7954                          start, end );
7955        break;
7956     }
7957
7958     default: {
7959       error = DtEDITOR_INVALID_RANGE;
7960     }
7961
7962   } /* end switch */
7963
7964   _DtAppUnlock(app);
7965   return( error );
7966
7967 } /* DtEditorFormat */
7968
7969
7970 /*
7971  *
7972  * DtEditorGetMessageTextFieldID - Returns the widget ID of the Text
7973  *      Field used to display application status messages.
7974  *
7975  */
7976 Widget
7977 DtEditorGetMessageTextFieldID(
7978         Widget          widget)
7979 {
7980    DtEditorWidget editor = (DtEditorWidget) widget;
7981    Widget result;
7982    _DtWidgetToAppContext(widget);
7983    _DtAppLock(app);
7984
7985    /*
7986     * Create the status line if is does not exist
7987     */
7988    if( M_status_statusArea(editor) == (Widget) NULL )
7989       M_status_statusArea(editor) = CreateStatusLine( editor ); 
7990
7991    result = M_status_messageText(editor);
7992
7993    _DtAppUnlock(app);
7994    return result;
7995
7996 } /* end DtEditorGetMessageTextFieldID */
7997
7998 /*
7999  * DtEditorGoToLine moves the insert cursor to the beginning of the
8000  * line specified by lineNumber.  It figures out the text character 
8001  * position corresponding to the specified line and sets the text 
8002  * widget's insertionPosition to that location.  If this new 
8003  * insertionPosition is not currently on-screen, then the
8004  * text widget's contents are scrolled to display the new position.
8005  *
8006  * The cursor can be moved to last line by specifying DtEDITOR_LAST_LINE 
8007  * as the line number.
8008  * If lineNumber is less than one, the insert cursor will be placed
8009  * at the beginning of the first line.  If it is greater than the total
8010  * number of lines, the cursor will be placed at the last line of text.
8011  */
8012  
8013 /* ARGSUSED */
8014 void DtEditorGoToLine(
8015         Widget  widget,
8016         int     lineNumber)
8017 {
8018     DtEditorWidget editor = (DtEditorWidget)widget;
8019     XmTextWidget tw;
8020     XmTextLineTable lineTab;
8021     XmTextPosition newPos;
8022     _DtWidgetToAppContext(widget);
8023     _DtAppLock(app);
8024
8025     tw = (XmTextWidget)M_text(editor);
8026     lineTab = tw->text.line_table;
8027
8028     /*
8029      * Validate the specified line number, check it is in range.
8030      * If we adjust the line number, then update the current line display
8031      * in the status line so it reflects where we are really going.  This
8032      * is only a problem if lineNumber is less/greater than the first/last
8033      * line becausee we won't be moving the cursor so the status line will 
8034      * not be updated.
8035      */
8036     if (lineNumber > tw->text.total_lines || lineNumber == DtEDITOR_LAST_LINE)
8037     {
8038        lineNumber = tw->text.total_lines;
8039        _DtEditorUpdateLineDisplay( editor, lineNumber, FORCE ); 
8040     }
8041     else if(lineNumber < 1)
8042     {
8043        lineNumber = 1;
8044        _DtEditorUpdateLineDisplay( editor, lineNumber, FORCE ); 
8045     }
8046
8047
8048     /*
8049      * Move the insertion cursor
8050      */
8051     newPos = lineTab[lineNumber - 1].start_pos;
8052     XmTextSetInsertionPosition(M_text(editor), newPos);
8053
8054     /* 
8055      * Scroll the widget, if necessary
8056      */
8057     if (newPos < tw->text.top_character || newPos >= tw->text.bottom_position)
8058     {
8059         Arg al[5];
8060         int ac;
8061         Dimension height;
8062         short rows;
8063         Position x, y;
8064
8065         ac = 0;
8066         XtSetArg(al[ac], XmNheight, &height);  ac++;
8067         XtSetArg(al[ac], XmNrows, &rows);  ac++;
8068         XtGetValues(M_text(editor), al, ac);
8069
8070         if(XmTextPosToXY(M_text(editor), newPos, &x, &y) == True)
8071         {
8072             int offset = (y - height/2) * rows;
8073             XmTextScroll(M_text(editor), offset/(int) height);
8074         }
8075     }
8076
8077     _DtAppUnlock(app);
8078 } /* end DtEditorGoToLine */
8079
8080 /*
8081  * DtEditorGetEditorSizeHints - Set the resize increment, minimum window 
8082  *      size, and base dimension properties in the supplied XSizeHints 
8083  *      struct for the editor as a whole.  
8084  * 
8085  * NOTE: This routine returns data in the struct pointed to by pHints.
8086  * 
8087  */
8088 void
8089 DtEditorGetSizeHints(
8090     Widget widget,
8091     XSizeHints *pHints) /* Return */
8092 {
8093     Arg al[10];                 /* arg list */
8094     register int ac;            /* arg count */
8095     Dimension FormWidth, FormHeight, 
8096               Twidth, Theight, statusHeight,
8097               highlightThickness, shadowThickness,
8098               marginWidth, marginHeight,
8099               textRegionWidth, textRegionHeight;
8100
8101     DtEditorWidget editor = (DtEditorWidget) widget;
8102     _DtWidgetToAppContext(widget);
8103     _DtAppLock(app);
8104
8105     /*
8106      * Window manager should resize in increments of a character or line.
8107      */
8108     pHints->width_inc   = M_fontWidth(editor);
8109     pHints->height_inc  = M_fontHeight(editor);
8110
8111     /*
8112      * Size of the Editor (Form)
8113      */
8114
8115     FormWidth = editor->core.width + (2 * editor->core.border_width);
8116     FormHeight = editor->core.height + (2 * editor->core.border_width);
8117
8118     /* 
8119      * Size of the Edit window (text widget) 
8120      */
8121     ac=0;
8122     XtSetArg(al[ac], XmNwidth, &Twidth); ac++;
8123     XtSetArg(al[ac], XmNheight, &Theight); ac++;
8124     XtSetArg(al[ac], XmNhighlightThickness, &highlightThickness); ac++;
8125     XtSetArg(al[ac], XmNshadowThickness, &shadowThickness); ac++;
8126     XtSetArg(al[ac], XmNmarginWidth, &marginWidth); ac++;
8127     XtSetArg(al[ac], XmNmarginHeight, &marginHeight); ac++;
8128     XtGetValues(M_text(editor), al, ac);
8129
8130     /*
8131      * Calculate the width & height of the area within the text widget 
8132      * which can actually display characters.
8133      */
8134     textRegionWidth  = (int)Twidth - 
8135                        (2 * ((int)highlightThickness + 
8136                              (int)shadowThickness + (int)marginWidth));
8137     textRegionHeight = (int)Theight - 
8138                        (2 * ((int)highlightThickness + 
8139                              (int)shadowThickness + (int)marginHeight));
8140
8141     /*
8142      * Set the base width/height to the size of the area which will not
8143      * display characters.
8144      * 
8145      * The base width/height is used by the window manager in concert 
8146      * with the height & width increments to display the current size 
8147      * (rows & columns) of edit window (text widget) while resizing the
8148      * editor.
8149      */
8150     pHints->base_width  = FormWidth - textRegionWidth;
8151     pHints->base_height = FormHeight - textRegionHeight;
8152     
8153     /* 
8154      * Get the height of the status line, if it is turned on. 
8155      * Remember, the border width is not included in the height of the
8156      * status line so add it in to account for the border between the
8157      * edit window (text widget) and the status line.
8158      */
8159
8160     /* XXX Actually, the statusHeight should already be included in the 
8161      * FormHeight, so it should not be necessary to add it in again.  
8162      * However, the numbers don't come out right otherwise. Hmmm? */
8163
8164     if( M_status_showStatusLine(editor) == True )
8165     {
8166         XtSetArg( al[0], XmNheight, &statusHeight );
8167         XtGetValues( M_status_statusArea(editor), al, 1 );
8168         statusHeight = statusHeight + editor->core.border_width;
8169     }
8170     else
8171         statusHeight = 0;
8172
8173     /*
8174      * What is being returned here is the minimum width & height of the 
8175      * editor. Leave room for the scrollbars, shadows, etc., plus one 
8176      * character.
8177      */
8178     pHints->min_width  = pHints->base_width + pHints->width_inc;
8179     pHints->min_height = pHints->base_width + pHints->height_inc +
8180                          statusHeight;
8181
8182     pHints->flags = PMinSize | PResizeInc | PBaseSize;
8183
8184     _DtAppUnlock(app);
8185 }  /* end DtEditorGetSizeHints */
8186
8187
8188 void
8189 DtEditorInvokeFormatDialog(
8190         Widget widget)
8191 {
8192   DtEditorWidget editor = (DtEditorWidget) widget;
8193   _DtWidgetToAppContext(widget);
8194   _DtAppLock(app);
8195
8196   /* 
8197    * Create the dialog if it is the first time 
8198    */
8199   if (M_format_dialog(editor) == (Widget)NULL) 
8200       CreateFormatDialog( editor );
8201
8202   /*
8203    * Post the dialog
8204    */
8205   XtUnmanageChild (M_format_dialog(editor));
8206   XtManageChild (M_format_dialog(editor));
8207   XmProcessTraversal(M_format_paragraph(editor), XmTRAVERSE_CURRENT);
8208
8209   _DtAppUnlock(app);
8210 } /* DtEditorInvokeFormatDialog */
8211
8212
8213 void
8214 DtEditorReset(
8215         Widget widget)
8216 {
8217   DtEditorContentRec cr;
8218   DtEditorWidget editor = (DtEditorWidget) widget;
8219   _DtWidgetToAppContext(widget);
8220   _DtAppLock(app);
8221
8222   /*
8223    * Reset the edit window (includes the Undo context)
8224    */
8225   cr.type = DtEDITOR_TEXT;
8226   cr.value.string = "";
8227   DtEditorSetContents( widget, &cr );
8228
8229   /*
8230    * Reset the status line
8231    * Note, the current & total line displays are reset by DtEditorSetContents()
8232    */
8233   if( M_status_statusArea(editor) != (Widget) NULL ) {
8234
8235     XmTextFieldSetString( M_status_messageText(editor), "" );
8236
8237   }
8238
8239   /*
8240    * Reset the Find/Change & Spell dialogs
8241    */
8242   if ( M_search_string(editor) ) 
8243     XtFree(M_search_string(editor));
8244   M_search_string(editor) = (char *)NULL;
8245
8246   if ( M_replace_string(editor) ) 
8247     XtFree(M_replace_string(editor));
8248   M_replace_string(editor) = (char *)NULL;
8249
8250   if (M_misspelled_string(editor))
8251     XtFree(M_misspelled_string(editor));
8252   M_misspelled_string(editor) = (char *)NULL;
8253
8254   /*
8255    * Reset the Format Settings dialog
8256    */
8257   if (M_format_dialog(editor) != (Widget)NULL)
8258     ResetFormatDialog(editor);  
8259  
8260   _DtAppUnlock(app);
8261 } /* end DtEditorReset */
8262
8263
8264 /*
8265  *
8266  * DtEditorSelectAll - Selects the contents of an Editor widget
8267  *
8268  */
8269 Boolean 
8270 DtEditorSelectAll( 
8271         Widget widget)
8272 {
8273     DtEditorWidget editor = (DtEditorWidget) widget;
8274     char *params=(char *)NULL;
8275     Cardinal num_params = 0;
8276     XEvent event;
8277     _DtWidgetToAppContext(widget);
8278     _DtAppLock(app);
8279
8280     /*
8281      * Create an event with a correct timestamp
8282      */
8283     event.xkey.time = XtLastTimestampProcessed( M_display(editor) );
8284
8285     SelectAll( widget, &event, &params, &num_params );
8286
8287     _DtAppUnlock(app);
8288     return(True);
8289 } /* end DtEditorSelectAll */
8290
8291
8292 void
8293 DtEditorTraverseToEditor(
8294     Widget widget)
8295 {
8296   DtEditorWidget editor = (DtEditorWidget) widget;
8297   _DtWidgetToAppContext(widget);
8298   _DtAppLock(app);
8299
8300   XmProcessTraversal(M_text(editor), XmTRAVERSE_CURRENT);
8301
8302   _DtAppUnlock(app);
8303 } /* end DtEditorTraverseToEditor */
8304