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