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 libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company *
25 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
26 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. *
27 * (c) Copyright 1993, 1994, 1996 Novell, Inc. *
28 * (c) Copyright 1996 Digital Equipment Corporation. *
29 * (c) Copyright 1996 FUJITSU LIMITED. *
30 * (c) Copyright 1996 Hitachi. *
33 #include <Xm/ScrollBar.h>
34 #include <Xm/XmPrivate.h>
36 #include "TermHeader.h"
37 #include "TermPrimDebug.h"
38 #include "TermPrimI.h"
39 #include "TermPrimP.h"
40 #include "TermPrimData.h"
41 #include "TermPrimLineDraw.h"
42 #include "TermPrimBufferP.h"
44 static void cursorToggle(Widget w);
48 timeoutCallback(XtPointer client_data, XtIntervalId *id)
50 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
51 struct termData *tpd = tw->term.tpd;
52 (void) cursorToggle((Widget) tw);
54 /* add a timeout... */
55 if (tw->term.blinkRate > 0) {
56 tpd->cursorTimeoutId =
57 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) tw),
59 (XtTimerCallbackProc) timeoutCallback, (XtPointer) tw);
61 tpd->cursorTimeoutId = (XtIntervalId) 0;
66 _DtTermPrimCursorChangeFocus(Widget w)
68 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
69 struct termData *tpd = tw->term.tpd;
72 if (tw->term.hasFocus) {
73 /* if the input method already didn't have focus or the cursor
74 * position has changed, then set the input method focus and
77 if ((!tpd->IMHasFocus) ||
78 (tpd->IMCursorColumn != tpd->cursorColumn) ||
79 (tpd->IMCursorRow != tpd->cursorRow)) {
80 tpd->IMHasFocus = True;
81 tpd->IMCursorColumn = tpd->cursorColumn;
82 tpd->IMCursorRow = tpd->cursorRow;
84 point.x = tpd->IMCursorColumn * tpd->cellWidth + tpd->offsetX;
85 point.y = tpd->IMCursorRow * tpd->cellHeight + tpd->offsetY +
87 DebugF('F', 1, fprintf(stderr,
88 "%s() %s calling %s\n",
89 "_DtTermPrimCursorChangeFocus",
91 "XmImVaSetFocusValues()"));
92 (void) XmImVaSetFocusValues(w,
93 XmNspotLocation, &point,
97 /* we want to blink now... */
98 if (tpd->cursorVisible && (!tpd->cursorTimeoutId) &&
99 (tw->term.blinkRate > 0) &&
100 (tpd->cursorState != CURSORoff)) {
101 Debug('F', fprintf(stderr,
102 ">>we got focus, turning off cursor...\n"));
103 (void) cursorToggle(w);
105 /* add a timeout... */
106 Debug('F', fprintf(stderr, ">>adding a timeout...\n"));
107 tpd->cursorTimeoutId =
109 XtWidgetToApplicationContext(w),
110 tw->term.blinkRate, timeoutCallback, (XtPointer) w);
113 if (tpd->IMHasFocus) {
114 tpd->IMHasFocus = False;
115 DebugF('F', 1, fprintf(stderr,
116 "%s() %s calling %s\n",
117 "_DtTermPrimCursorChangeFocus",
119 "XmImUnsetFocus()"));
120 /* remove input method focus... */
121 (void) XmImUnsetFocus(w);
124 /* we want to stop blinking now... */
125 if (tpd->cursorTimeoutId && (tpd->cursorState != CURSORoff)) {
126 Debug('F', fprintf(stderr, ">>we lost focus...\n"));
127 if (CURSORon == tpd->cursorState) {
128 /* we need to make the cursor visible... */
129 Debug('F', fprintf(stderr,
130 ">>turning on the cursor...\n"));
131 (void) cursorToggle(w);
133 /* we need to kill the timeout... */
134 Debug('F', fprintf(stderr, ">>removing the timeout...\n"));
135 (void) XtRemoveTimeOut(tpd->cursorTimeoutId);
136 tpd->cursorTimeoutId = (XtIntervalId) 0;
138 if (tw->term.blinkRate > 0) {
139 Debug('F', fprintf(stderr,
140 ">>we lost focus, but cursor is not on and blinking...\n"));
147 cursorToggle(Widget w)
149 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
150 struct termData *tpd = tw->term.tpd;
155 /* if the cursor is not visible or is off... */
156 if (!tpd->cursorVisible || (CURSORoff == tpd->cursorState)) {
161 cursorRow = tpd->cursorRow;
162 if (tpd->useHistoryBuffer) {
163 /* since topRow is used for history scrolling, move down by the
164 * (negative) number of rows in topRow...
166 cursorRow -= tpd->topRow;
169 if (cursorRow < tw->term.rows) {
170 if (DtTERM_CHAR_CURSOR_BOX == tw->term.charCursorStyle) {
172 y = cursorRow * tpd->cellHeight + tpd->offsetY;
173 height = tpd->cellHeight;
176 y = cursorRow * tpd->cellHeight + tpd->offsetY +
181 (void) XFillRectangle(XtDisplay(w),
183 XtWindow(w), /* Window */
184 tpd->cursorGC.gc, /* GC */
185 ((tpd->cursorColumn >= tw->term.columns) ?
186 tw->term.columns - 1 :
187 tpd->cursorColumn) * tpd->cellWidth + tpd->offsetX,
190 tpd->cellWidth, /* width */
191 height); /* height */
194 /* toggle the state flag... */
195 tpd->cursorState = (tpd->cursorState == CURSORon) ? CURSORblink : CURSORon;
201 _DtTermPrimCursorOn(Widget w)
203 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
204 struct termData *tpd = tw->term.tpd;
206 static Boolean alreadyActive = False;
208 enhValues enhancements;
209 unsigned long valueMask = 0L;
211 TermEnhInfoRec enhInfo;
214 /* if we are being called cyclically (by _DtTermPrimScrollWait ->
215 * _DtTermPrimExposeText -> _DtTermPrimCursorOn), just return...
217 _DtTermProcessLock();
219 /*DKS!!! vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
220 fprintf(stderr, "tell Dave _DtTermPrimCursorOn has alreadyActive == True\n");
221 /*DKS!!! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
222 _DtTermProcessUnlock();
226 /* this is where we will actually perform a pending scroll and
229 if (tw->term.jumpScroll && tpd->scroll.jump.scrolled) {
230 /* make sure we don't end up in an infinite loop... */
231 alreadyActive = True;
232 Debug('t', fprintf(stderr,
233 ">>_DtTermPrimCursorOn() calling _DtTermPrimScrollWait()\n"));
234 (void) _DtTermPrimScrollWait(w);
235 alreadyActive = False;
237 _DtTermProcessUnlock();
239 #ifdef DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF
240 if ( _DtTermPrimSelectIsAboveSelection(w,tpd->cursorRow,
241 tpd->cursorColumn)) {
242 _DtTermPrimSelectDisown(w) ;
244 #endif /* DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF */
246 /* update the input method spot location...
248 if ((tpd->IMCursorColumn != tpd->cursorColumn) ||
249 (tpd->IMCursorRow != tpd->cursorRow)) {
250 tpd->IMCursorColumn = tpd->cursorColumn;
251 tpd->IMCursorRow = tpd->cursorRow;
252 point.x = tpd->cursorColumn * tpd->cellWidth + tpd->offsetX;
253 point.y = tpd->cursorRow * tpd->cellHeight + tpd->offsetY + tpd->ascent;
254 DebugF('F', 1, fprintf(stderr,
255 "%s() %s calling %s\n",
256 "_DtTermPrimCursorOn",
258 "XmImVaSetValues()"));
259 (void) XmImVaSetValues(w,
260 XmNspotLocation, &point,
264 if (!tw->term.hasFocus) {
265 (void) fprintf(stderr,
266 "%s() %s calling %s\n",
267 "_DtTermPrimCursorOn",
270 (void) XmImUnsetFocus(w);
272 #endif /* NOT_NEEDED */
274 /* update the scrollbar and position indicator... */
275 (void) _DtTermPrimCursorUpdate(w);
277 /* if the cursor is not visible, we are done now... */
278 if (!tpd->cursorVisible) {
282 /* set up the GC... */
283 if (!tpd->cursorGC.gc) {
284 tpd->cursorGC.foreground =
285 tw->primitive.foreground ^ tw->core.background_pixel;
286 values.foreground = tpd->cursorGC.foreground;
287 values.function = GXxor;
288 tpd->cursorGC.gc = XCreateGC(XtDisplay(w), XtWindow(w),
289 GCForeground | GCFunction, &values);
292 /* update the cursor's foreground and background...
294 /* if we are past the lastUsedRow, or the column > width, use color
298 /* reasonable defaults... */
299 enhInfo.fg = tw->primitive.foreground;
300 enhInfo.bg = tw->core.background_pixel;
301 if (!((tpd->lastUsedRow <= tpd->topRow + tpd->cursorRow) ||
302 (_DtTermPrimBufferGetLineWidth(tpd->termBuffer,
303 tpd->topRow + tpd->cursorRow) <= MIN(tpd->cursorColumn,
304 tw->term.columns - 1)))) {
305 /* get the current enhancement to determine the color pair to use...
307 (void) _DtTermPrimBufferGetEnhancement(tpd->termBuffer,
309 tpd->topRow + tpd->cursorRow,
311 MIN(tpd->cursorColumn, tw->term.columns - 1),
313 &enhancements, /* enhancements */
314 &chunkWidth, /* width */
315 countNew); /* countWhich */
316 /* set our font and color from the enhancements... */
317 if (ENH_PROC(tpd->termBuffer)) {
318 (void) (*(ENH_PROC(tpd->termBuffer)))(w, enhancements, &enhInfo);
323 if (tpd->cursorGC.foreground != (enhInfo.fg ^ enhInfo.bg)) {
324 tpd->cursorGC.foreground = enhInfo.fg ^ enhInfo.bg;
325 values.foreground = enhInfo.fg ^ enhInfo.bg;
326 valueMask |= GCForeground;
329 (void) XChangeGC(XtDisplay(w), tpd->cursorGC.gc, valueMask, &values);
332 if (tpd->cursorState != CURSORoff) {
336 tpd->cursorState = CURSORon;
337 (void) cursorToggle(w);
339 if (tw->term.hasFocus) {
340 /* add a timeout... */
341 if (tw->term.blinkRate > 0) {
342 tpd->cursorTimeoutId =
343 XtAppAddTimeOut(XtWidgetToApplicationContext(w),
344 tw->term.blinkRate, (XtTimerCallbackProc) timeoutCallback,
352 _DtTermPrimCursorUpdate(Widget w)
354 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
355 struct termData *tpd = tw->term.tpd;
359 Boolean newMaximum = False;
360 Boolean newValue = False;
362 /* update the scrollbar... */
363 if (tw->term.verticalScrollBar) {
365 if (tpd->useHistoryBuffer) {
366 #define NO_SCROLL_REGION_HISTORY_SCROLL
367 #ifdef NO_SCROLL_REGION_HISTORY_SCROLL
368 value = tw->term.rows;
369 if ((tpd->scrollLockTopRow <= 0) &&
370 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
371 value += tpd->lastUsedHistoryRow;
373 #else /* NO_SCROLL_REGION_HISTORY_SCROLL */
374 value = tw->term.rows + tpd->lastUsedHistoryRow;
375 #endif /* NO_SCROLL_REGION_HISTORY_SCROLL */
377 value = tpd->lastUsedRow +
378 (tpd->useHistoryBuffer ? tpd->lastUsedHistoryRow : 0) -
379 tpd->scrollLockTopRow -
380 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
382 /* add in any non-exisstent rows below the last used row...
384 if (tpd->allowScrollBelowBuffer) {
385 /* add in a full screen (less one line and protected areas)
386 * below the last used row...
388 value += tw->term.rows - 1 -
389 tpd->scrollLockTopRow -
390 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
394 if (tw->term.verticalScrollBarMaximum != value) {
395 /* need to set maximum ... */
396 tw->term.verticalScrollBarMaximum = value;
400 if (tpd->useHistoryBuffer) {
401 value = tw->term.rows;
403 value = tw->term.rows -
404 tpd->scrollLockTopRow -
405 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
407 if (tw->term.verticalScrollBarSliderSize != value) {
408 /* need to set sliderSize ... */
409 tw->term.verticalScrollBarSliderSize = value;
410 (void) XtSetArg(arglist[i], XmNsliderSize,
411 tw->term.verticalScrollBarSliderSize); i++;
415 /* verticalScrollBarPageIncrement = verticalScrollBarSliderSize... */
416 if (tw->term.verticalScrollBarPageIncrement != value) {
417 /* need to set pageIncrement ... */
418 tw->term.verticalScrollBarPageIncrement = value;
419 (void) XtSetArg(arglist[i], XmNpageIncrement,
420 tw->term.verticalScrollBarPageIncrement); i++;
424 #ifdef NO_SCROLL_REGION_HISTORY_SCROLL
426 if (tpd->useHistoryBuffer && (tpd->scrollLockTopRow <= 0) &&
427 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
428 value += tpd->lastUsedHistoryRow;
430 #else /* NO_SCROLL_REGION_HISTORY_SCROLL */
431 value = tpd->topRow + tpd->lastUsedHistoryRow;
432 #endif /* NO_SCROLL_REGION_HISTORY_SCROLL */
434 if (tw->term.verticalScrollBarValue != value) {
435 /* need to set value... */
436 tw->term.verticalScrollBarValue = value;
437 (void) XtSetArg(arglist[i], XmNvalue,
438 tw->term.verticalScrollBarValue); i++;
442 /* check and see if value > max - size. If it is, adjust
445 if (tw->term.verticalScrollBarValue >
446 tw->term.verticalScrollBarMaximum -
447 tw->term.verticalScrollBarSliderSize) {
448 tw->term.verticalScrollBarMaximum =
449 tw->term.verticalScrollBarValue +
450 tw->term.verticalScrollBarSliderSize;
454 Debug('b', if (newMaximum || newValue) {
455 fprintf(stderr, ">>_DtTermPrimCursorUpdate: sb size=%d min=%d max=%d value=%d pginc=%d\n",
456 tw->term.verticalScrollBarSliderSize,
458 tw->term.verticalScrollBarMaximum,
459 tw->term.verticalScrollBarValue,
460 tw->term.verticalScrollBarPageIncrement);
464 (void) XtSetArg(arglist[i], XmNmaximum,
465 tw->term.verticalScrollBarMaximum); i++;
466 (void) XtSetValues(tw->term.verticalScrollBar, arglist, i);
467 } else if (newValue) {
468 /* only need to worry about setting value, slidersize, and
471 (void) XmScrollBarSetValues(tw->term.verticalScrollBar,
472 tw->term.verticalScrollBarValue,
474 tw->term.verticalScrollBarSliderSize,
477 tw->term.verticalScrollBarPageIncrement,
483 /* invoke any cursor motion callbacks... */
484 if (tw->term.statusChangeCallback) {
485 _DtTermPrimInvokeStatusChangeCallback(w);
490 _DtTermPrimCursorOff(Widget w)
492 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
493 struct termData *tpd = tw->term.tpd;
495 if (CURSORoff == tpd->cursorState) {
499 if (CURSORblink == tpd->cursorState) {
500 /* we need to restore the text... */
501 (void) cursorToggle(w);
504 /* reset the state flag... */
505 tpd->cursorState = CURSORoff;
507 /* turn off the timer... */
508 if (tpd->cursorTimeoutId) {
509 XtRemoveTimeOut(tpd->cursorTimeoutId);
511 tpd->cursorTimeoutId = (XtIntervalId) 0;
513 #ifdef DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF
514 if ( _DtTermPrimSelectIsAboveSelection(w,tpd->cursorRow,
515 tpd->cursorColumn)) {
516 _DtTermPrimSelectDisown(w) ;
518 #endif /* DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF */
522 ** _DtTermPrimCursorMove
524 ** Move the cursor to the specified location, scrolling the screen
528 ** If the new cursor position is exceeds the line width, the line
529 ** is padded with spaces up to (but not including) the new cursor
530 ** position (just adjust the line width since the line is already
531 ** filled with spaces).
532 ** if (cursorColumn == width)
533 ** then the cursor is at the end of the line
535 ** if (cursorColumn > width)
536 ** then the cursor is past the end of the line,
537 ** pad the line by setting width = cursorColumn
540 _DtTermPrimCursorMove
547 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
548 struct termData *tpd = tw->term.tpd;
551 ** Constrain col to buffer width.
557 else if (col >= COLS(tpd->termBuffer))
559 col = COLS(tpd->termBuffer) - 1;
561 tpd->cursorColumn = col;
564 ** Constraint row to >= 0. Height is open ended...
573 ** Scroll the window as necessary.
575 if (row < tpd->topRow) {
576 /* scroll so that row is the topRow... */
577 _DtTermPrimScrollTextTo(w, row);
579 } else if (row >= tpd->topRow + tw->term.rows) {
580 /* scroll so that row is the bottomRow... */
581 _DtTermPrimScrollTextTo(w, row - tw->term.rows + 1);
582 tpd->cursorRow = tw->term.rows - 1;
584 /* we just need to move the cursor... */
585 tpd->cursorRow = row - tpd->topRow;
590 ** Make sure the line is padded properly.
592 ** NOTE: we no longer do this, it might be necessary for hpterm3.0
593 ** but I will double check then
595 _DtTermPrimRenderPadLine(w);
600 _DtTermPrimSetCursorVisible
606 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
607 struct termData *tpd = tw->term.tpd;
609 /* make sure the cursor is off... */
610 _DtTermPrimCursorOff(w);
614 tpd->cursorVisible = True;
618 tpd->cursorVisible = False;
623 _DtTermPrimGetCursorVisible
628 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
629 struct termData *tpd = tw->term.tpd;
631 return(tpd->cursorVisible);