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[] = "$XConsortium: TermPrimCursor.c /main/1 1996/04/21 19:17:13 drk $";
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 1996 Digital Equipment Corporation. *
35 * (c) Copyright 1996 FUJITSU LIMITED. *
36 * (c) Copyright 1996 Hitachi. *
39 #include <Xm/ScrollBar.h>
40 #include <Xm/XmPrivate.h>
42 #include "TermHeader.h"
43 #include "TermPrimDebug.h"
44 #include "TermPrimI.h"
45 #include "TermPrimP.h"
46 #include "TermPrimData.h"
47 #include "TermPrimLineDraw.h"
48 #include "TermPrimBufferP.h"
50 static void cursorToggle(Widget w);
54 timeoutCallback(XtPointer client_data, XtIntervalId *id)
56 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
57 struct termData *tpd = tw->term.tpd;
58 (void) cursorToggle((Widget) tw);
60 /* add a timeout... */
61 if (tw->term.blinkRate > 0) {
62 tpd->cursorTimeoutId =
63 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) tw),
65 (XtTimerCallbackProc) timeoutCallback, (XtPointer) tw);
67 tpd->cursorTimeoutId = (XtIntervalId) 0;
72 _DtTermPrimCursorChangeFocus(Widget w)
74 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
75 struct termData *tpd = tw->term.tpd;
78 if (tw->term.hasFocus) {
79 /* if the input method already didn't have focus or the cursor
80 * position has changed, then set the input method focus and
83 if ((!tpd->IMHasFocus) ||
84 (tpd->IMCursorColumn != tpd->cursorColumn) ||
85 (tpd->IMCursorRow != tpd->cursorRow)) {
86 tpd->IMHasFocus = True;
87 tpd->IMCursorColumn = tpd->cursorColumn;
88 tpd->IMCursorRow = tpd->cursorRow;
90 point.x = tpd->IMCursorColumn * tpd->cellWidth + tpd->offsetX;
91 point.y = tpd->IMCursorRow * tpd->cellHeight + tpd->offsetY +
93 DebugF('F', 1, fprintf(stderr,
94 "%s() %s calling %s\n",
95 "_DtTermPrimCursorChangeFocus",
97 "XmImVaSetFocusValues()"));
98 (void) XmImVaSetFocusValues(w,
99 XmNspotLocation, &point,
103 /* we want to blink now... */
104 if (tpd->cursorVisible && (!tpd->cursorTimeoutId) &&
105 (tw->term.blinkRate > 0) &&
106 (tpd->cursorState != CURSORoff)) {
107 Debug('F', fprintf(stderr,
108 ">>we got focus, turning off cursor...\n"));
109 (void) cursorToggle(w);
111 /* add a timeout... */
112 Debug('F', fprintf(stderr, ">>adding a timeout...\n"));
113 tpd->cursorTimeoutId =
115 XtWidgetToApplicationContext(w),
116 tw->term.blinkRate, timeoutCallback, (XtPointer) w);
119 if (tpd->IMHasFocus) {
120 tpd->IMHasFocus = False;
121 DebugF('F', 1, fprintf(stderr,
122 "%s() %s calling %s\n",
123 "_DtTermPrimCursorChangeFocus",
125 "XmImUnsetFocus()"));
126 /* remove input method focus... */
127 (void) XmImUnsetFocus(w);
130 /* we want to stop blinking now... */
131 if (tpd->cursorTimeoutId && (tpd->cursorState != CURSORoff)) {
132 Debug('F', fprintf(stderr, ">>we lost focus...\n"));
133 if (CURSORon == tpd->cursorState) {
134 /* we need to make the cursor visible... */
135 Debug('F', fprintf(stderr,
136 ">>turning on the cursor...\n"));
137 (void) cursorToggle(w);
139 /* we need to kill the timeout... */
140 Debug('F', fprintf(stderr, ">>removing the timeout...\n"));
141 (void) XtRemoveTimeOut(tpd->cursorTimeoutId);
142 tpd->cursorTimeoutId = (XtIntervalId) 0;
144 if (tw->term.blinkRate > 0) {
145 Debug('F', fprintf(stderr,
146 ">>we lost focus, but cursor is not on and blinking...\n"));
153 cursorToggle(Widget w)
155 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
156 struct termData *tpd = tw->term.tpd;
161 /* if the cursor is not visible or is off... */
162 if (!tpd->cursorVisible || (CURSORoff == tpd->cursorState)) {
167 cursorRow = tpd->cursorRow;
168 if (tpd->useHistoryBuffer) {
169 /* since topRow is used for history scrolling, move down by the
170 * (negative) number of rows in topRow...
172 cursorRow -= tpd->topRow;
175 if (cursorRow < tw->term.rows) {
176 if (DtTERM_CHAR_CURSOR_BOX == tw->term.charCursorStyle) {
178 y = cursorRow * tpd->cellHeight + tpd->offsetY;
179 height = tpd->cellHeight;
182 y = cursorRow * tpd->cellHeight + tpd->offsetY +
187 (void) XFillRectangle(XtDisplay(w),
189 XtWindow(w), /* Window */
190 tpd->cursorGC.gc, /* GC */
191 ((tpd->cursorColumn >= tw->term.columns) ?
192 tw->term.columns - 1 :
193 tpd->cursorColumn) * tpd->cellWidth + tpd->offsetX,
196 tpd->cellWidth, /* width */
197 height); /* height */
200 /* toggle the state flag... */
201 tpd->cursorState = (tpd->cursorState == CURSORon) ? CURSORblink : CURSORon;
207 _DtTermPrimCursorOn(Widget w)
209 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
210 struct termData *tpd = tw->term.tpd;
212 static Boolean alreadyActive = False;
214 enhValues enhancements;
215 unsigned long valueMask = 0L;
217 TermEnhInfoRec enhInfo;
220 /* if we are being called cyclically (by _DtTermPrimScrollWait ->
221 * _DtTermPrimExposeText -> _DtTermPrimCursorOn), just return...
223 _DtTermProcessLock();
225 /*DKS!!! vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
226 fprintf(stderr, "tell Dave _DtTermPrimCursorOn has alreadyActive == True\n");
227 /*DKS!!! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
228 _DtTermProcessUnlock();
232 /* this is where we will actually perform a pending scroll and
235 if (tw->term.jumpScroll && tpd->scroll.jump.scrolled) {
236 /* make sure we don't end up in an infinite loop... */
237 alreadyActive = True;
238 Debug('t', fprintf(stderr,
239 ">>_DtTermPrimCursorOn() calling _DtTermPrimScrollWait()\n"));
240 (void) _DtTermPrimScrollWait(w);
241 alreadyActive = False;
243 _DtTermProcessUnlock();
245 #ifdef DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF
246 if ( _DtTermPrimSelectIsAboveSelection(w,tpd->cursorRow,
247 tpd->cursorColumn)) {
248 _DtTermPrimSelectDisown(w) ;
250 #endif /* DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF */
252 /* update the input method spot location...
254 if ((tpd->IMCursorColumn != tpd->cursorColumn) ||
255 (tpd->IMCursorRow != tpd->cursorRow)) {
256 tpd->IMCursorColumn = tpd->cursorColumn;
257 tpd->IMCursorRow = tpd->cursorRow;
258 point.x = tpd->cursorColumn * tpd->cellWidth + tpd->offsetX;
259 point.y = tpd->cursorRow * tpd->cellHeight + tpd->offsetY + tpd->ascent;
260 DebugF('F', 1, fprintf(stderr,
261 "%s() %s calling %s\n",
262 "_DtTermPrimCursorOn",
264 "XmImVaSetValues()"));
265 (void) XmImVaSetValues(w,
266 XmNspotLocation, &point,
270 if (!tw->term.hasFocus) {
271 (void) fprintf(stderr,
272 "%s() %s calling %s\n",
273 "_DtTermPrimCursorOn",
276 (void) XmImUnsetFocus(w);
278 #endif /* NOT_NEEDED */
280 /* update the scrollbar and position indicator... */
281 (void) _DtTermPrimCursorUpdate(w);
283 /* if the cursor is not visible, we are done now... */
284 if (!tpd->cursorVisible) {
288 /* set up the GC... */
289 if (!tpd->cursorGC.gc) {
290 tpd->cursorGC.foreground =
291 tw->primitive.foreground ^ tw->core.background_pixel;
292 values.foreground = tpd->cursorGC.foreground;
293 values.function = GXxor;
294 tpd->cursorGC.gc = XCreateGC(XtDisplay(w), XtWindow(w),
295 GCForeground | GCFunction, &values);
298 /* update the cursor's foreground and background...
300 /* if we are past the lastUsedRow, or the column > width, use color
304 /* reasonable defaults... */
305 enhInfo.fg = tw->primitive.foreground;
306 enhInfo.bg = tw->core.background_pixel;
307 if (!((tpd->lastUsedRow <= tpd->topRow + tpd->cursorRow) ||
308 (_DtTermPrimBufferGetLineWidth(tpd->termBuffer,
309 tpd->topRow + tpd->cursorRow) <= MIN(tpd->cursorColumn,
310 tw->term.columns - 1)))) {
311 /* get the current enhancement to determine the color pair to use...
313 (void) _DtTermPrimBufferGetEnhancement(tpd->termBuffer,
315 tpd->topRow + tpd->cursorRow,
317 MIN(tpd->cursorColumn, tw->term.columns - 1),
319 &enhancements, /* enhancements */
320 &chunkWidth, /* width */
321 countNew); /* countWhich */
322 /* set our font and color from the enhancements... */
323 if (ENH_PROC(tpd->termBuffer)) {
324 (void) (*(ENH_PROC(tpd->termBuffer)))(w, enhancements, &enhInfo);
329 if (tpd->cursorGC.foreground != (enhInfo.fg ^ enhInfo.bg)) {
330 tpd->cursorGC.foreground = enhInfo.fg ^ enhInfo.bg;
331 values.foreground = enhInfo.fg ^ enhInfo.bg;
332 valueMask |= GCForeground;
335 (void) XChangeGC(XtDisplay(w), tpd->cursorGC.gc, valueMask, &values);
338 if (tpd->cursorState != CURSORoff) {
342 tpd->cursorState = CURSORon;
343 (void) cursorToggle(w);
345 if (tw->term.hasFocus) {
346 /* add a timeout... */
347 if (tw->term.blinkRate > 0) {
348 tpd->cursorTimeoutId =
349 XtAppAddTimeOut(XtWidgetToApplicationContext(w),
350 tw->term.blinkRate, (XtTimerCallbackProc) timeoutCallback,
358 _DtTermPrimCursorUpdate(Widget w)
360 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
361 struct termData *tpd = tw->term.tpd;
365 Boolean newMaximum = False;
366 Boolean newValue = False;
368 /* update the scrollbar... */
369 if (tw->term.verticalScrollBar) {
371 if (tpd->useHistoryBuffer) {
372 #define NO_SCROLL_REGION_HISTORY_SCROLL
373 #ifdef NO_SCROLL_REGION_HISTORY_SCROLL
374 value = tw->term.rows;
375 if ((tpd->scrollLockTopRow <= 0) &&
376 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
377 value += tpd->lastUsedHistoryRow;
379 #else /* NO_SCROLL_REGION_HISTORY_SCROLL */
380 value = tw->term.rows + tpd->lastUsedHistoryRow;
381 #endif /* NO_SCROLL_REGION_HISTORY_SCROLL */
383 value = tpd->lastUsedRow +
384 (tpd->useHistoryBuffer ? tpd->lastUsedHistoryRow : 0) -
385 tpd->scrollLockTopRow -
386 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
388 /* add in any non-exisstent rows below the last used row...
390 if (tpd->allowScrollBelowBuffer) {
391 /* add in a full screen (less one line and protected areas)
392 * below the last used row...
394 value += tw->term.rows - 1 -
395 tpd->scrollLockTopRow -
396 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
400 if (tw->term.verticalScrollBarMaximum != value) {
401 /* need to set maximum ... */
402 tw->term.verticalScrollBarMaximum = value;
406 if (tpd->useHistoryBuffer) {
407 value = tw->term.rows;
409 value = tw->term.rows -
410 tpd->scrollLockTopRow -
411 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
413 if (tw->term.verticalScrollBarSliderSize != value) {
414 /* need to set sliderSize ... */
415 tw->term.verticalScrollBarSliderSize = value;
416 (void) XtSetArg(arglist[i], XmNsliderSize,
417 tw->term.verticalScrollBarSliderSize); i++;
421 /* verticalScrollBarPageIncrement = verticalScrollBarSliderSize... */
422 if (tw->term.verticalScrollBarPageIncrement != value) {
423 /* need to set pageIncrement ... */
424 tw->term.verticalScrollBarPageIncrement = value;
425 (void) XtSetArg(arglist[i], XmNpageIncrement,
426 tw->term.verticalScrollBarPageIncrement); i++;
430 #ifdef NO_SCROLL_REGION_HISTORY_SCROLL
432 if (tpd->useHistoryBuffer && (tpd->scrollLockTopRow <= 0) &&
433 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
434 value += tpd->lastUsedHistoryRow;
436 #else /* NO_SCROLL_REGION_HISTORY_SCROLL */
437 value = tpd->topRow + tpd->lastUsedHistoryRow;
438 #endif /* NO_SCROLL_REGION_HISTORY_SCROLL */
440 if (tw->term.verticalScrollBarValue != value) {
441 /* need to set value... */
442 tw->term.verticalScrollBarValue = value;
443 (void) XtSetArg(arglist[i], XmNvalue,
444 tw->term.verticalScrollBarValue); i++;
448 /* check and see if value > max - size. If it is, adjust
451 if (tw->term.verticalScrollBarValue >
452 tw->term.verticalScrollBarMaximum -
453 tw->term.verticalScrollBarSliderSize) {
454 tw->term.verticalScrollBarMaximum =
455 tw->term.verticalScrollBarValue +
456 tw->term.verticalScrollBarSliderSize;
460 Debug('b', if (newMaximum || newValue) {
461 fprintf(stderr, ">>_DtTermPrimCursorUpdate: sb size=%d min=%d max=%d value=%d pginc=%d\n",
462 tw->term.verticalScrollBarSliderSize,
464 tw->term.verticalScrollBarMaximum,
465 tw->term.verticalScrollBarValue,
466 tw->term.verticalScrollBarPageIncrement);
470 (void) XtSetArg(arglist[i], XmNmaximum,
471 tw->term.verticalScrollBarMaximum); i++;
472 (void) XtSetValues(tw->term.verticalScrollBar, arglist, i);
473 } else if (newValue) {
474 /* only need to worry about setting value, slidersize, and
477 (void) XmScrollBarSetValues(tw->term.verticalScrollBar,
478 tw->term.verticalScrollBarValue,
480 tw->term.verticalScrollBarSliderSize,
483 tw->term.verticalScrollBarPageIncrement,
489 /* invoke any cursor motion callbacks... */
490 if (tw->term.statusChangeCallback) {
491 _DtTermPrimInvokeStatusChangeCallback(w);
496 _DtTermPrimCursorOff(Widget w)
498 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
499 struct termData *tpd = tw->term.tpd;
501 if (CURSORoff == tpd->cursorState) {
505 if (CURSORblink == tpd->cursorState) {
506 /* we need to restore the text... */
507 (void) cursorToggle(w);
510 /* reset the state flag... */
511 tpd->cursorState = CURSORoff;
513 /* turn off the timer... */
514 if (tpd->cursorTimeoutId) {
515 XtRemoveTimeOut(tpd->cursorTimeoutId);
517 tpd->cursorTimeoutId = (XtIntervalId) 0;
519 #ifdef DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF
520 if ( _DtTermPrimSelectIsAboveSelection(w,tpd->cursorRow,
521 tpd->cursorColumn)) {
522 _DtTermPrimSelectDisown(w) ;
524 #endif /* DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF */
528 ** _DtTermPrimCursorMove
530 ** Move the cursor to the specified location, scrolling the screen
534 ** If the new cursor position is exceeds the line width, the line
535 ** is padded with spaces up to (but not including) the new cursor
536 ** position (just adjust the line width since the line is already
537 ** filled with spaces).
538 ** if (cursorColumn == width)
539 ** then the cursor is at the end of the line
541 ** if (cursorColumn > width)
542 ** then the cursor is past the end of the line,
543 ** pad the line by setting width = cursorColumn
546 _DtTermPrimCursorMove
553 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
554 struct termData *tpd = tw->term.tpd;
557 ** Constrain col to buffer width.
563 else if (col >= COLS(tpd->termBuffer))
565 col = COLS(tpd->termBuffer) - 1;
567 tpd->cursorColumn = col;
570 ** Constraint row to >= 0. Height is open ended...
579 ** Scroll the window as necessary.
581 if (row < tpd->topRow) {
582 /* scroll so that row is the topRow... */
583 _DtTermPrimScrollTextTo(w, row);
585 } else if (row >= tpd->topRow + tw->term.rows) {
586 /* scroll so that row is the bottomRow... */
587 _DtTermPrimScrollTextTo(w, row - tw->term.rows + 1);
588 tpd->cursorRow = tw->term.rows - 1;
590 /* we just need to move the cursor... */
591 tpd->cursorRow = row - tpd->topRow;
596 ** Make sure the line is padded properly.
598 ** NOTE: we no longer do this, it might be necessary for hpterm3.0
599 ** but I will double check then
601 _DtTermPrimRenderPadLine(w);
606 _DtTermPrimSetCursorVisible
612 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
613 struct termData *tpd = tw->term.tpd;
615 /* make sure the cursor is off... */
616 _DtTermPrimCursorOff(w);
620 tpd->cursorVisible = True;
624 tpd->cursorVisible = False;
629 _DtTermPrimGetCursorVisible
634 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
635 struct termData *tpd = tw->term.tpd;
637 return(tpd->cursorVisible);