2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
24 #ifdef VERBOSE_REV_INFO
25 static char rcs_id[] = "$TOG: TermPrim.c /main/15 1999/10/14 16:35:04 mgreess $";
26 #endif /* VERBOSE_REV_INFO */
30 * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company *
31 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
32 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. *
33 * (c) Copyright 1993, 1994, 1996 Novell, Inc. *
34 * (c) Copyright 1995, 1996 Digital Equipment Corporation. *
35 * (c) Copyright 1996 FUJITSU LIMITED. *
36 * (c) Copyright 1996 Hitachi. *
39 extern char _DtTermPrimPullInTermWhatString[];
40 static char *termWhatString = _DtTermPrimPullInTermWhatString;
41 extern char * _DtTermPrimGetMessage( char *filename, int set, int n, char *s );
48 #include <X11/keysym.h>
49 #include <Xm/MessageB.h>
51 #include <Xm/DisplayP.h>
52 #include <Xm/VirtKeys.h>
53 #include <Xm/MwmUtil.h>
54 #include "TermHeader.h"
55 #include "TermPrimOSDepI.h" /* for SETENV_LINES_AND_COLS */
56 #include "TermPrimI.h"
57 #include "TermPrimP.h"
58 #include "TermPrimBufferP.h"
59 #include "TermPrimAction.h"
60 #include "TermPrimParser.h"
61 #include "TermPrimParseTable.h"
62 #include "TermPrimPendingTextP.h"
63 #include "TermPrimRenderFont.h"
64 #include "TermPrimRenderFontSet.h"
65 #include "TermPrimSelectP.h"
66 #include "TermPrimSetUtmp.h"
67 #include "TermPrimUtil.h"
68 #include "TermPrimDebug.h"
69 #include "TermPrimWMProtocols.h"
70 #include "TermPrimSetPty.h"
71 #include <Xm/RepType.h>
72 #include "TermPrimRepType.h"
73 #include "TermPrimMessageCatI.h"
74 #include <X11/CoreP.h>
75 #include <Xm/ManagerP.h>
79 #if defined(linux) || defined(hpV4)
80 # include <sys/types.h> /* For FD_* macros. */
81 # include <sys/time.h> /* For select() prototype. */
83 # include <sys/select.h>
86 extern void TermReadKey(Widget w, XEvent *event, String *params,
87 Cardinal *num_params);
88 static void ClassInitialize(void);
89 static void ClassPartInitialize(WidgetClass wc);
90 static void initializeKeyboard(DtTermPrimData tpd);
91 static void initializeModes(DtTermPrimData tpd);
92 static void initializeStraps(DtTermPrimData tpd);
93 static void Initialize(Widget rw, Widget nw, Arg *args, Cardinal *num_args);
94 static void Resize(Widget w);
95 static void Redisplay(Widget w, XEvent *event, Region region);
96 static Boolean SetValues(Widget cw, Widget rw, Widget nw, ArgList args,
98 static void Realize(Widget w, XtValueMask *p_valueMask,
99 XSetWindowAttributes *attributes);
100 static void Destroy(Widget w);
101 static void readPty(XtPointer client_data, int *source,
103 static void handleKeyEvents(Widget w, XtPointer closure, XEvent *event,
105 static void handleButtonEvents(Widget w, XtPointer closure, XEvent *event,
107 static void handleNonMaskableEvents(Widget w, XtPointer eventData,
108 XEvent *event, Boolean *cont);
109 static void handlePropertyChangeEvents(Widget w, XtPointer eventData,
110 XEvent *event, Boolean *cont);
111 static void handleProcessStructureNotifyEvent(Widget w, XtPointer eventData,
112 XEvent *event, Boolean *cont);
113 static Boolean moreInput(int pty);
114 static void CapsLockUpdate(Widget w, Boolean capsLock);
115 static void InitializeVerticalScrollBar(Widget w, Boolean initCallbacks);
116 static void VerticalScrollBarCallback(Widget w, XtPointer client_data,
117 XtPointer call_data);
118 static void setThickness(Widget widget, int offset, XrmValue *value);
121 * on the spot callbacks
123 static int PreeditStart(
125 XPointer client_data,
128 static void PreeditDone(
130 XPointer client_data,
133 static void PreeditDraw(
135 XPointer client_data,
136 XIMPreeditDrawCallbackStruct *call_data);
138 static void PreeditCaret(
140 XPointer client_data,
141 XIMPreeditCaretCallbackStruct *call_data);
144 /* action list for class: Term... */
146 static XtActionsRec actionsList[] = {
147 {"self-insert", _DtTermPrimActionKeyInput},
148 {"insert", _DtTermPrimActionKeyInput},
149 {"key-release", _DtTermPrimActionKeyRelease},
150 {"grab-focus", _DtTermPrimSelectGrabFocus},
151 {"select-adjust", _DtTermPrimSelectExtend},
152 {"extend-end", _DtTermPrimSelectExtendEnd},
153 {"extend-start", _DtTermPrimSelectExtendStart},
154 {"copy-to", _DtTermPrimSelectInsert},
155 {"copy-clipboard", _DtTermPrimSelectCopyClipboardEventIF},
156 {"paste-clipboard", _DtTermPrimSelectPasteClipboardEventIF},
157 {"process-bdrag", _DtTermPrimSelectProcessBDrag},
158 {"leave", _DtTermPrimActionLeave},
159 {"enter", _DtTermPrimActionEnter},
160 {"focus-in", _DtTermPrimActionFocusIn},
161 {"focus-out", _DtTermPrimActionFocusOut},
162 {"keymap", _DtTermPrimActionKeymap},
163 {"redraw-display", _DtTermPrimActionRedrawDisplay},
164 {"return", _DtTermPrimActionReturn},
165 {"stop", _DtTermPrimActionStop},
166 {"string", _DtTermPrimActionString},
167 {"tab", _DtTermPrimActionTab},
168 {"select-page", _DtTermPrimSelectPage},
169 {"select-all", _DtTermPrimSelectAll},
170 {"process-cancel", _DtTermPrimSelectProcessCancel}
173 #define defaultColumns 80
174 #define defaultRows 24
176 /* the resource list for Term... */
177 static XtResource resources[] =
180 DtNcharCursorStyle, DtCCharCursorStyle, DtRDtTermCharCursorStyle,
181 sizeof(unsigned char),
182 XtOffsetOf(struct _DtTermPrimitiveRec, term.charCursorStyle),
183 XmRImmediate, (XtPointer) DtTERM_CHAR_CURSOR_BOX
186 DtNconsoleMode, DtCConsoleMode, XmRBoolean, sizeof(Boolean),
187 XtOffsetOf(struct _DtTermPrimitiveRec, term.consoleMode),
188 XmRImmediate, (XtPointer) False
191 DtNblinkRate, DtCBlinkRate, XmRInt, sizeof(int),
192 XtOffsetOf(struct _DtTermPrimitiveRec, term.blinkRate),
193 XmRImmediate, (XtPointer) 250
196 DtNbaseWidth, DtCBaseWidth, XmRInt, sizeof(int),
197 XtOffsetOf(struct _DtTermPrimitiveRec, term.baseWidth),
198 XmRImmediate, (XtPointer) 0
201 DtNbaseHeight, DtCBaseHeight, XmRInt, sizeof(int),
202 XtOffsetOf(struct _DtTermPrimitiveRec, term.baseHeight),
203 XmRImmediate, (XtPointer) 0
206 DtNwidthInc, DtCWidthInc, XmRInt, sizeof(int),
207 XtOffsetOf(struct _DtTermPrimitiveRec, term.widthInc),
208 XmRImmediate, (XtPointer) 0
211 DtNheightInc, DtCHeightInc, XmRInt, sizeof(int),
212 XtOffsetOf(struct _DtTermPrimitiveRec, term.heightInc),
213 XmRImmediate, (XtPointer) 0
216 DtNtermDevice, DtCTermDevice, XmRInt, sizeof(int),
217 XtOffsetOf(struct _DtTermPrimitiveRec, term.pty),
218 XmRImmediate, (XtPointer) -1
221 DtNtermDeviceAllocate, DtCTermDeviceAllocate, XmRBoolean,
223 XtOffsetOf(struct _DtTermPrimitiveRec, term.ptyAllocate),
224 XmRImmediate, (XtPointer) True
227 DtNtermSlaveName, DtCTermSlaveName, XmRString, sizeof(char *),
228 XtOffsetOf(struct _DtTermPrimitiveRec, term.ptySlaveName),
229 XmRImmediate, (XtPointer) NULL
232 DtNsaveLines, DtCSaveLines, XmRString, sizeof(char *),
233 XtOffsetOf(struct _DtTermPrimitiveRec, term.saveLines),
234 XmRImmediate, (XtPointer) "4s"
237 DtNrows, DtCRows, XmRShort, sizeof(short),
238 XtOffsetOf(struct _DtTermPrimitiveRec, term.rows),
239 XmRImmediate, (XtPointer) defaultRows
242 DtNcolumns, DtCColumns, XmRShort, sizeof(short),
243 XtOffsetOf(struct _DtTermPrimitiveRec, term.columns),
244 XmRImmediate, (XtPointer) defaultColumns
248 DtNbackgroundIsSelect, DtCBackgroundIsSelect, XmRBoolean,
250 XtOffsetOf(struct _DtTermPrimitiveRec, term.backgroundIsSelect),
251 XtRImmediate, (XtPointer) True
255 DtNbackgroundIsSelect, DtCBackgroundIsSelect, XmRBoolean,
257 XtOffsetOf(struct _DtTermPrimitiveRec, term.backgroundIsSelect),
258 XtRImmediate, (XtPointer) False
262 XmNtraversalOn, XmCTraversalOn, XmRBoolean, sizeof(Boolean),
263 XtOffsetOf(struct _DtTermPrimitiveRec, primitive.traversal_on),
264 XtRImmediate, (XtPointer) True
267 DtNshadowType, DtCShadowType, XmRShadowType, sizeof (unsigned char),
268 XtOffsetOf( struct _DtTermPrimitiveRec, term.shadowType),
269 XmRImmediate, (XtPointer) DtSHADOW_IN
272 XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
274 XtOffsetOf( struct _DtTermPrimitiveRec, primitive.shadow_thickness),
275 XmRCallProc, (XtPointer) setThickness
278 DtNmarginWidth, DtCMarginWidth, XmRHorizontalDimension,
280 XtOffsetOf( struct _DtTermPrimitiveRec, term.marginWidth),
281 XmRImmediate, (XtPointer) 2
284 DtNmarginHeight, DtCMarginHeight, XmRVerticalDimension,
286 XtOffsetOf( struct _DtTermPrimitiveRec, term.marginHeight),
287 XmRImmediate, (XtPointer) 2
290 DtNuserBoldFont, DtCUserBoldFont, XmRFontList,
292 XtOffsetOf( struct _DtTermPrimitiveRec, term.boldFontList),
293 XmRImmediate, (XtPointer) NULL
296 DtNuserFont, DtCUserFont, XmRFontList,
298 XtOffsetOf( struct _DtTermPrimitiveRec, term.fontList),
299 XmRImmediate, (XtPointer) NULL
302 XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
304 XtOffsetOf( struct _DtTermPrimitiveRec, primitive.highlight_thickness),
305 XmRCallProc, (XtPointer) setThickness
308 DtNvisualBell, DtCVisualBell, XmRBoolean, sizeof(Boolean),
309 XtOffsetOf( struct _DtTermPrimitiveRec, term.visualBell),
310 XtRImmediate, (XtPointer) False
313 DtNmarginBell, DtCMarginBell, XmRBoolean, sizeof(Boolean),
314 XtOffsetOf( struct _DtTermPrimitiveRec, term.marginBell),
315 XtRImmediate, (XtPointer) False
318 DtNnMarginBell, DtCNMarginBell, XmRInt, sizeof(int),
319 XtOffsetOf( struct _DtTermPrimitiveRec, term.nMarginBell),
320 XtRImmediate, (XtPointer) 8
323 DtNjumpScroll, DtCJumpScroll, XmRBoolean, sizeof(Boolean),
324 XtOffsetOf( struct _DtTermPrimitiveRec, term.jumpScroll),
325 XtRImmediate, (XtPointer) True
328 DtNsubprocessLoginShell, DtCSubprocessLoginShell, XmRBoolean,
330 XtOffsetOf( struct _DtTermPrimitiveRec, term.subprocessLoginShell),
331 XtRImmediate, (XtPointer) False
334 DtNsubprocessTerminationCallback, DtCCallback, XmRCallback,
335 sizeof(XtCallbackList),
336 XtOffsetOf( struct _DtTermPrimitiveRec, term.subprocessTerminationCallback),
337 XmRPointer, (XtPointer) NULL
340 DtNstatusChangeCallback, DtCCallback, XmRCallback,
341 sizeof(XtCallbackList),
342 XtOffsetOf( struct _DtTermPrimitiveRec, term.statusChangeCallback),
343 XmRPointer, (XtPointer) NULL
346 DtNoutputLogCallback, DtCCallback, XmRCallback,
347 sizeof(XtCallbackList),
348 XtOffsetOf( struct _DtTermPrimitiveRec, term.outputLogCallback),
349 XmRPointer, (XtPointer) NULL
352 DtNinputVerifyCallback, DtCCallback, XmRCallback,
353 sizeof(XtCallbackList),
354 XtOffsetOf( struct _DtTermPrimitiveRec, term.inputVerifyCallback),
355 XmRPointer, (XtPointer) NULL
358 DtNverticalScrollBar, DtCVerticalScrollBar, XmRWidget, sizeof(Widget),
359 XtOffsetOf( struct _DtTermPrimitiveRec, term.verticalScrollBar),
360 XmRImmediate, (XtPointer) NULL
363 DtNsubprocessPid, DtCSubprocessPid, XmRInt, sizeof(int),
364 XtOffsetOf( struct _DtTermPrimitiveRec, term.subprocessPid),
365 XtRImmediate, (XtPointer) -1
368 DtNsubprocessExec, DtCSubprocessExec, XmRBoolean, sizeof(Boolean),
369 XtOffsetOf( struct _DtTermPrimitiveRec, term.subprocessExec),
370 XmRImmediate, (XtPointer) True
373 DtNsubprocessTerminationCatch, DtCSubprocessTerminationCatch,
374 XmRBoolean, sizeof(Boolean),
375 XtOffsetOf( struct _DtTermPrimitiveRec, term.subprocessTerminationCatch),
376 XmRImmediate, (XtPointer) True
379 DtNsubprocessCmd, DtCSubprocessCmd, XmRString, sizeof(char *),
380 XtOffsetOf( struct _DtTermPrimitiveRec, term.subprocessCmd),
381 XtRImmediate, (XtPointer) NULL
384 DtNsubprocessArgv, DtCSubprocessArgv, XtRStringArray, sizeof(String *),
385 XtOffsetOf( struct _DtTermPrimitiveRec, term.subprocessArgv),
386 XmRImmediate, (XtPointer) NULL
389 DtNemulationId, DtCEmulationId, XmRString, sizeof(char *),
390 XtOffsetOf( struct _DtTermPrimitiveRec, term.emulationId),
391 XtRImmediate, (XtPointer) "DtTermPrimitiveWidget"
394 DtNtermId, DtCTermId, XmRString, sizeof(char *),
395 XtOffsetOf( struct _DtTermPrimitiveRec, term.termId),
396 XtRImmediate, (XtPointer) "dumb"
399 DtNtermName, DtCTermName, XmRString, sizeof(char *),
400 XtOffsetOf( struct _DtTermPrimitiveRec, term.termName),
401 XtRImmediate, (XtPointer) "dumb"
404 DtNttyModes, DtCTtyModes, XmRString, sizeof(char *),
405 XtOffsetOf( struct _DtTermPrimitiveRec, term.ttyModes),
406 XtRImmediate, (XtPointer) NULL
409 DtNcsWidth, DtCCsWidth, XmRString, sizeof(char *),
410 XtOffsetOf( struct _DtTermPrimitiveRec, term.csWidth),
411 XtRImmediate, (XtPointer) NULL
414 DtNkshMode, DtCKshMode, XmRBoolean, sizeof(Boolean),
415 XtOffsetOf( struct _DtTermPrimitiveRec, term.kshMode),
416 XtRImmediate, (XtPointer) False
419 DtNpointerBlank, DtCPointerBlank, XmRBoolean, sizeof(Boolean),
420 XtOffsetOf( struct _DtTermPrimitiveRec, term.pointerBlank),
421 XtRImmediate, (XtPointer) False
424 DtNpointerBlankDelay, DtCPointerBlankDelay, XmRInt, sizeof(int),
425 XtOffsetOf( struct _DtTermPrimitiveRec, term.pointerBlankDelay),
426 XtRImmediate, (XtPointer) 2
429 DtNpointerShape, DtCCursor, XtRCursor, sizeof(Cursor),
430 XtOffsetOf( struct _DtTermPrimitiveRec, term.pointerShape),
431 XtRString, (XtPointer) "xterm"
434 DtNpointerColor, DtCForeground, XtRPixel, sizeof(Pixel),
435 XtOffsetOf( struct _DtTermPrimitiveRec, term.pointerColor),
436 XtRString, (XtPointer) "XtDefaultForeground"
439 DtNpointerColorBackground, DtCBackground, XtRPixel, sizeof(Pixel),
440 XtOffsetOf( struct _DtTermPrimitiveRec, term.pointerColorBackground),
441 XtRString, (XtPointer) "XtDefaultBackground"
444 DtNmapOnOutput, DtCMapOnOutput , XmRBoolean, sizeof(Boolean),
445 XtOffsetOf( struct _DtTermPrimitiveRec, term.mapOnOutput ),
446 XtRImmediate, (XtPointer) False
449 DtNmapOnOutputDelay, DtCMapOnOutputDelay, XmRInt, sizeof(int),
450 XtOffsetOf( struct _DtTermPrimitiveRec, term.mapOnOutputDelay ),
451 XtRImmediate, (XtPointer) 0
454 DtNlogging, DtCLogging , XmRBoolean, sizeof(Boolean),
455 XtOffsetOf( struct _DtTermPrimitiveRec, term.logging ),
456 XtRImmediate, (XtPointer) False
459 DtNlogFile, DtCLogFile , XmRString, sizeof(char *),
460 XtOffsetOf( struct _DtTermPrimitiveRec, term.logFile ),
461 XtRImmediate, (XtPointer) NULL
464 DtNlogInhibit, DtCLogInhibit , XmRBoolean, sizeof(Boolean),
465 XtOffsetOf( struct _DtTermPrimitiveRec, term.logInhibit ),
466 XtRImmediate, (XtPointer) False
469 DtNreverseVideo, DtCReverseVideo, XmRBoolean, sizeof(Boolean),
470 XtOffsetOf( struct _DtTermPrimitiveRec, term.reverseVideo ),
471 XtRImmediate, (XtPointer) False
474 DtNallowSendEvents , DtCAllowSendEvents , XmRBoolean, sizeof(Boolean),
475 XtOffsetOf(struct _DtTermPrimitiveRec, term.allowSendEvents),
476 XtRImmediate, (XtPointer) False
481 * Goofy debug'ed code by HP.
482 * IBM's JP kbd accepts Shift+KP_Multiply as a valid key sequence.
483 * I don't know why HP added non-exposed(internal) Xt's action ???
484 * Anyway, remove KP_Multiply entry from defaultTranslations[]
486 static char defaultTranslations[] = "\
487 Ctrl<Key>Cancel: stop(long)\n\
488 ~Ctrl<Key>Cancel: stop()\n\
490 <Key>KP_Tab: tab()\n\
491 <KeyRelease>: key-release()\n\
492 <KeyPress>: insert()\n\
493 ~Shift~Ctrl<Btn1Down>: grab-focus()\n\
494 Shift~Ctrl<Btn1Down>: extend-start()\n\
495 ~Ctrl<Btn1Motion>: select-adjust()\n\
496 ~Ctrl<Btn1Up>: extend-end()\n\
497 ~Shift<Btn2Down>: process-bdrag()\n\
498 ~Shift<Btn2Up>: copy-to()\n\
499 <EnterWindow>: enter()\n\
500 <LeaveWindow>: leave()\n\
501 <FocusIn>: focus-in()\n\
502 <FocusOut>: focus-out()\n\
506 /* global class record for instances of class: TermPrim
509 externaldef(termclassrec) DtTermPrimitiveClassRec dtTermPrimitiveClassRec =
511 /* core class record */
513 /* superclass */ (WidgetClass) &xmPrimitiveClassRec,
514 /* class_name */ "DtTermPrim",
515 /* widget_size */ sizeof(DtTermPrimitiveRec),
516 /* class_initialize */ ClassInitialize,
517 /* class_part_init */ ClassPartInitialize,
518 /* class_inited */ FALSE,
519 /* initialize */ Initialize,
520 /* initialize_hook */ (XtArgsProc) NULL,
521 /* realize */ Realize,
522 /* actions */ actionsList,
523 /* num_actions */ XtNumber(actionsList),
524 /* resources */ resources,
525 /* num_resources */ XtNumber(resources),
526 /* xrm_class */ NULLQUARK,
527 /* compress_motion */ TRUE,
528 /* compress_exposure */ FALSE,
529 /* compress_enterlv */ TRUE,
530 /* visible_interest */ TRUE,
531 /* destroy */ Destroy,
533 /* expose */ Redisplay,
534 /* set_values */ SetValues,
535 /* set_values_hook */ (XtArgsFunc) NULL,
536 /* set_values_almost */ XtInheritSetValuesAlmost,
537 /* get_values_hook */ (XtArgsProc) NULL,
538 /* accept_focus */ (XtAcceptFocusProc) NULL,
539 /* version */ XtVersion,
540 /* callback_private */ (XtPointer) NULL,
541 /* tm_table */ defaultTranslations,
542 /* query_geometry */ (XtGeometryHandler) NULL,
543 /* display_accelerator */ (XtStringProc) NULL,
544 /* extension */ (XtPointer) NULL,
547 /* primitive class record */
549 /* Primitive border_highlight */ XmInheritWidgetProc,
550 /* Primitive border_unhighlight */ XmInheritWidgetProc,
551 /* translations */ "" /*NULL*/ /*XtInheritTranslations*/,
552 /* arm_and_activate */ NULL,
553 /* get resources */ (XmSyntheticResource *) NULL,
554 /* num get_resources */ 0,
555 /* extension */ (XtPointer) NULL,
558 /* term class record */
560 /* parser_start_state */ &_DtTermPrimStateStart,
561 /* use_history_buffer */ False,
562 /* allow_scroll_below_buffer */ False,
563 /* wrap_right_after_insert */ False,
564 /* buffer_create_proc */ _DtTermPrimBufferCreateBuffer,
565 /* buffer_free_proc */ _DtTermPrimBufferFreeBuffer,
566 /* term_insert_proc */ _DtTermPrimInsertText,
567 /* sizeOfBuffer */ (short) sizeof(TermBufferRec),
568 /* sizeOfLine */ (short) sizeof(TermLineRec),
569 /* sizeOfEnh */ (short) sizeof(TermEnhPart),
573 externaldef(termwidgetclass) WidgetClass dtTermPrimitiveWidgetClass =
574 (WidgetClass)&dtTermPrimitiveClassRec;
576 /* Class Initialize...
579 ClassInitialize(void)
581 /* register our resource converters... */
582 (void) _DtTermPrimInitRepTypes();
588 ClassPartInitialize(WidgetClass w_class)
590 (void) DtTermInitialize();
600 ** Make sure the keyboard is unlocked...
602 tpd->keyboardLocked.escape = False;
603 tpd->keyboardLocked.xferPending = False;
604 tpd->keyboardLocked.error = False;
605 tpd->keyboardLocked.record = False;
607 /* other keyboard modes...
609 tpd->autoLineFeed = False;
610 tpd->halfDuplex = False;
614 ** initialize the term-generic straps...
622 tpd->transmitFunctions = False;
623 tpd->autoWrapRight = True;
627 ** initialize the term-generic modes...
635 tpd->scrollLockMode = SCROLL_LOCKoff;
639 ** initialize on the spot data...
647 tpd->onthespot = (OnTheSpotData)XtMalloc(sizeof(OnTheSpotDataRec));
648 tpd->onthespot->start = 0;
649 tpd->onthespot->end = 0;
650 tpd->onthespot->pre_len = 0;
651 tpd->onthespot->cursor = 0;
652 tpd->onthespot->under_preedit = False;
657 _DtTermPrimGetFontSet
665 XmFontContext fontContext;
666 XmFontListEntry fontListEntry;
670 *fontSet = (XFontSet) 0;
671 *font = (XFontStruct *) 0;
673 if (!XmFontListInitFontContext(&fontContext, fontList)) {
674 (void) fprintf(stderr, "XmFontListInitFontContext() failed\n");
678 /* suppress the CodeCenter warning:
679 * "Assignment in conditional 'while' expression."...
682 while (fontListEntry = XmFontListNextEntry(fontContext)) {
683 pointer = XmFontListEntryGetFont(fontListEntry, &fontType);
684 if (fontType == XmFONT_IS_FONTSET) {
690 Debug('f', fprintf(stderr, ">>fontType == XmFONT_IS_FONTSET\n"));
691 *fontSet = (XFontSet) pointer;
692 num_fonts = XFontsOfFontSet(*fontSet, &fonts, &fontNames);
693 for (i = 0; i < num_fonts; i++) {
694 Debug('f', fprintf(stderr, ">> font %d: %s\n", i + 1,
699 Debug('f', fprintf(stderr, ">>fontType != XmFONT_IS_FONTSET\n"));
700 *font = (XFontStruct *) pointer;
701 if (XGetFontProperty(*font, XA_FONT, &ret)) {
702 Debug('f', fprintf(stderr, ">>font: %s\n",
703 XGetAtomName(XtDisplay(w), ret)));
712 char **missingCharsetList;
713 int missingCharsetCount;
715 /* build a fontSet from the font... */
716 if (XGetFontProperty(*font, XA_FONT, &ret)) {
717 fontName = XGetAtomName(XtDisplay(w), ret);
719 *fontSet = XCreateFontSet(XtDisplay(w),
722 &missingCharsetCount,
724 if (missingCharsetCount > 0) {
727 for (i = 0; i < missingCharsetCount; i++)
728 (void) fprintf(stderr, "missing charset in fontset \"%s\"\n",
729 missingCharsetList[i]);
734 /* DKS: at some point, we may want to do something with the other
735 * fonts in the fontList as well...
737 /* free up malloc'ed memory... */
738 (void) XmFontListFreeFontContext(fontContext);
746 XFontSet *retFontSet,
747 XFontStruct **retFont
751 XFontSet fontSet = (XFontSet) 0;
752 XFontStruct *font = (XFontStruct *) 0;
754 /* get our fontset from the fontlist... */
755 (void) _DtTermPrimGetFontSet(w, fontList, &fontSet, &font);
757 /* generate a TermFont from either the fontset or the font... */
759 termFont = _DtTermPrimRenderFontSetCreate(w, fontSet);
761 termFont = _DtTermPrimRenderFontCreate(w, font);
764 /* return the font and fontSet if requested... */
766 *retFontSet = fontSet;
770 /* return the generated font... */
780 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
782 /* let's adjust the units by the base font size... */
783 if (tw->term.fontSet) {
784 XFontSetExtents *fontSetExtents;
790 num_fonts = XFontsOfFontSet(tw->term.fontSet, &fonts, &fontNames);
791 /* look for the single byte font that includes the normal
792 * ascii characters...
794 for (i = 0; i < num_fonts; i++) {
795 if ((fonts[i]->min_byte1 == 0) && (fonts[i]->max_byte1 == 0) &&
796 (fonts[i]->min_char_or_byte2 <= 'A') &&
797 (fonts[i]->max_char_or_byte2 >= 'Z')) {
801 if (i >= num_fonts) {
802 /* look for the multi-bypte font that includes the normal ascii
805 for (i = 0; i < num_fonts; i++) {
806 if (fonts[i]->min_byte1 == 0) {
811 if (i >= num_fonts) {
812 /* as a last resort, just use the first font... */
816 fontSetExtents = XExtentsOfFontSet(tw->term.fontSet);
818 /* build termFont for this fontset... */
819 tw->term.widthInc = fonts[i]->max_bounds.width;
820 tw->term.heightInc = fontSetExtents->max_logical_extent.height;
821 /* why are there two "ascents"? TMH */
822 tw->term.ascent = -fontSetExtents->max_logical_extent.y;
823 tw->term.tpd->ascent = tw->term.ascent;
825 tw->term.tpd->cellWidth = tw->term.widthInc;
826 tw->term.tpd->cellHeight = tw->term.heightInc;
828 tw->term.widthInc = tw->term.font->max_bounds.width;
829 tw->term.heightInc = tw->term.font->ascent + tw->term.font->descent;
830 /* why are there two "ascents"? TMH */
831 tw->term.ascent = tw->term.font->ascent;
832 tw->term.tpd->ascent = tw->term.font->ascent;
834 tw->term.tpd->cellWidth = tw->term.widthInc;
835 tw->term.tpd->cellHeight = tw->term.heightInc;
842 XModifierKeymap *modifierMapping,
843 short *numCapsLockKeyCodes
846 KeyCode *capsLockKeyCodes;
849 /* initialize number of caps lock key codes... */
850 *numCapsLockKeyCodes = 0;
852 /* malloc storage for the keycodes (it will be less than or equal to
855 capsLockKeyCodes = (KeyCode *)
856 XtMalloc(modifierMapping->max_keypermod * sizeof(KeyCode));
858 /* copy them over... */
859 for (i1 = 0; i1 < modifierMapping->max_keypermod; i1++) {
860 capsLockKeyCodes[*numCapsLockKeyCodes] =
861 modifierMapping->modifiermap[LockMapIndex *
862 modifierMapping->max_keypermod + i1];
863 /* only count non-zero keycodes... */
864 if (capsLockKeyCodes[*numCapsLockKeyCodes])
865 (*numCapsLockKeyCodes)++;
868 return(capsLockKeyCodes);
874 XModifierKeymap *modifierMapping,
875 KeySym *keyboardMapping,
876 int keysymsPerKeycode,
882 unsigned int metaMask;
888 /* figure out what modifier corresponds to the meta key.
889 * If there is none, return 0...
891 for (match = False, metaMask = Mod1Mask, mapIndex = Mod1MapIndex;
892 (mapIndex <= Mod5MapIndex) && !match;
893 metaMask <<= 1, mapIndex++) {
894 for (i1 = 0; i1 < modifierMapping->max_keypermod; i1++) {
895 thisKeyCode = modifierMapping->modifiermap[mapIndex *
896 modifierMapping->max_keypermod + i1];
897 thisKeySym = keyboardMapping[(thisKeyCode - minKeycodes) *
899 if ((thisKeySym == XK_Meta_L) || (thisKeySym == XK_Meta_R)) {
900 /* we found either meta_l or meta_r... */
907 /* we found either meta_l or meta_r... */
921 Initialize(Widget ref_w, Widget w, Arg *args, Cardinal *num_args)
923 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
925 XmFontContext fontContext;
926 XmFontListEntry fontListEntry;
928 XModifierKeymap *modifierMapping;
929 KeySym *keyboardMapping;
932 int keysymsPerKeycode;
933 XmRepTypeId shadowTypeID;
936 Debug('T', timeStamp("TermPrim Initialize() starting"));
940 /* we need to insure that everthing is initialized. Let's do a
944 (void) _DtTermPrimToggleSuidRoot(False);
946 /* Widget verticalScrollBar set via setvalues */
947 /* short verticalScrollBarValue */
948 tw->term.verticalScrollBarValue = 0;
950 /* short verticalScrollBarMaximum */
951 tw->term.verticalScrollBarMaximum = 0;
953 /* short verticalScrollBarSliderSize */
954 tw->term.verticalScrollBarSliderSize = 0;
956 /* short verticalScrollBarPageIncrement */
957 tw->term.verticalScrollBarPageIncrement = 0;
959 /* unsigned char charCursorStyle set via setvalues */
960 /* int blinkRate set via setvalues */
961 /* Boolean stickyPrevCursor set via setvalues */
962 /* Boolean stickyNextCursor set via setvalues */
963 /* Boolean backgroundIsSelect set via setvalues */
964 /* Boolean visualBell set via setvalues */
965 /* Boolean marginBell set via setvalues */
966 /* int nMarginBell set via setvalues */
967 /* Boolean jumpScroll set via setvalues */
968 /* Boolean hasFocus */
969 tw->term.hasFocus = False;
971 /* char *termId set via setvalues */
972 /* char *termName set via setvalues */
973 /* char *ttyModes set via setvalues */
974 /* unsigned char shadowType set via setvalues */
975 /* XmFontList fontList set via setvalues */
976 /* XFontStruct *font */
977 tw->term.font = (XFontStruct *) 0;
978 tw->term.boldFont = (XFontStruct *) 0;
980 /* XFontSet fontSet */
981 tw->term.fontSet = (XFontSet) 0;
982 tw->term.boldFontSet = (XFontSet) 0;
984 /* Boolean haveFontSet */
985 tw->term.haveFontSet = False;
987 /* char *saveLines set via setvalues */
988 /* short rows set via setvalues */
989 /* short columns set via setvalues */
990 /* Dimension marginHeight set via setvalues */
991 /* Dimension marginWidth set via setvalues */
992 /* int baseWidth set via setvalues */
993 /* int baseHeight set via setvalues */
994 /* int widthInc set via setvalues */
995 /* int heightInc set via setvalues */
999 /* int pty set via setvalues */
1000 /* int ptyAllocate set via setvalues */
1001 /* char *ptySlaveName set via setvalues */
1002 /* int subprocessPid set via setvalues */
1003 /* char *subprocessCWD */
1004 tw->term.subprocessCWD = (char *) 0;
1006 /* char *subprocessCmd set via setvalues */
1007 /* char **subprocessArgv set via setvalues */
1008 /* Boolean subprocessLoginShell set via setvalues */
1009 /* Boolean subprocessTerminationCatch
1010 set via setvalues */
1011 /* Boolean subprocessExec set via setvalues */
1012 /* _termSubprocId subprocessId */
1013 tw->term.subprocessId = (_termSubprocId) 0;
1015 /* XtCallbackList statusChangeCallback
1016 set via setvalues */
1017 /* XtCallbackList subprocessTerminationCallback
1018 set via setvalues */
1020 /* Boolean allowOsfKeysyms */
1021 tw->term.allowOsfKeysyms = False;
1023 if (tw->term.backgroundIsSelect) {
1024 /* set the background pixel based on the select color... */
1025 (void) XmGetColors(XtScreen(w), w->core.colormap,
1026 tw->core.background_pixel, NULL, NULL, NULL,
1027 &tw->core.background_pixel);
1030 /* malloc terminalData dataspace... */
1031 tw->term.tpd = (DtTermPrimData) malloc(sizeof(DtTermPrimDataRec));
1034 /* clear malloc'ed memory... */
1035 (void) memset(tpd, '\0', sizeof(DtTermPrimDataRec));
1037 /* initialize any of it...
1039 tpd->cursorState = CURSORoff;
1040 tpd->cursorVisible = True;
1041 tpd->IMHasFocus = False;
1042 tpd->IMCursorRow = -1;
1043 tpd->IMCursorColumn = -1;
1046 ** Initialize the keyboard, straps, and modes...
1048 initializeKeyboard(tpd);
1049 initializeModes(tpd);
1050 initializeStraps(tpd);
1053 /* initialize scroll variables...
1056 tpd->useHistoryBuffer = ((DtTermPrimitiveClassRec *) (tw->core.widget_class))->
1057 term_primitive_class.use_history_buffer;
1058 tpd->allowScrollBelowBuffer = ((DtTermPrimitiveClassRec *) (tw->core.widget_class))->
1059 term_primitive_class.allow_scroll_below_buffer;
1060 tpd->wrapRightAfterInsert = ((DtTermPrimitiveClassRec *) (tw->core.widget_class))->
1061 term_primitive_class.wrap_right_after_insert;
1063 /* initialize pending text... */
1064 tpd->pendingRead = _DtTermPrimPendingTextCreate();
1065 tpd->pendingWrite = _DtTermPrimPendingTextCreate();
1068 ** Initialize the utmp stuff...
1070 _DtTermPrimUtmpInit(w);
1073 ** Initialize the selection inforamtion
1075 tpd->selectInfo = _DtTermPrimSelectCreate(w);
1077 /* force unit type to pixels... */
1078 tw->primitive.unit_type = XmPIXELS;
1080 /* we have a fontlist. Get a fontset from it if we can, else get a
1081 * fontstruct and make a fontset if we can...
1083 /* get the text default fontlist if we don't have one... */
1084 if (!tw->term.fontList) {
1085 tw->term.fontList = XmeGetDefaultRenderTable(w, XmTEXT_FONTLIST);
1088 tpd->termFont = CreateRenderFont(w, tw->term.fontList,
1089 &tw->term.fontSet, &tw->term.font);
1091 if (tw->term.boldFontList) {
1092 tpd->boldTermFont = CreateRenderFont(w, tw->term.boldFontList,
1093 &tw->term.boldFontSet, &tw->term.boldFont);
1095 /* let's try and build a bold fontlist off of the base fontlist... */
1096 if (tw->term.fontSet) {
1098 XFontStruct **fonts;
1100 char boldFontNames[BUFSIZ];
1105 char **missingCharsetList;
1106 int missingCharsetCount;
1108 Debug('f', fprintf(stderr, ">>generating bold fontset\n"));
1109 num_fonts = XFontsOfFontSet(tw->term.fontSet, &fonts, &fontNames);
1110 for (i1 = 0, c2 = boldFontNames; i1 < num_fonts; i1++) {
1111 /* if this is not the first name we need a comma to
1112 * separate the names...
1119 /* copy over the first 3 fields... */
1120 for (c1 = fontNames[i1], i2 = 0; (i2 < 3) && *c1; i2++) {
1121 while (*c1 && (*c1 != '-')) {
1127 /* copy over the '-'... */
1130 /* make boldFont bold by swapping the bold in for the
1133 (void) strcpy(c2, "bold");
1134 c2 += strlen("bold");
1136 /* skip over the weight in the source... */
1137 while (*c1 && (*c1 != '-')) {
1141 /* copy over the rest of the fontname... */
1150 /* now create the fontset... */
1151 tw->term.boldFontSet = XCreateFontSet(XtDisplay(w),
1153 &missingCharsetList,
1154 &missingCharsetCount,
1156 if (missingCharsetCount > 0) {
1159 for (i = 0; i < missingCharsetCount; i++)
1160 Debug('f', fprintf(stderr,
1161 ">>missing charsets in boldfont \"%s\"\n",
1162 missingCharsetList[i]));
1163 (void) XFreeStringList(missingCharsetList);
1164 if (tw->term.boldFontSet) {
1165 (void) XFreeFontSet(XtDisplay(w), tw->term.boldFontSet);
1166 tw->term.boldFontSet = (XFontSet) 0;
1170 /* create a bold render font... */
1171 if (tw->term.boldFontSet) {
1173 _DtTermPrimRenderFontSetCreate(w, tw->term.boldFontSet);
1175 } else if (tw->term.font) {
1178 char boldFontName[BUFSIZ];
1183 /* get the fontname associated with the font... */
1184 if (XGetFontProperty(tw->term.font, XA_FONT, &ret)) {
1185 fontName = XGetAtomName(XtDisplay(w), ret);
1186 /* copy over the first 3 fields... */
1187 for (c1 = fontName, c2 = boldFontName, i2 = 0;
1188 (i2 < 3) && *c1; i2++) {
1189 while (*c1 && (*c1 != '-')) {
1195 /* copy over the '-'... */
1198 /* make boldFont bold by swapping the bold in for the
1201 (void) strcpy(c2, "bold");
1202 c2 += strlen("bold");
1204 /* skip over the weight in the source... */
1205 while (*c1 && (*c1 != '-')) {
1209 /* copy over the rest of the fontname... */
1214 /* null term the string... */
1217 tw->term.boldFont = XLoadQueryFont(XtDisplay(w), boldFontName);
1218 /* create a bold render font... */
1219 if (tw->term.boldFont) {
1221 _DtTermPrimRenderFontCreate(w, tw->term.boldFont);
1223 if (fontName) XFree(fontName) ;
1228 /* save away our original fonts as defaults... */
1229 tpd->defaultTermFont = tpd->termFont;
1230 tpd->defaultBoldTermFont = tpd->boldTermFont;
1232 /* look through our XFontSet or XFontStruct and adjust our
1233 * width and height increments...
1235 (void) AdjustWindowUnits(w);
1237 /* initialize the base width/height... */
1238 tw->term.baseWidth = 2 * (tw->primitive.shadow_thickness +
1239 tw->primitive.highlight_thickness + tw->term.marginWidth);
1240 tw->term.baseHeight = 2 * (tw->primitive.shadow_thickness +
1241 tw->primitive.highlight_thickness + tw->term.marginHeight);
1243 /* adjust width and height by rows/columns and the font size... */
1245 tw->term.columns * tw->term.widthInc + tw->term.baseWidth;
1247 tw->term.rows * tw->term.heightInc + tw->term.baseHeight;
1248 Debug('w', fprintf(stderr, ">>core.width=%u\n", tw->core.width));
1249 Debug('w', fprintf(stderr, ">>core.height=%u\n", tw->core.height));
1251 /* set the termData fields... */
1252 (void) _DtTermPrimParserInitContext(w);
1253 tpd->parserNotInStartState = False;
1254 tpd->offsetX = tw->primitive.shadow_thickness +
1255 tw->primitive.highlight_thickness + tw->term.marginWidth;
1256 tpd->offsetY = tw->primitive.shadow_thickness +
1257 tw->primitive.highlight_thickness + tw->term.marginHeight;
1258 tpd->cellWidth = tw->term.widthInc;
1259 tpd->cellHeight = tw->term.heightInc;
1260 tpd->ascent = tw->term.ascent;
1261 tpd->windowMapped = False ;
1262 time( &tpd->creationTime) ;
1263 if (tw->term.pointerBlank) tpd->pointerFirst = True ;
1265 /* multi-byte specific fields...
1267 tpd->mbCurMax = MB_CUR_MAX;
1268 /* use a debug flag to force ourselves into multi-byte
1269 * mode for single byte locales...
1271 DebugF('m', 1, tpd->mbCurMax = MB_LEN_MAX);
1272 tpd->mbPartialCharLen = 0; /* no pending partial multi-byte char */
1274 /* check results of type converters... */
1275 shadowTypeID = XmRepTypeGetId(XmRShadowType);
1276 if (shadowTypeID != XmREP_TYPE_INVALID) {
1277 if (!XmRepTypeValidValue(shadowTypeID, tw->term.shadowType, w))
1278 tw->term.shadowType = DtSHADOW_IN;
1281 /* get the keyboard modifier mapping... */
1282 modifierMapping = XGetModifierMapping(XtDisplay(w));
1283 (void) XDisplayKeycodes(XtDisplay(w), &minKeycodes, &maxKeycodes);
1284 keyboardMapping = XGetKeyboardMapping(XtDisplay(w), minKeycodes,
1285 maxKeycodes - minKeycodes + 1, &keysymsPerKeycode);
1287 /* get the caps lock keycodes... */
1288 tpd->capsLockKeyCodes = GetCapsLockKeyCodes(modifierMapping,
1289 &tpd->numCapsLockKeyCodes);
1291 /* get the modifier bit that corresponds to meta.
1292 * If there is none, use mod1...
1294 tpd->metaMask = GetMetaMask(modifierMapping, keyboardMapping,
1295 keysymsPerKeycode, minKeycodes, maxKeycodes);
1296 if (!tpd->metaMask) {
1297 /* default to mod1... */
1298 tpd->metaMask = Mod1Mask;
1301 (void) XFree(keyboardMapping);
1302 (void) XFreeModifiermap(modifierMapping);
1304 (void) XtAddEventHandler(w,
1305 (EventMask) KeyPressMask | KeyReleaseMask,
1306 False, handleKeyEvents, (Opaque) NULL);
1307 (void) XtAddEventHandler(w,
1308 (EventMask) ButtonPressMask | ButtonReleaseMask,
1309 False, handleButtonEvents, (Opaque) NULL);
1310 (void) XtAddEventHandler(w,
1312 True, handleNonMaskableEvents, (Opaque) NULL);
1316 for (sw = w; !XtIsShell(sw); sw = XtParent(sw))
1318 (void) XtAddEventHandler(sw, (EventMask) StructureNotifyMask,
1319 False, handleProcessStructureNotifyEvent, (Opaque) w);
1320 (void) XtAddEventHandler(sw, (EventMask) PropertyChangeMask,
1321 False, handlePropertyChangeEvents, (Opaque) w);
1324 if (tw->term.verticalScrollBar) {
1325 /* set up the callbacks for the scrollbar... */
1326 (void) InitializeVerticalScrollBar(w, True);
1329 tw->term.log_on = False ;
1330 if (tw->term.logging) {
1331 _DtTermPrimStartLog(tw) ;
1334 Debug('T', timeStamp("TermPrim Initialize() finished"));
1339 InitializeVerticalScrollBar(Widget w, Boolean initCallbacks)
1341 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
1342 DtTermPrimData tpd = tw->term.tpd;
1347 if (initCallbacks) {
1348 /* set up the scrollbar callbacks... */
1350 (void) XtAddCallback(tw->term.verticalScrollBar, XmNdecrementCallback,
1351 VerticalScrollBarCallback, (XtPointer) w);
1352 (void) XtAddCallback(tw->term.verticalScrollBar, XmNincrementCallback,
1353 VerticalScrollBarCallback, (XtPointer) w);
1355 (void) XtAddCallback(tw->term.verticalScrollBar,
1356 XmNpageDecrementCallback,
1357 VerticalScrollBarCallback, (XtPointer) w);
1358 (void) XtAddCallback(tw->term.verticalScrollBar,
1359 XmNpageIncrementCallback,
1360 VerticalScrollBarCallback, (XtPointer) w);
1362 (void) XtAddCallback(tw->term.verticalScrollBar,
1363 XmNtoTopCallback, VerticalScrollBarCallback, (XtPointer) w);
1364 (void) XtAddCallback(tw->term.verticalScrollBar,
1365 XmNtoBottomCallback, VerticalScrollBarCallback, (XtPointer) w);
1368 (void) XtAddCallback(tw->term.verticalScrollBar, XmNdragCallback,
1369 VerticalScrollBarCallback, (XtPointer) w);
1370 (void) XtAddCallback(tw->term.verticalScrollBar,
1371 XmNvalueChangedCallback, VerticalScrollBarCallback,
1375 if (!tpd->termBuffer) {
1376 /* no termBuffer yet, we set anything yet... */
1380 /* update the scrollbar... */
1381 if (tw->term.verticalScrollBar) {
1382 /* we can scroll the height of the history buffer and the
1383 * number of used rows less the protected areas...
1385 if (tpd->useHistoryBuffer) {
1386 #define NO_SCROLL_REGION_HISTORY_SCROLL
1387 #ifdef NO_SCROLL_REGION_HISTORY_SCROLL
1388 tw->term.verticalScrollBarMaximum = tw->term.rows;
1389 if ((tpd->scrollLockTopRow <= 0) &&
1390 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
1391 tw->term.verticalScrollBarMaximum += tpd->lastUsedHistoryRow;
1393 #else /* NO_SCROLL_REGION_HISTORY_SCROLL */
1394 tw->term.verticalScrollBarMaximum = tw->term.rows +
1395 tpd->lastUsedHistoryRow;
1396 #endif /* NO_SCROLL_REGION_HISTORY_SCROLL */
1398 tw->term.verticalScrollBarMaximum = tpd->lastUsedRow +
1399 tpd->scrollLockTopRow -
1400 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
1402 /* add in any non-existent rows below the last used row...
1404 if (tpd->allowScrollBelowBuffer) {
1405 /* add in a full screen (less one line and protected areas)
1406 * below the last used row...
1408 tw->term.verticalScrollBarMaximum += tw->term.rows - 1 -
1409 tpd->scrollLockTopRow -
1410 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
1414 if (tpd->useHistoryBuffer) {
1415 tw->term.verticalScrollBarSliderSize = tw->term.rows;
1417 tw->term.verticalScrollBarSliderSize =
1418 tw->term.rows - tpd->scrollLockTopRow -
1419 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
1422 tw->term.verticalScrollBarPageIncrement =
1423 tw->term.verticalScrollBarSliderSize;
1425 #ifdef NO_SCROLL_REGION_HISTORY_SCROLL
1426 tw->term.verticalScrollBarValue = tpd->topRow;
1427 if (tpd->useHistoryBuffer && (tpd->scrollLockTopRow <= 0) &&
1428 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
1429 tw->term.verticalScrollBarValue += tpd->lastUsedHistoryRow;
1431 #else /* NO_SCROLL_REGION_HISTORY_SCROLL */
1432 tw->term.verticalScrollBarValue = tpd->topRow + tpd->lastUsedHistoryRow;
1433 #endif /* NO_SCROLL_REGION_HISTORY_SCROLL */
1436 (void) XtSetArg(arglist[i], XmNincrement, 1); i++;
1437 (void) XtSetArg(arglist[i], XmNminimum, 0); i++;
1438 (void) XtSetArg(arglist[i], XmNmaximum,
1439 tw->term.verticalScrollBarMaximum); i++;
1440 (void) XtSetArg(arglist[i], XmNpageIncrement,
1441 tw->term.verticalScrollBarPageIncrement); i++;
1442 (void) XtSetArg(arglist[i], XmNsliderSize,
1443 tw->term.verticalScrollBarSliderSize); i++;
1444 (void) XtSetArg(arglist[i], XmNvalue, tw->term.verticalScrollBarValue);
1446 (void) XtSetValues(tw->term.verticalScrollBar, arglist, i);
1448 Debug('b', fprintf(stderr,
1449 "InitializeVerticalScrollBar: sb size=%d min=%d max=%d value=%d pginc=%d\n",
1450 tw->term.verticalScrollBarSliderSize,
1452 tw->term.verticalScrollBarMaximum,
1453 tw->term.verticalScrollBarValue,
1454 tw->term.verticalScrollBarPageIncrement));
1459 InitOrResizeTermBuffer(Widget w)
1461 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
1462 DtTermPrimData tpd = tw->term.tpd;
1463 DtTermPrimitiveClassPart *termClassPart = &(((DtTermPrimitiveClassRec *)
1464 (tw->core.widget_class))->term_primitive_class);
1471 short newBufferRows = tpd->bufferRows;
1472 short newHistoryBufferRows = tpd->historyBufferRows;
1474 int historyLinesNeeded;
1476 Boolean resizeTermBuffer;
1477 Boolean updateWindowSize = False;
1479 /* set rows and columns... */
1480 newColumns = MAX(1, ((int)(tw->core.width - (2 * (tw->primitive.shadow_thickness +
1481 tw->primitive.highlight_thickness + tw->term.marginWidth)))) /
1483 newRows = MAX(1, ((int)(tw->core.height - (2 * (tw->primitive.shadow_thickness +
1484 tw->primitive.highlight_thickness + tw->term.marginHeight)))) /
1485 tw->term.heightInc);
1487 if ((newColumns == tw->term.columns) && (newRows == tw->term.rows) &&
1489 /* we already have a buffer and the size didn't change so,
1495 /* resize/create the term buffer... */
1496 if (tpd->termBuffer) {
1497 /* restore the buffer-to-window ratio of our off-window buffer
1498 * is less than 75% of the original off-window buffer...
1500 if (tpd->useHistoryBuffer) {
1501 if ((100 * (tpd->bufferRows + tpd->historyBufferRows) /
1502 newRows) < ((75 * tpd->bufferRowRatio) / 100)) {
1503 newBufferRows = (tpd->bufferRowRatio * newRows) / 100;
1504 newHistoryBufferRows = newBufferRows - newRows;
1505 newBufferRows = newRows;
1507 /* the buffer needs to be the length of the window... */
1508 newBufferRows = newRows;
1511 if ((100 * tpd->bufferRows / newRows) <
1512 ((75 * tpd->bufferRowRatio) / 100)) {
1513 newBufferRows = (tpd->bufferRowRatio * newRows) / 100;
1517 /* it needs to be at least the size of the window...
1519 if (newBufferRows < newRows) {
1520 newBufferRows = newRows;
1523 resizeTermBuffer = True; /* until further notice */
1525 if (tpd->useHistoryBuffer && tpd->historyBufferRows > 0 )
1528 ** if we are using a history buffer and have scrolled
1529 ** into it, we need to snap back down before we do
1532 if (tpd->topRow < 0)
1534 (void) _DtTermPrimScrollTextTo((Widget) tw, 0);
1537 /* resize the history buffer first so that we can scroll
1538 * data from the active buffer into it (if necessary) without
1539 * loosing any data...
1542 if ((newHistoryBufferRows > tpd->historyBufferRows) ||
1543 (newColumns != tw->term.columns))
1545 reqRows = newHistoryBufferRows;
1546 reqColumns = newColumns;
1548 _DtTermPrimBufferResizeBuffer(&tpd->historyBuffer, &reqRows,
1551 if ((reqColumns < newColumns) ||
1552 (reqRows < newHistoryBufferRows))
1555 ** we ran out of memory when we tried to resize the
1556 ** history buffer, make the necessary adjustments
1558 newColumns = reqColumns;
1559 newHistoryBufferRows = reqRows;
1562 ** we ran out of memory, no need try and resize the
1565 resizeTermBuffer == False;
1569 if (resizeTermBuffer)
1571 if (newBufferRows < tpd->bufferRows)
1573 /* we are shrinking the window. The first choice is to
1574 * move lines above the cursor into the history buffer so
1575 * that we don't loose any lines in the window. If there
1576 * are not enough lines above the cursor, we will drop
1577 * some of the lines off the bottom of the window...
1579 linesNeeded = tpd->bufferRows - newBufferRows;
1581 /* clip this by the number of lines above the cursor... */
1582 if (linesNeeded > tpd->cursorRow)
1584 linesNeeded = tpd->cursorRow;
1587 historyLinesNeeded = linesNeeded - (newHistoryBufferRows -
1588 tpd->lastUsedHistoryRow);
1590 if (historyLinesNeeded > 0) {
1591 /* take them from the top of the history buffer... */
1592 (void) _DtTermPrimBufferInsertLineFromTB(
1593 tpd->historyBuffer, tpd->historyBufferRows - 1,
1594 historyLinesNeeded, insertFromTop);
1595 /* adjust everything... */
1596 tpd->lastUsedHistoryRow -= historyLinesNeeded;
1599 /* copy the lines over... */
1600 for (i1 = 0; i1 < linesNeeded; i1++) {
1603 termChar *overflowChars;
1604 short overflowCount;
1606 /* get the line from the active buffer... */
1607 length = _DtTermPrimBufferGetLineLength(tpd->termBuffer,
1609 c1 = _DtTermPrimBufferGetCharacterPointer(tpd->termBuffer,
1612 /* stuff it into the history buffer... */
1613 (void) _DtTermPrimBufferSetLineWidth(tpd->historyBuffer,
1614 tpd->lastUsedHistoryRow,
1616 overflowChars = (termChar *) XtMalloc(BUFSIZ * sizeof (termChar));
1617 (void) _DtTermPrimBufferInsert(tpd->historyBuffer,
1618 tpd->lastUsedHistoryRow,
1619 0, c1, length, False,
1622 (void) tpd->lastUsedHistoryRow++;
1623 (void) XtFree((char *) overflowChars);
1626 /* scroll up the active buffer... */
1627 if (linesNeeded > 0) {
1628 (void) _DtTermPrimBufferInsertLineFromTB(tpd->termBuffer,
1629 tpd->bufferRows - 1,
1632 /* adjust everything... */
1633 tpd->cursorRow -= linesNeeded;
1637 if ((newBufferRows != tpd->bufferRows) ||
1638 (newColumns != tw->term.columns))
1640 reqRows = newBufferRows;
1641 reqColumns = newColumns;
1643 _DtTermPrimBufferResizeBuffer(&tpd->termBuffer, &reqRows,
1645 if ((reqColumns < newColumns) || (reqRows < newBufferRows))
1648 ** we ran out of memory, resize the history buffer
1649 ** to the same width as the terminal buffer,
1650 ** and assume we will succeed...
1652 newColumns = reqColumns;
1653 reqRows = newHistoryBufferRows;
1655 _DtTermPrimBufferResizeBuffer(&tpd->historyBuffer,
1656 &reqRows, &reqColumns);
1657 newBufferRows = reqRows;
1661 tpd->historyBufferRows = newHistoryBufferRows;
1662 tpd->bufferRows = newBufferRows;
1667 ** no history buffer to worry about...
1669 _DtTermPrimBufferResizeBuffer(&tpd->termBuffer, &newBufferRows,
1671 tpd->bufferRows = newBufferRows;
1675 ** on the slight chance that the buffer shrank...
1677 newBufferRows = MIN(newBufferRows, newRows);
1680 ** if we added rows, then malloc a new set of scrollRefreshRows...
1682 if (newBufferRows > tw->term.rows)
1684 (void) XtFree(tpd->scrollRefreshRows);
1685 tpd->scrollRefreshRows = (Boolean *) XtMalloc(newBufferRows *
1687 (void) memset(tpd->scrollRefreshRows, '\0', newBufferRows *
1691 /* we got this far because we changed the buffer size. We
1692 * will have to update the winsize structure...
1694 updateWindowSize = True;
1696 tw->term.rows = newBufferRows;
1697 tw->term.columns = newColumns;
1698 if (tpd->lastUsedRow > newRows)
1699 tpd->lastUsedRow = newRows;
1701 /* adjust the insert point if necessary... */
1702 if (tpd->cursorColumn > tw->term.columns - 1)
1703 tpd->cursorColumn = tw->term.columns - 1;
1704 if (tpd->cursorRow > tw->term.rows - 1)
1705 tpd->cursorRow = tw->term.rows - 1;
1708 #ifdef SET_WINDOW_SIZE_ONLY_IF_CHANGED
1709 /* if our rows and columns changed, we will have to update
1710 * the winsize structure...
1712 if ((tw->term.rows != newRows) || (tw->term.columns != newColumns)) {
1713 updateWindowSize = True;
1715 #else /* SET_WINDOW_SIZE_ONLY_IF_CHANGED */
1716 /* we always need to update the winsize structure since it will not
1717 * be done for us via $LINES and $COLUMNS...
1719 updateWindowSize = True;
1720 #endif /* SET_WINDOW_SIZE_ONLY_IF_CHANGED */
1722 tw->term.rows = newRows;
1723 tw->term.columns = newColumns;
1725 /* this is the first time and we need to figure out our ratio for
1726 * future resizing...
1728 if (tw->term.saveLines && *tw->term.saveLines) {
1729 lines = strtol(tw->term.saveLines, &c, 0);
1730 if (c && (*c == 's')) {
1731 /* in terms of screens... */
1732 tpd->bufferRows = (lines + 1) * tw->term.rows;
1734 tpd->bufferRows = (lines + tw->term.rows);
1737 tpd->bufferRows = 2 * tw->term.rows;
1740 /* calculate the buffer ratio from bufferRows and rows... */
1741 tpd->bufferRowRatio = (100 * tpd->bufferRows) / tw->term.rows;
1743 if (tpd->useHistoryBuffer) {
1744 /* split up the buffer between the active and history buffers...
1746 tpd->historyBufferRows = tpd->bufferRows - tw->term.rows;
1747 tpd->bufferRows = tw->term.rows;
1750 /* allocate the two buffers... */
1751 tpd->termBuffer = (*(termClassPart->buffer_create_proc))(
1755 termClassPart->sizeOfBuffer,
1756 termClassPart->sizeOfLine,
1757 termClassPart->sizeOfEnh);
1758 if (tpd->useHistoryBuffer) {
1759 tpd->historyBuffer = (*(termClassPart->buffer_create_proc))(
1761 tpd->historyBufferRows,
1763 termClassPart->sizeOfBuffer,
1764 termClassPart->sizeOfLine,
1765 termClassPart->sizeOfEnh);
1766 (void) _DtTermPrimBufferSetLinks(tpd->termBuffer,
1769 (void) _DtTermPrimBufferSetLinks(tpd->historyBuffer,
1774 /* check for error... */
1775 if (!tpd->termBuffer ||
1776 (tpd->useHistoryBuffer && !tpd->historyBuffer)) {
1777 /*DKS: this needs to be cleaned up... */
1778 (void) fprintf(stderr, "unable to create termBuffer\n");
1782 /* malloc a set of scrollRefreshRows... */
1783 tpd->scrollRefreshRows = (Boolean *) XtMalloc(tw->term.rows *
1785 (void) memset(tpd->scrollRefreshRows, '\0', tw->term.rows *
1788 /* now that we have a term buffer, we can set up our input selector
1789 * on our input source (pty or whatever)...
1791 (void) _DtTermPrimStartOrStopPtyInput(w);
1792 /* initialize the insertion point... */
1793 tpd->cursorColumn = 0;
1796 tpd->lastUsedRow = 1;
1797 tpd->lastUsedHistoryRow = 0;
1801 ** Resize (or creation) is complete, now update the relevant
1804 ** reset scroll lock...
1806 tpd->scrollLockMode = SCROLL_LOCKoff;
1807 tpd->scrollLockTopRow = 0;
1808 tpd->scrollLockBottomRow = newRows - 1;
1810 /* set the rows and columns for the terminal... */
1811 if ((tw->term.pty >= 0) && (updateWindowSize)) {
1812 (void) _DtTermPrimPtySetWindowSize(tw->term.pty,
1813 newColumns * tw->term.widthInc +
1814 (2 * (tw->primitive.shadow_thickness +
1815 tw->primitive.highlight_thickness +
1816 tw->term.marginWidth)),
1817 newRows * tw->term.heightInc +
1818 (2 * (tw->primitive.shadow_thickness +
1819 tw->primitive.highlight_thickness +
1820 tw->term.marginHeight)),
1821 newRows, newColumns);
1824 /* reset margins... */
1825 tpd->leftMargin = 0;
1826 tpd->rightMargin = newColumns - 1;
1828 (void) InitializeVerticalScrollBar(w, False);
1830 _DtTermPrimSelectResize(w) ;
1836 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
1838 if (XtIsRealized(w)) {
1839 /* the first time through, if our size is changed during interactive
1840 * placement, we will be called before redisplay and we will be
1841 * initializing the buffer. If we are sized to our requested size,
1842 * the resize function will not be called...
1844 (void) InitOrResizeTermBuffer(w);
1851 Redisplay(Widget w, XEvent *event, Region region)
1853 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
1854 /* if this is the first time we are exposed, and we have never had our
1855 * size changed (i.e., no Resize() invoked), then we need to initialize
1856 * a few things, so let's force a resize...
1858 if (XtIsRealized(w)) {
1859 if (!tw->term.tpd->termBuffer) {
1860 InitOrResizeTermBuffer(w);
1863 Debug('e', fprintf(stderr,
1864 ">>Redisplay() expose.x=%d .y=%d .width=%d .height=%d\n",
1865 event->xexpose.x, event->xexpose.y, event->xexpose.width,
1866 event->xexpose.height));
1868 (void) _DtTermPrimDrawShadow(w);
1870 /* expose (refresh) the text... */
1871 _DtTermPrimCursorOff(w);
1872 (void) _DtTermPrimExposeText(w, event->xexpose.x, event->xexpose.y,
1873 event->xexpose.width, event->xexpose.height, True);
1874 if (event->xexpose.count == 0)
1875 _DtTermPrimCursorOn(w);
1877 /* Envelop our superclass expose method */
1878 (*(xmPrimitiveClassRec.core_class.expose)) (w, event, region);
1884 handleNonMaskableEvents(Widget w, XtPointer eventData, XEvent *event,
1887 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
1888 DtTermPrimData tpd = tw->term.tpd;
1889 unsigned char *buffer = (unsigned char *) 0;
1890 int fd = tw->term.pty;
1892 switch (event->type) {
1893 case GraphicsExpose:
1895 if (!tw->term.jumpScroll && tpd->scroll.nojump.scrollPending) {
1897 (void) _DtTermPrimExposeText(w, event->xexpose.x, event->xexpose.y,
1898 event->xexpose.width, event->xexpose.height, False);
1902 if (event->xgraphicsexpose.count > 0)
1904 /* else fall through to noexpose... */
1907 /* clear the scroll flag... */
1908 tpd->scrollInProgress = False;
1910 if (tpd->scroll.nojump.pendingScroll) {
1911 (void) _DtTermPrimScrollComplete(w, False);
1914 /* process any pending input... */
1915 if (TextIsPending(tpd->pendingRead)) {
1916 (void) readPty((XtPointer) w, &fd, &tpd->ptyInputId);
1919 /* reinstall the pty input select... */
1920 (void) _DtTermPrimStartOrStopPtyInput(w);
1922 /* free the old buffer... */
1924 (void) XtFree((char *) buffer);
1927 if ((tpd->scroll.nojump.pendingScroll == 0) &&
1928 !moreInput(tw->term.pty)) {
1929 /* turn the cursor back on... */
1930 (void) _DtTermPrimCursorOn(w);
1937 handleProcessStructureNotifyEvent(Widget w, XtPointer eventData, XEvent *event,
1940 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) eventData;
1941 DtTermPrimData tpd = tw->term.tpd;
1943 switch (event->type) {
1945 tpd->windowMapped = True;
1946 if (tpd->mapWarningDialog && tpd->warningDialog) {
1947 (void) XtManageChild(tpd->warningDialog);
1948 tpd->warningDialogMapped = True;
1949 tpd->mapWarningDialog = False;
1954 tpd->windowMapped = False;
1961 handlePropertyChangeEvents(Widget w, XtPointer eventData, XEvent *event,
1964 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) eventData;
1965 static Boolean firstTime = True;
1966 static Atom xa_WM_STATE = None;
1967 struct _wmStateStruct {
1973 unsigned long nItems;
1974 unsigned long bytesAfter;
1978 fprintf(stderr, "handlePropertyChangeEvents() starting\n"));
1979 /* initialize things... */
1980 _DtTermProcessLock();
1982 xa_WM_STATE = XInternAtom(XtDisplay(w), "WM_STATE", True);
1985 _DtTermProcessUnlock();
1988 fprintf(stderr, "event == %s\n",
1989 XGetAtomName(((XPropertyEvent *) event)->display,
1990 ((XPropertyEvent *) event)->atom)));
1991 /* is this a WM_STATE property change?... */
1992 if (((XPropertyEvent *) event)->atom == xa_WM_STATE) {
1993 /* if we have not yet initialized the buffer (and started listening
1994 * to the pty), then let's see if we are iconfied and do so...
1996 if (!tw->term.tpd->termBuffer) {
1997 if (Success == XGetWindowProperty(
1998 ((XPropertyEvent *) event)->display,
1999 ((XPropertyEvent *) event)->window,
2002 (sizeof(struct _wmStateStruct) + 3) / 4,
2009 (unsigned char **) &prop)) {
2010 if ((int) prop->state == IconicState) {
2012 fprintf(stderr, "event == IconicState\n"));
2013 InitOrResizeTermBuffer((Widget) tw);
2020 fprintf(stderr, "handlePropertyChangeEvents() finished\n"));
2025 InvokeTerminationCallback(Widget w, pid_t pid, int *stat_loc)
2027 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
2028 DtTermSubprocessTerminationCallbackStruct cb;
2030 (void) memset(&cb, '\0', sizeof(cb));
2031 cb.reason = DtCR_TERM_SUBPROCESS_TERMINATION;
2032 cb.event = (XEvent *) 0;
2034 cb.status = *stat_loc;
2036 if (tw->term.subprocessTerminationCallback) {
2037 (void) XtCallCallbackList(w,
2038 tw->term.subprocessTerminationCallback, (XtPointer) &cb);
2046 SetValues(Widget cur_w, Widget ref_w, Widget w, ArgList args,
2049 DtTermPrimitiveWidget cur_tw = (DtTermPrimitiveWidget) cur_w;
2050 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
2051 Boolean flag = False; /* return value... */
2053 /* DKS: this needs to be done later...
2056 /* install/remove/modify the subprocess callback process... */
2057 if (cur_tw->term.subprocessPid != tw->term.subprocessPid) {
2058 /* if there was an old handler... */
2059 if (tw->term.subprocessId) {
2060 /* remove the old handler... */
2061 (void) _DtTermPrimSubprocRemoveSubproc(w, tw->term.subprocessId);
2062 tw->term.subprocessId = (_termSubprocId) 0;
2065 /* if there is a new handler... */
2066 if (tw->term.subprocessPid) {
2067 /* add it old handler... */
2068 tw->term.subprocessId = _DtTermPrimAddSubproc(w,
2069 tw->term.subprocessPid, InvokeTerminationCallback, NULL);
2071 /* now that we have a handler, we may need to invoke it... */
2072 if (tw->term.subprocessTerminationCatch) {
2073 (void) _DtTermPrimSetChildSignalHandler();
2078 if (cur_tw->term.jumpScroll != tw->term.jumpScroll) {
2079 /* we need to sync up the scroll before we make the change... */
2080 Boolean newJumpScroll = tw->term.jumpScroll;
2082 tw->term.jumpScroll = cur_tw->term.jumpScroll;
2083 (void) _DtTermPrimScrollComplete(w, True);
2084 tw->term.jumpScroll = newJumpScroll;
2087 if (cur_tw->term.verticalScrollBar != tw->term.verticalScrollBar) {
2088 if (tw->term.verticalScrollBar) {
2089 /* set up the scrollbar values and callbacks... */
2090 (void) InitializeVerticalScrollBar(w, True);
2094 /* change in rows or columns... */
2095 if ((cur_tw->term.rows != tw->term.rows) ||
2096 (cur_tw->term.columns != tw->term.columns)) {
2097 XtWidgetGeometry request;
2098 XtWidgetGeometry reply;
2100 request.request_mode = (XtGeometryMask) 0;
2102 /* handle changes in rows... */
2103 if (cur_tw->term.rows != tw->term.rows) {
2104 request.height = tw->term.rows * tw->term.heightInc +
2105 2 * (tw->primitive.shadow_thickness +
2106 tw->primitive.highlight_thickness + tw->term.marginWidth);
2107 request.request_mode |= CWHeight;
2110 /* handle changes in columns... */
2111 if (cur_tw->term.columns != tw->term.columns) {
2112 request.width = tw->term.columns * tw->term.widthInc +
2113 2 * (tw->primitive.shadow_thickness +
2114 tw->primitive.highlight_thickness + tw->term.marginHeight);
2115 request.request_mode |= CWWidth;
2118 /* ignore the return result. The switch statement makes
2119 * it possible to debug the result...
2121 switch(XtMakeGeometryRequest(w, &request, &reply)) {
2122 case XtGeometryAlmost:
2132 if (XtIsRealized(w)) {
2133 /* Let's set the columns and rows back at this point. They will
2134 * be set for real when and if the XtMakeGeometryRequest is
2137 tw->term.columns = cur_tw->term.columns;
2138 tw->term.rows = cur_tw->term.rows;
2142 if (cur_tw->term.fontList != tw->term.fontList) {
2143 XtWidgetGeometry request;
2144 XtWidgetGeometry reply;
2146 /* reset the font in the GC's... */
2147 tw->term.tpd->renderGC.fid = (Font) 0;
2148 tw->term.tpd->renderReverseGC.fid = (Font) 0;
2149 tw->term.tpd->clearGC.fid = (Font) 0;
2151 /* Our font list changed on us. We need to resize ourself and
2152 * recompute our width and height increment values...
2154 tw->term.tpd->termFont = CreateRenderFont(w, tw->term.fontList,
2155 &tw->term.fontSet, &tw->term.font);
2157 /* look through our XFontSet or XFontStruct and adjust our
2158 * width and height increments...
2160 (void) AdjustWindowUnits(w);
2161 request.height = tw->term.rows * tw->term.heightInc +
2162 2 * (tw->primitive.shadow_thickness +
2163 tw->primitive.highlight_thickness + tw->term.marginWidth);
2164 request.width = tw->term.columns * tw->term.widthInc +
2165 2 * (tw->primitive.shadow_thickness +
2166 tw->primitive.highlight_thickness + tw->term.marginHeight);
2167 request.request_mode = CWWidth | CWHeight;
2169 /* ignore the return result... */
2170 (void) XtMakeGeometryRequest(w, &request, &reply);
2171 (void) XmImVaSetValues(w,
2172 XmNfontList, tw->term.fontList,
2174 /* clear the cursor position so that we will recalculate the
2175 * im spotLocation with the new font metrics...
2177 tw->term.tpd->IMCursorRow = -1;
2178 tw->term.tpd->IMCursorColumn = -1;
2181 if (cur_tw->term.boldFontList != tw->term.boldFontList) {
2182 /* Our bold font has been changed... */
2183 tw->term.tpd->boldTermFont = CreateRenderFont(w, tw->term.boldFontList,
2184 (XFontSet *) 0, (XFontStruct **) 0);
2187 if (cur_tw->term.charCursorStyle != tw->term.charCursorStyle) {
2188 /* we need to refresh so that we won't get caught in the cursor
2194 if (cur_tw->term.reverseVideo != tw->term.reverseVideo) {
2195 /* we need to refresh so that we will turn on or turn off
2206 ** oldEnv - pointer to a null terminated list of env strings
2207 ** mergeEnv - pointer to a null terminated list of env strings to merge
2210 ** a pointer to a new list of environment strings
2212 ** It is the calling function's responsibility to free the memory
2213 ** allocated for the new list of strings.
2215 ** If one of the merge environment strings already exists in the old
2216 ** environment, then the new environment string replaces the old string,
2217 ** otherwise it is appended to the new list of strings.
2237 ** count the number of new environment strings
2239 for (numMerge = 0; mergeEnv[numMerge]; numMerge++)
2243 ** create and initialize a list of indexs for each of the new strings
2244 ** (assume they will all be appended (idx == -1) and adjust later)...
2246 mergeIdx = (int *) XtMalloc(numMerge * sizeof(int));
2247 for (i1 = 0; i1 < numMerge; i1++)
2253 ** count the number of strings in old environment, and see how many
2254 ** of the merge strings match old strings
2257 for (numOld = 0; oldEnv[numOld]; numOld++)
2260 ** how many old strings have to be replaced?
2262 if (numReplace < numMerge)
2264 for (i1 = 0; i1 < numMerge; i1++)
2266 if (mergeIdx[i1] == -1)
2269 idx = strchr(mergeEnv[i1], '=');
2271 if (strncmp(mergeEnv[i1], oldEnv[numOld],
2272 idx - mergeEnv[i1] + 1) == 0)
2275 ** we have a match, remember the index of
2276 ** this string for later...
2278 mergeIdx[i1] = numOld;
2286 numNew = numOld + numMerge - numReplace;
2289 ** make room for the appended strings...
2292 ** We use malloc here instead of XtMalloc to keep Sentinel from
2293 ** complaining if putenv reallocs this space. (Sentinel prints a
2294 ** warning if memory allocation functions are not used symmetrically
2295 ** (i.e. memory that is XtMalloc'd should be either XtFree'd or
2296 ** XtRealloc'd, not free'd or realloc'd).)
2298 newEnv = (char **) malloc((numNew + 1) * sizeof(char *));
2301 printf("L10n MALLOC ERROR\n");
2305 ** copy the old environment into the new one, and null terminate the
2308 memcpy(newEnv, oldEnv, numOld * sizeof(char *));
2309 newEnv[numNew] = (char *) NULL;
2312 ** now merge in the merge strings, the merge string will either replace
2313 ** the existing string (mergeIdx >= 0) or be appended to the list
2316 ppChar = newEnv + numOld;
2317 for (i1 = 0; i1 < numMerge; i1++)
2319 if (mergeIdx[i1] < 0)
2322 ** append it to the list
2324 *ppChar = mergeEnv[i1];
2330 ** replace the existing string
2332 newEnv[mergeIdx[i1]] = mergeEnv[i1];
2336 XtFree((char *)mergeIdx);
2344 Realize(Widget w, XtValueMask *p_valueMask, XSetWindowAttributes *attributes)
2346 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
2347 DtTermPrimData tpd = tw->term.tpd;
2348 Mask valueMask = *p_valueMask;
2350 char buffer[BUFSIZ];
2351 char **newEnv = (char **) 0;
2352 char **oldEnv = (char **) 0;
2353 extern char **environ;
2354 char *newEnvStrings[4];
2356 char *ptyMasterName = (char *) 0;
2359 XIMCallback xim_cb[4];
2362 Debug('T', timeStamp("TermPrim Realize() starting"));
2364 /* adjust rows and columns to the window size...
2366 tw->term.columns = ((int)(tw->core.width - (2 * (tw->primitive.shadow_thickness +
2367 tw->primitive.highlight_thickness + tw->term.marginWidth)))) /
2369 tw->term.rows = ((int)(tw->core.height - (2 * (tw->primitive.shadow_thickness +
2370 tw->primitive.highlight_thickness + tw->term.marginHeight)))) /
2374 valueMask |= CWBitGravity | CWDontPropagate;
2375 attributes->bit_gravity = ForgetGravity;
2376 attributes->do_not_propagate_mask = ButtonPressMask |
2377 ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
2380 (void) XtCreateWindow(w, InputOutput, CopyFromParent, valueMask,
2384 * register input method, and set callbacks for on the spot
2387 (void) XmImRegister(w, (unsigned int) NULL);
2392 XtSetArg(args[n], XmNspotLocation, &imPoint); n++;
2393 XtSetArg(args[n], XmNfontList, tw->term.fontList); n++;
2394 XtSetArg(args[n], XmNbackground, tw->core.background_pixel); n++;
2395 XtSetArg(args[n], XmNforeground, tw->primitive.foreground); n++;
2396 XtSetArg(args[n], XmNbackgroundPixmap, tw->core.background_pixmap); n++;
2397 XtSetArg(args[n], XmNlineSpace, tw->term.heightInc); n++;
2400 * Register on the spot callbacks.
2402 xim_cb[0].client_data = (XPointer)w;
2403 xim_cb[0].callback = (XIMProc)PreeditStart;
2404 xim_cb[1].client_data = (XPointer)w;
2405 xim_cb[1].callback = (XIMProc)PreeditDone;
2406 xim_cb[2].client_data = (XPointer)tw;
2407 xim_cb[2].callback = (XIMProc)PreeditDraw;
2408 xim_cb[3].client_data = (XPointer)w;
2409 xim_cb[3].callback = (XIMProc)PreeditCaret;
2410 XtSetArg(args[n], XmNpreeditStartCallback, &xim_cb[0]); n++;
2411 XtSetArg(args[n], XmNpreeditDoneCallback, &xim_cb[1]); n++;
2412 XtSetArg(args[n], XmNpreeditDrawCallback, &xim_cb[2]); n++;
2413 XtSetArg(args[n], XmNpreeditCaretCallback, &xim_cb[3]); n++;
2415 XmImSetValues(w, args, n);
2417 /* block sigchld while we do this... */
2418 (void) sigemptyset(&sigNew);
2419 (void) sigaddset(&sigNew, SIGCHLD);
2420 (void) sigprocmask(SIG_BLOCK, &sigNew, (sigset_t *) 0);
2422 /* get reference terminal modes before we open the pty (so we don't
2423 * inherit them from the pty), before we fork (so we only do this
2424 * once for however many instances we create), and before we break
2425 * our association from our controlling terminal (so we have something
2426 * to inherit from)...
2428 (void) _DtTermPrimPtyGetDefaultModes();
2430 /* allocate a pty if appropriate... */
2431 if (tw->term.ptyAllocate) {
2434 /* turn on suid root... */
2435 _DtTermPrimToggleSuidRoot(True);
2436 tw->term.pty = _DtTermPrimGetPty(&tw->term.ptySlaveName,
2438 /* turn off suid root... */
2439 _DtTermPrimToggleSuidRoot(False);
2441 if (tw->term.pty < 0) {
2442 XmeWarning(w, "unable to get pty");
2444 /* popup a warning dialog... */
2445 (void) _DtTermPrimWarningDialog(w, "unable to get pty");
2448 /* this is the Spec1170 way to do this. We probably could
2449 consolidate the various _DtTermPrimGetPtys at this point,
2450 but that's Truth & Beauty. */
2451 if (fcntl(tw->term.pty, F_SETFL, O_NONBLOCK |
2452 fcntl(tw->term.pty, F_GETFL, 0)) == -1)
2454 XmeWarning(w, "unable to set non-blocking on pty");
2456 /* popup a warning dialog... */
2457 (void) _DtTermPrimWarningDialog(w,
2458 "unable to set non-blocking on pty");
2462 if (ptyMasterName) {
2463 (void) free(ptyMasterName);
2467 /* set the initial winsize structure before we kick off the
2470 if (tw->term.pty >= 0) {
2471 (void) _DtTermPrimPtySetWindowSize(tw->term.pty,
2472 tw->term.columns * tw->term.widthInc +
2473 (2 * (tw->primitive.shadow_thickness +
2474 tw->primitive.highlight_thickness +
2475 tw->term.marginWidth)),
2476 tw->term.rows * tw->term.heightInc +
2477 (2 * (tw->primitive.shadow_thickness +
2478 tw->primitive.highlight_thickness +
2479 tw->term.marginHeight)),
2480 tw->term.rows, tw->term.columns);
2483 /* get the utmp line name to use for searching later... */
2484 if (tw->term.pty >= 0) {
2485 tw->term.tpd->utmpId = _DtTermPrimUtmpGetUtLine(-1,
2486 tw->term.ptySlaveName);
2490 ** If pointerBlank is true, then turn on the pointer with blanking,
2491 * else turn it on to always stay on.
2493 if (tw->term.pointerBlank) {(void) _DtTermPrimPointerOn((Widget)tw); }
2494 else XDefineCursor(XtDisplay(tw), XtWindow(tw), tw->term.pointerShape);
2495 _DtTermPrimRecolorPointer((Widget)tw) ;
2497 /* kick off a subprocess if appropriate. Don't kick one off if
2498 * we didn't get a pty...
2500 if (tw->term.subprocessExec && (tw->term.pty >= 0)) {
2502 /* DKS: maybe we need to start passing the cmd earlier and not
2505 if (!tw->term.subprocessCmd && tw->term.subprocessArgv) {
2506 tw->term.subprocessCmd = *tw->term.subprocessArgv;
2509 /* modify the environment for our child process...
2511 /* set the environment variables for TERM, LINES, COLUMNS... */
2515 #ifdef SETENV_LINES_AND_COLS
2516 (void) sprintf(buffer, "LINES=%d", tw->term.rows);
2517 newEnvStrings[i1] = XtMalloc(strlen(buffer) + 1);
2518 (void) strcpy(newEnvStrings[i1++], buffer);
2520 (void) sprintf(buffer, "COLUMNS=%d", tw->term.columns);
2521 newEnvStrings[i1] = XtMalloc(strlen(buffer) + 1);
2522 (void) strcpy(newEnvStrings[i1++], buffer);
2523 #endif /* SETENV_LINES_AND_COLS */
2525 if (tw->term.termName && *tw->term.termName)
2527 char *fmt = "TERM=%s";
2530 XtMalloc(strlen(tw->term.termName) + strlen(fmt) + 1);
2531 (void) sprintf(newEnvStrings[i1], fmt, tw->term.termName);
2534 /* null term the list of new env strings... */
2535 newEnvStrings[i1] = (char *) 0;
2537 environ = _mergeEnv(oldEnv, newEnvStrings);
2539 tw->term.subprocessPid = _DtTermPrimSubprocExec(w,
2540 tw->term.ptySlaveName,
2541 tw->term.consoleMode,
2542 tw->term.subprocessCWD,
2543 tw->term.subprocessCmd, tw->term.subprocessArgv,
2544 tw->term.subprocessLoginShell);
2546 /* free up the new environ... */
2547 for (i1 = 0; newEnvStrings[i1]; i1++)
2549 (void) XtFree(newEnvStrings[i1]);
2554 ** free environ (rather than XtFree it) is since it was
2555 ** malloc'd (not XtMalloc'd) in _mergeEnv...
2557 (void) free((char *) environ);
2562 /* set up a signal handler if appropriate... */
2563 if (tw->term.subprocessPid >= 0)
2565 tw->term.subprocessId = _DtTermPrimAddSubproc(w,
2566 tw->term.subprocessPid,
2567 InvokeTerminationCallback, NULL);
2568 if (tw->term.subprocessTerminationCatch)
2570 (void)_DtTermPrimSetChildSignalHandler();
2574 /* unblock sigchld now that we are done... */
2575 (void) sigprocmask(SIG_UNBLOCK, &sigNew, (sigset_t *) 0);
2576 Debug('T', timeStamp("TermPrim Realize() finished"));
2584 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
2586 /* remove our handlers on our shell widget... */
2590 for (sw = w; !XtIsShell(sw); sw = XtParent(sw))
2592 (void) XtRemoveEventHandler(sw, (EventMask) StructureNotifyMask,
2593 False, handleProcessStructureNotifyEvent, (Opaque) w);
2594 (void) XtRemoveEventHandler(sw, (EventMask) PropertyChangeMask,
2595 False, handlePropertyChangeEvents, (Opaque) w);
2599 ** Unregister our input method (this fixes CMVC 8146).
2603 /* clean up pty specific stuff...
2605 /* remove the pty input handler... */
2606 if (tw->term.tpd && tw->term.tpd->ptyInputId) {
2607 (void) XtRemoveInput(tw->term.tpd->ptyInputId);
2608 tw->term.tpd->ptyInputId = (XtInputId) 0;
2611 /* let's be proactive and send a SIGHUP to all the processes in this
2612 * instances process group. For safety sake, let's not do anything
2613 * if the process id is not >1 (since use of 1 will send the signal
2614 * to all processes).
2616 /* turn on suid root...
2618 _DtTermPrimToggleSuidRoot(True);
2619 if (tw->term.subprocessPid > 1) {
2620 (void) kill(-tw->term.subprocessPid, SIGHUP);
2622 /* turn off suid root...
2624 _DtTermPrimToggleSuidRoot(False);
2626 /* clean up our utmp entry... */
2627 if (tw->term.tpd && tw->term.tpd->utmpId && *tw->term.tpd->utmpId) {
2628 _DtTermPrimUtmpEntryDestroy(w, tw->term.tpd->utmpId);
2629 (void) XtFree(tw->term.tpd->utmpId);
2630 tw->term.tpd->utmpId = (char *) 0;
2633 /* close and release the...
2635 if (tw->term.pty >= 0) {
2636 /* close the pty file descriptor so that:
2637 * - the child will (passively) get SIGHUP'ed.
2638 * - the child will get EOF on stdin.
2640 (void) close(tw->term.pty);
2641 /* release the pty (restore owner, group, mode)... */
2642 if (tw->term.ptySlaveName) {
2643 (void) _DtTermPrimReleasePty(tw->term.ptySlaveName);
2647 /* remove the subproc termination callback... */
2648 if (tw->term.subprocessId) {
2649 _DtTermPrimSubprocRemoveSubproc(w, tw->term.subprocessId);
2650 tw->term.subprocessId = (_termSubprocId) 0;
2653 /* free storage for current working directory name*/
2654 if ( tw->term.subprocessCWD) {
2655 XtFree(tw->term.subprocessCWD);
2658 /* flush the log file */
2659 if (tw->term.logging ) {
2660 _DtTermPrimCloseLog(tw) ;
2663 if (tw->term.boldFont) {
2664 (void) XFreeFont(XtDisplay(w), tw->term.boldFont);
2666 if (tw->term.boldFontSet) {
2667 (void) XFreeFontSet(XtDisplay(w), tw->term.boldFontSet);
2670 /* remove the termData structure contents, followed by the structure...
2673 /* remove the cursor timeout... */
2674 if (tw->term.tpd->cursorTimeoutId) {
2675 (void) XtRemoveTimeOut(tw->term.tpd->cursorTimeoutId);
2676 tw->term.tpd->cursorTimeoutId = (XtIntervalId) 0;
2679 /* free up all our GC's...
2682 if (tw->term.tpd->renderGC.gc) {
2683 (void) XFreeGC(XtDisplay(w), tw->term.tpd->renderGC.gc);
2684 tw->term.tpd->renderGC.gc = (GC) 0;
2686 if (tw->term.tpd->renderReverseGC.gc) {
2687 (void) XFreeGC(XtDisplay(w), tw->term.tpd->renderReverseGC.gc);
2688 tw->term.tpd->renderReverseGC.gc = (GC) 0;
2691 if (tw->term.tpd->clearGC.gc) {
2692 (void) XFreeGC(XtDisplay(w), tw->term.tpd->clearGC.gc);
2693 tw->term.tpd->clearGC.gc = (GC) 0;
2696 if (tw->term.tpd->cursorGC.gc) {
2697 (void) XFreeGC(XtDisplay(w), tw->term.tpd->cursorGC.gc);
2698 tw->term.tpd->cursorGC.gc = (GC) 0;
2701 /* free up our buffers... */
2702 if (tw->term.tpd->historyBuffer) {
2703 _DtTermPrimBufferFreeBuffer(tw->term.tpd->historyBuffer);
2704 tw->term.tpd->historyBuffer = NULL;
2707 if (tw->term.tpd->termBuffer) {
2708 _DtTermPrimBufferFreeBuffer(tw->term.tpd->termBuffer);
2709 tw->term.tpd->termBuffer = NULL;
2712 /* free up the scrollRefreshRows... */
2713 if (tw->term.tpd->scrollRefreshRows) {
2714 (void) XtFree((char *) tw->term.tpd->scrollRefreshRows);
2715 tw->term.tpd->scrollRefreshRows = (Boolean *) 0;
2718 /* free up the selection information */
2719 if (tw->term.tpd->selectInfo) {
2720 (void) _DtTermPrimSelectDestroy(w, tw->term.tpd->selectInfo);
2721 tw->term.tpd->selectInfo = (TermSelectInfo) 0;
2724 /* free up pending text... */
2725 if (tw->term.tpd->pendingRead) {
2726 (void) _DtTermPrimPendingTextDestroy(tw->term.tpd->pendingRead);
2727 tw->term.tpd->pendingRead = (PendingText) 0;
2729 if (tw->term.tpd->pendingWrite) {
2730 (void) _DtTermPrimPendingTextDestroy(tw->term.tpd->pendingWrite);
2731 tw->term.tpd->pendingWrite = (PendingText) 0;
2734 if (tw->term.tpd->capsLockKeyCodes)
2735 (void) XtFree((char *)tw->term.tpd->capsLockKeyCodes) ;
2737 (void) _DtTermPrimDestroyFont(w,tw->term.tpd->boldTermFont) ;
2738 (void) _DtTermPrimDestroyFont(w,tw->term.tpd->termFont) ;
2740 if (tw->term.ptyAllocate && tw->term.ptySlaveName)
2741 (void) XtFree((char *)tw->term.ptySlaveName);
2744 if (tw->term.tpd->context)
2745 (void) XtFree((char *)tw->term.tpd->context);
2747 /* free up the termData structure... */
2748 (void) XtFree((char *) tw->term.tpd);
2749 tw->term.tpd = (DtTermPrimData) 0;
2754 /* _DtTermPrimActionEnter...
2757 _DtTermPrimActionEnter(Widget w, XEvent *event,
2758 String *params, Cardinal *num_params)
2760 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
2762 Debug('F', fprintf(stderr, ">>enterEvent starting\n"));
2764 Debug('F', fprintf(stderr,
2765 ">> widget: name=\"%s\" widget=0x%lx window=0x%lx\n",
2766 tw->core.name, tw, XtWindow(w)));
2767 Debug('F', fprintf(stderr,
2768 ">> event: window=0x%lx\n mode=%d detail=%d\n",
2769 event->xcrossing.window, event->xcrossing.mode,
2770 event->xcrossing.detail));
2772 Debug('F', _DtTermPrimDebugDumpEvent(stderr, w, event));
2774 if ((_XmGetFocusPolicy(w) != XmEXPLICIT) &&
2775 !(tw->term.hasFocus) &&
2776 event->xcrossing.focus &&
2777 (event->xcrossing.detail != NotifyInferior)) {
2778 tw->term.hasFocus = True;
2779 _DtTermPrimCursorChangeFocus(w);
2782 if ( tw->term.pointerBlank )
2783 _DtTermPrimPointerFreeze((Widget)tw, False);
2785 /* update the caps lock flag... */
2786 (void) CapsLockUpdate(w,
2787 (event->xcrossing.state & LockMask) != 0);
2789 _XmPrimitiveEnter(w, event, params, num_params);
2793 /* _DtTermPrimActionLeave...
2796 _DtTermPrimActionLeave(Widget w, XEvent *event,
2797 String *params, Cardinal *num_params)
2799 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
2801 Debug('F', fprintf(stderr, ">>leaveEvent starting\n"));
2803 Debug('F', fprintf(stderr,
2804 ">> widget: name=\"%s\" widget=0x%lx window=0x%lx\n",
2805 tw->core.name, tw, XtWindow(w)));
2806 Debug('F', fprintf(stderr,
2807 ">> event: window=0x%lx\n mode=%d detail=%d\n",
2808 event->xcrossing.window, event->xcrossing.mode,
2809 event->xcrossing.detail));
2811 Debug('F', _DtTermPrimDebugDumpEvent(stderr, w, event));
2813 if ((_XmGetFocusPolicy(w) != XmEXPLICIT) &&
2814 tw->term.hasFocus &&
2815 event->xcrossing.focus &&
2816 (event->xcrossing.detail != NotifyInferior)) {
2817 tw->term.hasFocus = False;
2818 _DtTermPrimCursorChangeFocus(w);
2821 if ( tw->term.pointerBlank )
2822 _DtTermPrimPointerFreeze((Widget)tw, True);
2824 /* update the caps lock flag... */
2825 (void) CapsLockUpdate(w,
2826 (event->xcrossing.state & LockMask) != 0);
2828 _XmPrimitiveLeave(w, event, params, num_params);
2835 struct timeval timeout;
2837 /* do a non-blocking select to see if we have any more input. If so,
2838 * we don't need to turn the cursor back on.
2841 FD_SET(pty, &readFD);
2843 timeout.tv_usec = 0;
2844 if (!((select(pty + 1, &readFD, 0, 0, &timeout) > 0) &&
2845 (FD_ISSET(pty, &readFD))))
2852 readPty(XtPointer client_data, int *source, XtInputId *id)
2854 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
2855 DtTermPrimData tpd = tw->term.tpd;
2856 unsigned char buffer[BUFSIZ];
2858 unsigned char *dangleBuffer;
2859 int dangleBufferLen;
2861 PendingTextChunk chunk = (PendingTextChunk) 0;
2863 Debug('i', fprintf(stderr, ">>readPty() starting\n"));
2864 tpd->readInProgress = True;
2865 (void) _DtTermPrimCursorOff((Widget) tw);
2866 /* if we are using a history buffer and have scrolled into it, we
2867 * need to snap back down before we do anything...
2869 if (tpd->useHistoryBuffer && (tpd->topRow < 0)) {
2870 (void) _DtTermPrimScrollTextTo((Widget) tw, 0);
2871 (void) _DtTermPrimScrollComplete((Widget) tw, True);
2874 if (TextIsPending(tpd->pendingRead)) {
2875 /* take text from the pendingRead buffer instead of doing a read...
2877 chunk = _DtTermPrimPendingTextGetChunk(tpd->pendingRead);
2879 (void) memcpy(buffer, chunk->bufPtr, len);
2881 len = read(*source, buffer, sizeof(buffer));
2882 Debug('i', fprintf(stderr, ">>readPty() read len=%d\n", len));
2883 if (isDebugFSet('i', 1)) {
2889 (void) fprintf(stderr,
2890 ">>readPty() read %d bytes", len);
2892 for (i1 = 0; i1 < len; i1++) {
2894 fputs("\n ", stderr);
2895 (void) fprintf(stderr, " %02x", buffer[i1]);
2897 (void) fprintf(stderr, "\n");
2903 if (!tpd->windowMapped && tw->term.mapOnOutput) {
2905 ** map window unless it is too early...
2907 if (tw->term.mapOnOutputDelay)
2908 if ((time((time_t *) 0) - tpd->creationTime) >
2909 tw->term.mapOnOutputDelay) {
2913 tw->term.mapOnOutputDelay = 0 ;
2916 if (!tw->term.mapOnOutputDelay) {
2919 for (sw = (Widget)tw; !XtIsShell(sw); sw = XtParent(sw))
2925 if (tw->term.log_on) {
2926 _DtTermPrimWriteLog(tw, buffer, len) ;
2929 if (tw->term.outputLogCallback) {
2930 DtTermOutputLogCallbackStruct cb;
2932 cb.reason = DtCR_TERM_OUTPUT_LOG;
2933 cb.event = (XEvent *) 0;
2937 (void) XtCallCallbackList((Widget) tw,
2938 tw->term.outputLogCallback, &cb);
2941 if (!_DtTermPrimParseInput((Widget) tw, buffer, len,
2942 &dangleBuffer, &dangleBufferLen)) {
2943 /* we were not able to write out everything and
2944 * we need to stuff away the pending text...
2947 /* we didn't finish up the pending text chunk we were
2948 * working on, so update the pointers and continue...
2950 (void) _DtTermPrimPendingTextReplace(chunk, dangleBuffer,
2953 (void) _DtTermPrimPendingTextAppend(tpd->pendingRead,
2954 dangleBuffer, dangleBufferLen);
2956 (void) XtFree((char *) dangleBuffer);
2958 /* we finished a pending chunk, so let's move on... */
2959 _DtTermPrimPendingTextRemoveChunk(tpd->pendingRead, chunk);
2961 if (!tpd->ptyInputId) {
2962 /* we need to wait until we get a graphicsexpose (count==0)
2965 /* we know we have more input, so we don't need to turn on
2968 tpd->readInProgress = False;
2969 Debug('i', fprintf(stderr, ">>readPty() finished\n"));
2974 if (!moreInput(tw->term.pty)) {
2975 /* we won't be getting an input select so we need to check on
2976 * pending text and force a read if we still have some...
2978 if (TextIsPending(tpd->pendingRead)) {
2979 (void) XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) tw),
2980 0, _DtTermPrimForcePtyRead, (XtPointer) tw);
2982 /* turn the cursor back on... */
2983 (void) _DtTermPrimCursorOn((Widget) tw);
2986 tpd->readInProgress = False;
2987 Debug('i', fprintf(stderr, ">>readPty() finished\n"));
2992 _DtTermPrimForcePtyRead(XtPointer client_data, XtIntervalId *id)
2994 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
2995 DtTermPrimData tpd = tw->term.tpd;
2996 int fd = tw->term.pty;
2998 (void) _DtTermPrimStartOrStopPtyInput((Widget) tw);
3000 if (TextIsPending(tpd->pendingRead)) {
3001 (void) readPty(client_data, &fd, &tpd->ptyInputId);
3006 _DtTermPrimLoopBackData(Widget w, char *data, int dataLength)
3008 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3009 DtTermPrimData tpd = tw->term.tpd;
3010 int fd = tw->term.pty;
3012 /* queue up the pending text... */
3013 (void) _DtTermPrimPendingTextAppend(tpd->pendingRead, (unsigned char *) data,
3016 /* if we have a read in process, we can return now... */
3017 if (tpd->readInProgress) {
3021 /* if we are set up to select on pty input, then we can force a read
3024 if (tpd->ptyInputId) {
3025 (void) readPty((XtPointer) w, &fd, &tpd->ptyInputId);
3028 /* if not, we will force a read when we turn select on input back
3037 unsigned char *buffer,
3041 _DtTermWidgetToAppContext(w);
3043 /* for now, it looks like _DtTermPrimLoopBackData will take care
3044 * of everything for us...
3046 _DtTermAppLock(app);
3047 (void) _DtTermPrimLoopBackData(w, (char *) buffer, length);
3048 _DtTermAppUnlock(app);
3053 writePty(XtPointer client_data, int *source, XtInputId *id)
3055 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
3056 DtTermPrimData tpd = tw->term.tpd;
3058 Debug('o', fprintf(stderr, ">>writePty() starting\n"));
3061 ** write some text from list of pending text chunks
3063 _DtTermPrimPendingTextWrite(tpd->pendingWrite, tw->term.pty);
3066 ** turn off the write select as appropriate
3068 _DtTermPrimStartOrStopPtyOutput((Widget)client_data);
3069 Debug('o', fprintf(stderr, ">>writePty() finished\n"));
3074 _DtTermPrimActionKeyRelease(Widget w, XEvent *event, String *params,
3075 Cardinal *num_params)
3077 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3078 DtTermPrimData tpd = tw->term.tpd;
3079 XKeyEvent *keyEvent = (XKeyEvent *) event;
3082 Debug('i', fprintf(stderr, ">>_DtTermPrimActionKeyRelease() starting\n"));
3083 if (keyEvent->type != KeyRelease) {
3084 (void) fprintf(stderr,
3085 "_DtTermPrimActionKeyRelease: incorrect event type %d\n",
3090 /* check for caps lock... */
3091 for (i = 0; i < tpd->numCapsLockKeyCodes; i++) {
3092 if (tpd->capsLockKeyCodes[i] == keyEvent->keycode) {
3093 /* caps lock has toggled... */
3094 (void) CapsLockUpdate(w, !tpd->capsLock);
3102 _DtTermPrimActionKeyInput(Widget w, XEvent *event, String *params,
3103 Cardinal *num_params)
3105 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3106 DtTermPrimData tpd = tw->term.tpd;
3107 XKeyEvent *keyEvent = (XKeyEvent *) event;
3110 unsigned char string[BUFSIZ];
3113 Boolean synEscape = False; /* synthesize escape key from meta key */
3116 Debug('i', fprintf(stderr, ">>_DtTermPrimActionKeyInput() starting\n"));
3117 if (keyEvent->type != KeyPress) {
3118 (void) fprintf(stderr, "_DtTermPrimActionKeyInput: incorrect event type %d\n",
3122 if (KEYBOARD_LOCKED(tpd->keyboardLocked)) {
3123 /* keyboard locked -- ring the bell...
3125 (void) _DtTermPrimBell(w);
3129 if (tw->term.kshMode &&
3130 ((keyEvent->state & tpd->metaMask) == tpd->metaMask)) {
3131 keyEvent->state &= ~tpd->metaMask;
3135 /* check for caps lock... */
3136 for (i = 0; i < tpd->numCapsLockKeyCodes; i++) {
3137 if (tpd->capsLockKeyCodes[i] == keyEvent->keycode) {
3138 /* caps lock has toggled... */
3139 (void) CapsLockUpdate(w, !tpd->capsLock);
3144 /* I've pulled the following from hpterm2.0's input.c. I don't
3145 * understand any of it, and we need to get some documentation on
3149 nbytes = XmImMbLookupString(w, keyEvent, (char *) string, sizeof(string),
3151 if (XBufferOverflow == status) {
3155 #ifdef XOR_CAPS_LOCK
3156 /* if lock and shift are both pressed, let's invert the case of all
3157 * upper and lower case characters...
3159 if ((keyEvent->state & (LockMask | ShiftMask)) == (LockMask | ShiftMask)) {
3160 for (i = 0; i < nbytes; i++) {
3161 if (isupper(string[i])) {
3162 string[i] = _tolower(string[i]);
3163 } else if (islower(string[i])) {
3164 string[i] = _toupper(string[i]);
3168 #endif /* XOR_CAPS_LOCK */
3171 if ((nbytes > 0) && (tw->term.inputVerifyCallback)) {
3172 DtTermInputVerifyCallbackStruct cb;
3174 cb.reason = DtCR_TERM_INPUT_VERIFY;
3180 /* invoke the callbacks... */
3181 (void) XtCallCallbackList(w, tw->term.inputVerifyCallback, &cb);
3183 /* if doit was turned off, forget about the string... */
3190 unsigned char *start;
3193 /* perform margin bell functionality if necessary... */
3194 if (tw->term.marginBell &&
3195 ((tw->term.columns - tw->term.nMarginBell) ==
3196 tpd->cursorColumn)) {
3200 /* synthesize escape unless it was CR or Vertical Tab */
3201 if (synEscape && *string != '\r' && *string != 0x0B)
3202 (void) _DtTermPrimSendInput(w, (unsigned char *) "\033", 1);
3204 /* for pointer blanking */
3205 if (tw->term.pointerBlank && *string != '\r' && *string != 0x0B)
3206 _DtTermPrimPointerOff((Widget)tw,(XtIntervalId *)NULL) ;
3208 for (end = string; nbytes > 0; ) {
3209 for (start = end; (nbytes > 0) && (*end != '\r'); nbytes--, end++)
3211 if ((nbytes > 0) && (*end == '\r')) {
3215 (void) _DtTermPrimSendInput(w, start, end - start);
3216 if (tpd->autoLineFeed && (end[-1] == '\r')) {
3217 (void) _DtTermPrimSendInput(w, (unsigned char *) "\n", 1);
3222 Debug('i', fprintf(stderr, ">>_DtTermPrimActionKeyInput() finished\n"));
3226 _DtTermPrimSendInput
3229 unsigned char *buffer,
3233 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3234 DtTermPrimData tpd = tw->term.tpd;
3237 (void) _DtTermPrimPendingTextAppend(tpd->pendingWrite, buffer, length);
3238 (void) _DtTermPrimStartOrStopPtyOutput(w);
3240 if (tpd->halfDuplex) {
3241 DtTermDisplaySend(w, buffer, length);
3250 unsigned char *buffer,
3254 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3255 DtTermPrimData tpd = tw->term.tpd;
3256 _DtTermWidgetToAppContext(w);
3258 /* queue up all text send from outside the widget... */
3259 _DtTermAppLock(app);
3261 (void) _DtTermPrimPendingTextAppend(tpd->pendingWrite, buffer, length);
3262 (void) _DtTermPrimStartOrStopPtyOutput(w);
3263 if (tpd->halfDuplex) {
3264 DtTermDisplaySend(w, buffer, length);
3267 _DtTermAppUnlock(app);
3272 _DtTermPrimActionFocusIn(Widget w, XEvent *event, String *params,
3273 Cardinal *num_params)
3275 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3277 Debug('F', fprintf(stderr, ">>focusIn starting\n"));
3279 Debug('F', fprintf(stderr,
3280 ">> widget: name=\"%s\" widget=0x%lx window=0x%lx\n",
3281 tw->core.name, tw, XtWindow(w)));
3282 Debug('F', fprintf(stderr,
3283 ">> event: window=0x%lx\n mode=%d detail=%d\n",
3284 event->xfocus.window, event->xfocus.mode, event->xfocus.detail));
3286 Debug('F', _DtTermPrimDebugDumpEvent(stderr, w, event));
3289 #ifdef MOTIF_TEXT_BUG
3290 event->xfocus.send_event &&
3291 #endif /* MOTIF_TEXT_BUG */
3292 !(tw->term.hasFocus)) {
3293 tw->term.hasFocus = True;
3294 _DtTermPrimCursorChangeFocus(w);
3295 if (_XmGetFocusPolicy(w) == XmEXPLICIT) {
3296 if (((XmPrimitiveWidgetClass) XtClass(w))
3297 ->primitive_class.border_highlight) {
3298 (void) (*((XmPrimitiveWidgetClass) XtClass(w))
3299 ->primitive_class.border_highlight)(w);
3303 (void) _XmPrimitiveFocusIn(w, event, params, num_params);
3308 _DtTermPrimActionFocusOut(Widget w, XEvent *event, String *params,
3309 Cardinal *num_params)
3311 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3313 Debug('F', fprintf(stderr, ">>focusOut starting\n"));
3315 Debug('F', fprintf(stderr,
3316 ">> widget: name=\"%s\" widget=0x%lx window=0x%lx\n",
3317 tw->core.name, tw, XtWindow(w)));
3318 Debug('F', fprintf(stderr,
3319 ">> event: window=0x%lx\n mode=%d detail=%d\n",
3320 event->xfocus.window, event->xfocus.mode, event->xfocus.detail));
3322 Debug('F', _DtTermPrimDebugDumpEvent(stderr, w, event));
3325 #ifdef MOTIF_TEXT_BUG
3326 event->xfocus.send_event &&
3327 #endif /* MOTIF_TEXT_BUG */
3328 tw->term.hasFocus) {
3329 tw->term.hasFocus = False;
3330 _DtTermPrimCursorChangeFocus(w);
3331 if (_XmGetFocusPolicy(w) == XmEXPLICIT) {
3332 if (((XmPrimitiveWidgetClass) XtClass(w))
3333 ->primitive_class.border_unhighlight) {
3334 (void) (*((XmPrimitiveWidgetClass) XtClass(w))
3335 ->primitive_class.border_unhighlight)(w);
3339 (void) _XmPrimitiveFocusOut(w, event, params, num_params);
3347 Modifiers modifiers,
3348 Modifiers *modifiersReturn,
3349 KeySym *keysymReturn
3352 /* call the Xt translator to translate this event... */
3353 (void) XtTranslateKey(display, keyCode, modifiers, modifiersReturn,
3355 /* and reinstall the Motif translator for the next widget/event... */
3356 (void) XtSetKeyTranslator(display, (XtKeyProc) XmTranslateKey);
3361 handleKeyEvents(Widget w, XtPointer closure, XEvent *event, Boolean *cont)
3363 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3365 /* drop synthetic events... */
3366 if (!tw->term.allowSendEvents && event->xany.send_event) {
3371 #ifdef KEY_TRANSLATE_HACK
3372 /* install our key translator... */
3373 (void) XtSetKeyTranslator(XtDisplay(w), (XtKeyProc) KeyTranslator);
3374 #endif /* KEY_TRANSLATE_HACK */
3380 handleButtonEvents(Widget w, XtPointer closure, XEvent *event, Boolean *cont)
3382 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3384 /* drop synthetic events... */
3385 if (!tw->term.allowSendEvents && event->xany.send_event) {
3392 CapsLockUpdate(Widget w, Boolean capsLock)
3394 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3395 DtTermPrimData tpd = tw->term.tpd;
3397 if (tpd->capsLock != capsLock) {
3398 tpd->capsLock = capsLock;
3400 /* invoke the caps lock callback... */
3401 if (tw->term.statusChangeCallback) {
3402 _DtTermPrimInvokeStatusChangeCallback(w);
3408 _DtTermPrimInsertCharUpdate(Widget w, DtTermInsertCharMode insertCharMode)
3410 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3411 DtTermPrimData tpd = tw->term.tpd;
3413 if (tpd->insertCharMode != insertCharMode) {
3414 tpd->insertCharMode = insertCharMode;
3416 /* invoke the caps lock callback... */
3417 if (tw->term.statusChangeCallback) {
3418 _DtTermPrimInvokeStatusChangeCallback(w);
3425 _DtTermPrimActionStop(Widget w, XEvent *event, String *params, Cardinal *num_params)
3427 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3428 DtTermPrimData tpd = tw->term.tpd;
3430 if (*num_params > 0) {
3431 if (!strcmp(params[0], "on")) {
3432 tpd->outputStopped = False;
3433 } else if (!strcmp(params[0], "off")) {
3434 tpd->outputStopped = True;
3436 /* toggle the output... */
3437 tpd->outputStopped = !tpd->outputStopped;
3440 /* toggle the output... */
3441 tpd->outputStopped = !tpd->outputStopped;
3444 (void) _DtTermPrimStartOrStopPtyInput(w);
3446 /* invoke the status update callback... */
3447 if (tw->term.statusChangeCallback) {
3448 _DtTermPrimInvokeStatusChangeCallback(w);
3453 _DtTermPrimInvokeStatusChangeCallback
3458 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3459 DtTermPrimData tpd = tw->term.tpd;
3460 DtTermStatusChangeCallbackStruct
3463 /* exit now if we don't need to do anything... */
3464 if (!tw->term.statusChangeCallback)
3467 (void) memset(&cb, '\0', sizeof(cb));
3468 cb.reason = DtCR_TERM_STATUS_CHANGE;
3469 cb.event = (XEvent *) 0;
3470 cb.cursorX = tpd->cursorColumn + 1;
3471 cb.cursorY = tpd->topRow + tpd->cursorRow + 1;
3472 cb.capsLock = tpd->capsLock;
3473 cb.stop = tpd->outputStopped;
3474 cb.insertCharMode = tpd->insertCharMode;
3475 cb.locked = tpd->keyboardLocked.escape;
3477 /* invoke them... */
3478 (void) XtCallCallbackList(w, tw->term.statusChangeCallback,
3483 _DtTermPrimDrawShadow(Widget w)
3485 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3487 if (XtIsRealized(w)) {
3488 XmeDrawShadows(XtDisplay(w), XtWindow(w),
3489 tw->primitive.top_shadow_GC,
3490 tw->primitive.bottom_shadow_GC,
3491 tw->primitive.highlight_thickness,
3492 tw->primitive.highlight_thickness,
3493 tw->core.width - 2 * tw->primitive.highlight_thickness,
3494 tw->core.height - 2 * tw->primitive.highlight_thickness,
3495 tw->primitive.shadow_thickness,
3496 tw->term.shadowType);
3501 DtCreateTermPrimitive(Widget parent, char *name, ArgList arglist,
3505 _DtTermWidgetToAppContext(parent);
3507 _DtTermAppLock(app);
3508 Debug('T', timeStamp("DtCreateTermPrimitive() starting"));
3509 w = XtCreateWidget(name, dtTermPrimitiveWidgetClass, parent, arglist,
3511 Debug('T', timeStamp("DtCreateTermPrimitive() finished"));
3512 _DtTermAppUnlock(app);
3517 _DtTermPrimStartOrStopPtyInput(Widget w)
3519 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3520 DtTermPrimData tpd = tw->term.tpd;
3521 Boolean inputOn = True;
3523 /* This function will either turn on or turn off the pty input selector
3524 * depending on the status of:
3526 * - the outputStopped flag,
3527 * - any pending scrolling operations.
3530 Debug('o', fprintf(stderr, ">>_StartOrStopPtyInput() starting\n"));
3531 /* turn off input if there is a non-jump scroll pending... */
3532 if (!tw->term.jumpScroll && tpd->scroll.nojump.pendingScroll)
3535 /* turn off input if we are stopped or paused... */
3536 if (tpd->outputStopped || tpd->oneSecondPause)
3539 if (inputOn && !tpd->ptyInputId && (tw->term.pty >= 0)) {
3542 XtAppAddInput(XtWidgetToApplicationContext((Widget) tw),
3543 tw->term.pty, (XtPointer) XtInputReadMask, readPty,
3545 Debug('o', fprintf(stderr, " adding pty read select\n"));
3546 } else if (!inputOn && tpd->ptyInputId) {
3547 /* turn it off... */
3548 (void) XtRemoveInput(tw->term.tpd->ptyInputId);
3549 tw->term.tpd->ptyInputId = (XtInputId) 0;
3550 Debug('o', fprintf(stderr, " removing pty read select\n"));
3552 Debug('o', fprintf(stderr, ">>_StartOrStopPtyInput() finished\n"));
3556 _DtTermPrimStartOrStopPtyOutput(Widget w)
3558 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3559 DtTermPrimData tpd = tw->term.tpd;
3561 Debug('o', fprintf(stderr, ">>_StartOrStopPtyOutput() starting\n"));
3563 ** This function will either turn on or turn off the
3564 ** pty write selector depending whether any text is waiting
3567 if (TextIsPending(tpd->pendingWrite))
3569 if (tpd->ptyOutputId == 0)
3574 tpd->ptyOutputId = XtAppAddInput(XtWidgetToApplicationContext(w),
3576 (XtPointer) XtInputWriteMask,
3579 Debug('o', fprintf(stderr, " adding pty write select\n"));
3582 else if (tpd->ptyOutputId != 0)
3587 (void) XtRemoveInput(tw->term.tpd->ptyOutputId);
3588 tw->term.tpd->ptyOutputId = (XtInputId) 0;
3589 Debug('o', fprintf(stderr, " removing pty write select\n"));
3591 Debug('o', fprintf(stderr, ">>_StartOrStopPtyOutput() finished\n"));
3595 static void VerticalScrollBarCallback(Widget wid, XtPointer client_data,
3596 XtPointer call_data)
3598 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
3599 XmScrollBarCallbackStruct *cb = (XmScrollBarCallbackStruct *) call_data;
3601 _DtTermPrimCursorOff((Widget) tw);
3603 (void) _DtTermPrimScrollTextTo((Widget) tw, cb->value -
3604 (tw->term.tpd->useHistoryBuffer ?
3605 tw->term.tpd->lastUsedHistoryRow : 0));
3606 /* we need to complete the scroll or it won't happen... */
3607 (void) _DtTermPrimScrollComplete((Widget) tw, True);
3608 if (cb->reason != XmCR_DRAG) {
3609 _DtTermPrimCursorOn((Widget) tw);
3614 static void WarningDialogOkCallback(Widget wid, XtPointer client_data,
3615 XtPointer call_data)
3617 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
3618 DtTermPrimData tpd = tw->term.tpd;
3620 tpd->warningDialogMapped = False;
3624 static void WarningDialogWMDestroyCallback(Widget wid, XtPointer client_data,
3625 XtPointer call_data)
3627 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
3628 DtTermPrimData tpd = tw->term.tpd;
3630 /* unmap the window (this is necessary for wm destroy callbacks)... */
3631 (void) XtUnmanageChild(tpd->warningDialog);
3632 /* call the OK callback... */
3633 (void) WarningDialogOkCallback(tpd->warningDialog, client_data,
3637 void _DtTermPrimWarningDialog(Widget w, char *msg)
3639 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
3641 DtTermPrimData tpd = tw->term.tpd;
3643 XmString titleString;
3647 if (!tpd->warningDialog) {
3650 (void) XtSetArg(arglist[i], XmNdialogStyle,
3651 XmDIALOG_PRIMARY_APPLICATION_MODAL); i++;
3654 GETMESSAGE(NL_SETN_Prim,2,"Terminal - Warning"),
3655 XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
3656 (void) XtSetArg(arglist[i], XmNdialogTitle, titleString); i++;
3657 tpd->warningDialog = XmCreateWarningDialog(w, "termWarning", arglist, i);
3658 (void) XmStringFree(titleString);
3660 (void) XtAddCallback(tpd->warningDialog,
3661 XmNokCallback, WarningDialogOkCallback, (XtPointer) w);
3662 /* find the shell widget so we can add a wmDestroy callback... */
3664 for (parent = tpd->warningDialog; !XtIsShell(parent);
3665 parent = XtParent(parent))
3667 (void) _DtTermPrimAddDeleteWindowCallback(parent,
3668 WarningDialogWMDestroyCallback, (XtPointer) w);
3673 XmStringGenerate(msg, XmFONTLIST_DEFAULT_TAG, XmCHARSET_TEXT, NULL);
3674 (void) XtSetArg(arglist[i], XmNmessageString, msgString); i++;
3675 (void) XtSetValues(tpd->warningDialog, arglist, i);
3676 (void) XmStringFree(msgString);
3678 if (!XtIsRealized(tpd->warningDialog)) {
3679 (void) XtRealizeWidget(tpd->warningDialog);
3680 (void) XtUnmanageChild(XmMessageBoxGetChild(tpd->warningDialog,
3681 XmDIALOG_CANCEL_BUTTON));
3682 (void) XtUnmanageChild(XmMessageBoxGetChild(tpd->warningDialog,
3683 XmDIALOG_HELP_BUTTON));
3686 /* limit wm functions to move, decorations to menu, border and title...
3689 (void) XtSetArg(arglist[i], XmNmwmFunctions, MWM_FUNC_MOVE); i++;
3690 (void) XtSetArg(arglist[i], XmNmwmDecorations,
3691 MWM_DECOR_MENU | MWM_DECOR_BORDER | MWM_DECOR_TITLE); i++;
3692 (void) XtSetValues(XtParent(tpd->warningDialog), arglist, i);
3694 if (tpd->windowMapped) {
3695 (void) XtManageChild(tpd->warningDialog);
3696 tpd->warningDialogMapped = True;
3697 tpd->mapWarningDialog = False;
3699 tpd->mapWarningDialog = True;
3703 typedef void _ManagerConstraintInitializeProc(Widget request, Widget new_w,
3704 ArgList args, Cardinal *num_args);
3705 static _ManagerConstraintInitializeProc *managerConstraintInitializeProc;
3708 ManagerConstraintInitializePatch(Widget request, Widget new_w, ArgList args,
3711 if (!XtIsSubclass(new_w, dtTermPrimitiveWidgetClass)) {
3712 (*managerConstraintInitializeProc)(request, new_w, args, num_args);
3719 XmManagerClassRec *mw = (XmManagerClassRec *) xmManagerWidgetClass;
3720 CoreClassRec *core = (CoreClassRec *) coreWidgetClass;
3721 static Boolean initted = False;
3723 /* only do this once... */
3724 _DtTermProcessLock();
3726 _DtTermProcessUnlock();
3730 if (core->core_class.class_inited) {
3731 (void) XtWarning("DtTermInitialize was not called before toolkit initialization\n");
3733 managerConstraintInitializeProc = mw->constraint_class.initialize;
3734 mw->constraint_class.initialize = ManagerConstraintInitializePatch;
3736 _DtTermProcessUnlock();
3740 _DtTermPrimPutEnv(char *c1, char *c2)
3742 char buffer[BUFSIZ];
3745 (void) strcpy(buffer, c1);
3746 (void) strcat(buffer, c2);
3747 c = XtMalloc(strlen(buffer) + 1);
3748 (void) strcpy(c, buffer);
3753 #if !defined(NL_CAT_LOCALE)
3754 #define NL_CAT_LOCALE 0
3755 #endif /* NL_CAT_LOCAL */
3758 _DtTermPrimGetMessage(
3766 static int first = 1;
3767 static nl_catd nlmsg_fd;
3769 _DtTermProcessLock();
3774 lang = (char *) getenv ("LANG");
3776 if (!lang || !(strcmp (lang, "C")))
3778 * If LANG is not set or if LANG=C, then there
3779 * is no need to open the message catalog - just
3780 * return the built-in string "s".
3782 nlmsg_fd = (nl_catd) -1;
3784 nlmsg_fd = catopen(filename, NL_CAT_LOCALE);
3786 _DtTermProcessUnlock();
3787 msg=catgets(nlmsg_fd,set,n,s);
3796 XPointer client_data,
3799 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
3802 PreRow(tw) = tw->term.tpd->cursorRow;
3803 PreColumn(tw) = tw->term.tpd->cursorColumn;
3805 /* vertical writing dependency here */
3806 PreStart(tw) = tw->term.tpd->cursorColumn;
3807 PreEnd(tw) = tw->term.tpd->cursorColumn;
3809 PreUnder(tw) = True;
3817 XPointer client_data,
3820 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
3822 _DtTermPrimRefreshText((Widget)tw, PreColumn(tw), PreRow(tw),
3825 PreUnder(tw) = False;
3832 DtTermPrimitiveWidget tw,
3833 XIMPreeditDrawCallbackStruct *call_data)
3835 short retcount, row, col, width;
3839 ** chg_first to chg_length in the preedit call_data
3840 ** structure indicates what should be deleted out of
3841 ** the preedit buffer, but this is terms of characters
3842 ** not bytes. We have stored the byte value in the
3843 ** term data structure, so we use that instead.
3845 if (call_data->chg_length && PreLen(tw)) {
3847 col = PreColumn(tw) + call_data->chg_first;
3848 width = call_data->chg_length;
3849 _DtTermPrimBufferDelete(tw->term.tpd->termBuffer, &row, &col,
3850 &width, &retchar, &retcount);
3853 ** We may want to consider freeing retcount @ retchar
3857 ** Refresh the text buffer -
3858 ** We must refresh to the rest of the line, because the
3859 ** preedit buffer may be in the middle of a line.
3861 _DtTermPrimRefreshText((Widget)tw, PreColumn(tw), PreRow(tw),
3870 DtTermPrimitiveWidget tw,
3871 XIMPreeditDrawCallbackStruct *call_data)
3873 TermSelectInfo selectInfo = tw->term.tpd->selectInfo;
3875 /* check for null feedback */
3876 if (call_data->text->feedback) {
3877 switch (*call_data->text->feedback) {
3884 /* clear any existing highlight first */
3885 selectInfo->ownPrimary = False;
3886 _DtTermPrimRenderRefreshTextLinear((Widget)tw,
3888 selectInfo->end - 1);
3889 selectInfo->ownPrimary =True;
3890 selectInfo->begin = rowColToPos(tw, PreRow(tw), PreColumn(tw));
3891 selectInfo->end = selectInfo->begin + PreLen(tw);
3892 _DtTermPrimRenderRefreshTextLinear((Widget)tw,
3894 selectInfo->end - 1);
3897 /* no highlight set, clear */
3898 selectInfo->ownPrimary = False;
3899 _DtTermPrimRenderRefreshTextLinear((Widget)tw,
3901 selectInfo->end - 1);
3910 XPointer client_data,
3911 XIMPreeditDrawCallbackStruct *call_data)
3913 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
3914 DtTermInsertCharMode savmode;
3919 /* are we under preedit? */
3924 ** This indicates a preedit buffer deletion
3926 if (!call_data->text) {
3927 PreeditHighlight(tw, call_data);
3928 PreeditDelete(tw, call_data);
3930 /* reset row/column position to beginning */
3931 tw->term.tpd->cursorRow = PreRow(tw);
3932 tw->term.tpd->cursorColumn = PreColumn(tw);
3933 _DtTermPrimCursorUpdate((Widget)tw);
3934 _DtTermPrimCursorOn((Widget)tw);
3939 ** At this point, we know there is a string in the
3940 ** preedit buffer that we must render.
3943 /* get preedit string */
3944 if (call_data->text->encoding_is_wchar) {
3946 /* preedit buffer is wchar, we must convert */
3947 wcs = call_data->text->string.wide_char;
3948 len = wcslen(wcs) * sizeof(wchar_t);
3949 mb = (unsigned char *)XtMalloc(len);
3951 /* check for invalid string */
3952 if (wcstombs((char *)mb, wcs, len) == -1)
3955 mb = (unsigned char *)call_data->text->string.multi_byte;
3959 ** First we must destroy the previous contents of
3960 ** the preedit buffer, if any, before we redraw
3963 PreeditDelete(tw, call_data);
3965 /* set insertion point */
3966 tw->term.tpd->cursorRow = PreRow(tw);
3967 tw->term.tpd->cursorColumn = PreColumn(tw);
3970 savmode = tw->term.tpd->insertCharMode;
3971 tw->term.tpd->insertCharMode = DtTERM_INSERT_CHAR_ON;
3972 len = strlen((char *)mb);
3973 _DtTermPrimInsertText((Widget)tw, mb, len);
3975 tw->term.tpd->insertCharMode = savmode;
3977 /* check highlight */
3978 PreeditHighlight(tw, call_data);
3981 _DtTermPrimCursorUpdate((Widget)tw);
3982 _DtTermPrimCursorOn((Widget)tw);
3989 XPointer client_data,
3990 XIMPreeditCaretCallbackStruct *call_data)
3992 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
3993 TermSelectInfo selectInfo = tw->term.tpd->selectInfo;
3994 Boolean chgcursor = False;
3997 switch (call_data->style) {
3998 case XIMIsInvisible:
3999 _DtTermPrimCursorOff((Widget)tw);
4002 case XIMIsSecondary:
4003 _DtTermPrimCursorOn((Widget)tw);
4009 switch (call_data->direction) {
4010 case XIMForwardChar:
4011 newpos = tw->term.tpd->cursorColumn + 1;
4014 case XIMBackwardChar:
4015 newpos = tw->term.tpd->cursorColumn - 1;
4019 newpos = PreStart(tw);
4023 newpos = PreEnd(tw);
4026 case XIMAbsolutePosition:
4027 newpos = PreColumn(tw) + call_data->position;
4031 /* do nothing we these movements */
4032 case XIMForwardWord:
4033 case XIMBackwardWord:
4037 case XIMPreviousLine:
4041 break; /* NOTREACHED */
4045 ** The input method shouldn't let us edit outside
4046 ** of the preedit buffer anyway, but we check just
4049 if (chgcursor && (newpos >= PreStart(tw)) && (newpos <= PreEnd(tw))) {
4050 tw->term.tpd->cursorColumn = newpos;
4051 _DtTermPrimCursorUpdate((Widget)tw);
4052 _DtTermPrimCursorOn((Widget)tw);
4054 ** refresh highlight (if any) because cursor
4055 ** movement hoses it up
4057 _DtTermPrimRenderRefreshTextLinear((Widget)tw,
4059 selectInfo->end - 1);
4069 XmDisplay xmDisplay;
4070 static Dimension thickness;
4072 xmDisplay = (XmDisplay)XmGetXmDisplay(XtDisplay(widget));
4074 if (xmDisplay->display.enable_thin_thickness) {
4081 value->addr = (XPointer)&thickness;