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