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 "TermHeader.h"
40 #include "TermPrimDebug.h"
41 #include "TermPrimP.h"
42 #include "TermPrimData.h"
43 #include "TermPrimLineDraw.h"
44 #include "TermPrimBufferP.h"
46 static void cursorToggle(Widget w);
50 timeoutCallback(XtPointer client_data, XtIntervalId *id)
52 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) client_data;
53 struct termData *tpd = tw->term.tpd;
54 (void) cursorToggle((Widget) tw);
56 /* add a timeout... */
57 if (tw->term.blinkRate > 0) {
58 tpd->cursorTimeoutId =
59 XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) tw),
61 (XtTimerCallbackProc) timeoutCallback, (XtPointer) tw);
63 tpd->cursorTimeoutId = (XtIntervalId) 0;
68 _DtTermPrimCursorChangeFocus(Widget w)
70 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
71 struct termData *tpd = tw->term.tpd;
74 if (tw->term.hasFocus) {
75 /* if the input method already didn't have focus or the cursor
76 * position has changed, then set the input method focus and
79 if ((!tpd->IMHasFocus) ||
80 (tpd->IMCursorColumn != tpd->cursorColumn) ||
81 (tpd->IMCursorRow != tpd->cursorRow)) {
82 tpd->IMHasFocus = True;
83 tpd->IMCursorColumn = tpd->cursorColumn;
84 tpd->IMCursorRow = tpd->cursorRow;
86 point.x = tpd->IMCursorColumn * tpd->cellWidth + tpd->offsetX;
87 point.y = tpd->IMCursorRow * tpd->cellHeight + tpd->offsetY +
89 DebugF('F', 1, fprintf(stderr,
90 "%s() %s calling %s\n",
91 "_DtTermPrimCursorChangeFocus",
93 "XmImVaSetFocusValues()"));
94 (void) XmImVaSetFocusValues(w,
95 XmNspotLocation, &point,
99 /* we want to blink now... */
100 if (tpd->cursorVisible && (!tpd->cursorTimeoutId) &&
101 (tw->term.blinkRate > 0) &&
102 (tpd->cursorState != CURSORoff)) {
103 Debug('F', fprintf(stderr,
104 ">>we got focus, turning off cursor...\n"));
105 (void) cursorToggle(w);
107 /* add a timeout... */
108 Debug('F', fprintf(stderr, ">>adding a timeout...\n"));
109 tpd->cursorTimeoutId =
111 XtWidgetToApplicationContext(w),
112 tw->term.blinkRate, timeoutCallback, (XtPointer) w);
115 if (tpd->IMHasFocus) {
116 tpd->IMHasFocus = False;
117 DebugF('F', 1, fprintf(stderr,
118 "%s() %s calling %s\n",
119 "_DtTermPrimCursorChangeFocus",
121 "XmImUnsetFocus()"));
122 /* remove input method focus... */
123 (void) XmImUnsetFocus(w);
126 /* we want to stop blinking now... */
127 if (tpd->cursorTimeoutId && (tpd->cursorState != CURSORoff)) {
128 Debug('F', fprintf(stderr, ">>we lost focus...\n"));
129 if (CURSORon == tpd->cursorState) {
130 /* we need to make the cursor visible... */
131 Debug('F', fprintf(stderr,
132 ">>turning on the cursor...\n"));
133 (void) cursorToggle(w);
135 /* we need to kill the timeout... */
136 Debug('F', fprintf(stderr, ">>removing the timeout...\n"));
137 (void) XtRemoveTimeOut(tpd->cursorTimeoutId);
138 tpd->cursorTimeoutId = (XtIntervalId) 0;
140 if (tw->term.blinkRate > 0) {
141 Debug('F', fprintf(stderr,
142 ">>we lost focus, but cursor is not on and blinking...\n"));
149 cursorToggle(Widget w)
151 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
152 struct termData *tpd = tw->term.tpd;
157 /* if the cursor is not visible or is off... */
158 if (!tpd->cursorVisible || (CURSORoff == tpd->cursorState)) {
163 cursorRow = tpd->cursorRow;
164 if (tpd->useHistoryBuffer) {
165 /* since topRow is used for history scrolling, move down by the
166 * (negative) number of rows in topRow...
168 cursorRow -= tpd->topRow;
171 if (cursorRow < tw->term.rows) {
172 if (DtTERM_CHAR_CURSOR_BOX == tw->term.charCursorStyle) {
174 y = cursorRow * tpd->cellHeight + tpd->offsetY;
175 height = tpd->cellHeight;
178 y = cursorRow * tpd->cellHeight + tpd->offsetY +
183 (void) XFillRectangle(XtDisplay(w),
185 XtWindow(w), /* Window */
186 tpd->cursorGC.gc, /* GC */
187 ((tpd->cursorColumn >= tw->term.columns) ?
188 tw->term.columns - 1 :
189 tpd->cursorColumn) * tpd->cellWidth + tpd->offsetX,
192 tpd->cellWidth, /* width */
193 height); /* height */
196 /* toggle the state flag... */
197 tpd->cursorState = (tpd->cursorState == CURSORon) ? CURSORblink : CURSORon;
203 _DtTermPrimCursorOn(Widget w)
205 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
206 struct termData *tpd = tw->term.tpd;
208 static Boolean alreadyActive = False;
210 enhValues enhancements;
211 unsigned long valueMask = 0L;
213 TermEnhInfoRec enhInfo;
216 /* if we are being called cyclically (by _DtTermPrimScrollWait ->
217 * _DtTermPrimExposeText -> _DtTermPrimCursorOn), just return...
219 _DtTermProcessLock();
221 /*DKS!!! vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
222 fprintf(stderr, "tell Dave _DtTermPrimCursorOn has alreadyActive == True\n");
223 /*DKS!!! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
224 _DtTermProcessUnlock();
228 /* this is where we will actually perform a pending scroll and
231 if (tw->term.jumpScroll && tpd->scroll.jump.scrolled) {
232 /* make sure we don't end up in an infinite loop... */
233 alreadyActive = True;
234 Debug('t', fprintf(stderr,
235 ">>_DtTermPrimCursorOn() calling _DtTermPrimScrollWait()\n"));
236 (void) _DtTermPrimScrollWait(w);
237 alreadyActive = False;
239 _DtTermProcessUnlock();
241 #ifdef DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF
242 if ( _DtTermPrimSelectIsAboveSelection(w,tpd->cursorRow,
243 tpd->cursorColumn)) {
244 _DtTermPrimSelectDisown(w) ;
246 #endif /* DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF */
248 /* update the input method spot location...
250 if ((tpd->IMCursorColumn != tpd->cursorColumn) ||
251 (tpd->IMCursorRow != tpd->cursorRow)) {
252 tpd->IMCursorColumn = tpd->cursorColumn;
253 tpd->IMCursorRow = tpd->cursorRow;
254 point.x = tpd->cursorColumn * tpd->cellWidth + tpd->offsetX;
255 point.y = tpd->cursorRow * tpd->cellHeight + tpd->offsetY + tpd->ascent;
256 DebugF('F', 1, fprintf(stderr,
257 "%s() %s calling %s\n",
258 "_DtTermPrimCursorOn",
260 "XmImVaSetValues()"));
261 (void) XmImVaSetValues(w,
262 XmNspotLocation, &point,
266 if (!tw->term.hasFocus) {
267 (void) fprintf(stderr,
268 "%s() %s calling %s\n",
269 "_DtTermPrimCursorOn",
272 (void) XmImUnsetFocus(w);
274 #endif /* NOT_NEEDED */
276 /* update the scrollbar and position indicator... */
277 (void) _DtTermPrimCursorUpdate(w);
279 /* if the cursor is not visible, we are done now... */
280 if (!tpd->cursorVisible) {
284 /* set up the GC... */
285 if (!tpd->cursorGC.gc) {
286 tpd->cursorGC.foreground =
287 tw->primitive.foreground ^ tw->core.background_pixel;
288 values.foreground = tpd->cursorGC.foreground;
289 values.function = GXxor;
290 tpd->cursorGC.gc = XCreateGC(XtDisplay(w), XtWindow(w),
291 GCForeground | GCFunction, &values);
294 /* update the cursor's foreground and background...
296 /* if we are past the lastUsedRow, or the column > width, use color
300 /* reasonable defaults... */
301 enhInfo.fg = tw->primitive.foreground;
302 enhInfo.bg = tw->core.background_pixel;
303 if (!((tpd->lastUsedRow <= tpd->topRow + tpd->cursorRow) ||
304 (_DtTermPrimBufferGetLineWidth(tpd->termBuffer,
305 tpd->topRow + tpd->cursorRow) <= MIN(tpd->cursorColumn,
306 tw->term.columns - 1)))) {
307 /* get the current enhancement to determine the color pair to use...
309 (void) _DtTermPrimBufferGetEnhancement(tpd->termBuffer,
311 tpd->topRow + tpd->cursorRow,
313 MIN(tpd->cursorColumn, tw->term.columns - 1),
315 &enhancements, /* enhancements */
316 &chunkWidth, /* width */
317 countNew); /* countWhich */
318 /* set our font and color from the enhancements... */
319 if (ENH_PROC(tpd->termBuffer)) {
320 (void) (*(ENH_PROC(tpd->termBuffer)))(w, enhancements, &enhInfo);
325 if (tpd->cursorGC.foreground != enhInfo.fg ^ enhInfo.bg) {
326 tpd->cursorGC.foreground = enhInfo.fg ^ enhInfo.bg;
327 values.foreground = enhInfo.fg ^ enhInfo.bg;
328 valueMask |= GCForeground;
331 (void) XChangeGC(XtDisplay(w), tpd->cursorGC.gc, valueMask, &values);
334 if (tpd->cursorState != CURSORoff) {
338 tpd->cursorState = CURSORon;
339 (void) cursorToggle(w);
341 if (tw->term.hasFocus) {
342 /* add a timeout... */
343 if (tw->term.blinkRate > 0) {
344 tpd->cursorTimeoutId =
345 XtAppAddTimeOut(XtWidgetToApplicationContext(w),
346 tw->term.blinkRate, (XtTimerCallbackProc) timeoutCallback,
354 _DtTermPrimCursorUpdate(Widget w)
356 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
357 struct termData *tpd = tw->term.tpd;
361 Boolean newMaximum = False;
362 Boolean newValue = False;
364 /* update the scrollbar... */
365 if (tw->term.verticalScrollBar) {
367 if (tpd->useHistoryBuffer) {
368 #define NO_SCROLL_REGION_HISTORY_SCROLL
369 #ifdef NO_SCROLL_REGION_HISTORY_SCROLL
370 value = tw->term.rows;
371 if ((tpd->scrollLockTopRow <= 0) &&
372 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
373 value += tpd->lastUsedHistoryRow;
375 #else /* NO_SCROLL_REGION_HISTORY_SCROLL */
376 value = tw->term.rows + tpd->lastUsedHistoryRow;
377 #endif /* NO_SCROLL_REGION_HISTORY_SCROLL */
379 value = tpd->lastUsedRow +
380 (tpd->useHistoryBuffer ? tpd->lastUsedHistoryRow : 0) -
381 tpd->scrollLockTopRow -
382 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
384 /* add in any non-exisstent rows below the last used row...
386 if (tpd->allowScrollBelowBuffer) {
387 /* add in a full screen (less one line and protected areas)
388 * below the last used row...
390 value += tw->term.rows - 1 -
391 tpd->scrollLockTopRow -
392 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
396 if (tw->term.verticalScrollBarMaximum != value) {
397 /* need to set maximum ... */
398 tw->term.verticalScrollBarMaximum = value;
402 if (tpd->useHistoryBuffer) {
403 value = tw->term.rows;
405 value = tw->term.rows -
406 tpd->scrollLockTopRow -
407 (tw->term.rows - 1 - tpd->scrollLockBottomRow);
409 if (tw->term.verticalScrollBarSliderSize != value) {
410 /* need to set sliderSize ... */
411 tw->term.verticalScrollBarSliderSize = value;
412 (void) XtSetArg(arglist[i], XmNsliderSize,
413 tw->term.verticalScrollBarSliderSize); i++;
417 /* verticalScrollBarPageIncrement = verticalScrollBarSliderSize... */
418 if (tw->term.verticalScrollBarPageIncrement != value) {
419 /* need to set pageIncrement ... */
420 tw->term.verticalScrollBarPageIncrement = value;
421 (void) XtSetArg(arglist[i], XmNpageIncrement,
422 tw->term.verticalScrollBarPageIncrement); i++;
426 #ifdef NO_SCROLL_REGION_HISTORY_SCROLL
428 if (tpd->useHistoryBuffer && (tpd->scrollLockTopRow <= 0) &&
429 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
430 value += tpd->lastUsedHistoryRow;
432 #else /* NO_SCROLL_REGION_HISTORY_SCROLL */
433 value = tpd->topRow + tpd->lastUsedHistoryRow;
434 #endif /* NO_SCROLL_REGION_HISTORY_SCROLL */
436 if (tw->term.verticalScrollBarValue != value) {
437 /* need to set value... */
438 tw->term.verticalScrollBarValue = value;
439 (void) XtSetArg(arglist[i], XmNvalue,
440 tw->term.verticalScrollBarValue); i++;
444 /* check and see if value > max - size. If it is, adjust
447 if (tw->term.verticalScrollBarValue >
448 tw->term.verticalScrollBarMaximum -
449 tw->term.verticalScrollBarSliderSize) {
450 tw->term.verticalScrollBarMaximum =
451 tw->term.verticalScrollBarValue +
452 tw->term.verticalScrollBarSliderSize;
456 Debug('b', if (newMaximum || newValue) {
457 fprintf(stderr, ">>_DtTermPrimCursorUpdate: sb size=%d min=%d max=%d value=%d pginc=%d\n",
458 tw->term.verticalScrollBarSliderSize,
460 tw->term.verticalScrollBarMaximum,
461 tw->term.verticalScrollBarValue,
462 tw->term.verticalScrollBarPageIncrement);
466 (void) XtSetArg(arglist[i], XmNmaximum,
467 tw->term.verticalScrollBarMaximum); i++;
468 (void) XtSetValues(tw->term.verticalScrollBar, arglist, i);
469 } else if (newValue) {
470 /* only need to worry about setting value, slidersize, and
473 (void) XmScrollBarSetValues(tw->term.verticalScrollBar,
474 tw->term.verticalScrollBarValue,
476 tw->term.verticalScrollBarSliderSize,
479 tw->term.verticalScrollBarPageIncrement,
485 /* invoke any cursor motion callbacks... */
486 if (tw->term.statusChangeCallback) {
487 _DtTermPrimInvokeStatusChangeCallback(w);
492 _DtTermPrimCursorOff(Widget w)
494 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
495 struct termData *tpd = tw->term.tpd;
497 if (CURSORoff == tpd->cursorState) {
501 if (CURSORblink == tpd->cursorState) {
502 /* we need to restore the text... */
503 (void) cursorToggle(w);
506 /* reset the state flag... */
507 tpd->cursorState = CURSORoff;
509 /* turn off the timer... */
510 if (tpd->cursorTimeoutId) {
511 XtRemoveTimeOut(tpd->cursorTimeoutId);
513 tpd->cursorTimeoutId = (XtIntervalId) 0;
515 #ifdef DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF
516 if ( _DtTermPrimSelectIsAboveSelection(w,tpd->cursorRow,
517 tpd->cursorColumn)) {
518 _DtTermPrimSelectDisown(w) ;
520 #endif /* DISOWN_SELECTION_ON_CURSOR_ON_OR_OFF */
524 ** _DtTermPrimCursorMove
526 ** Move the cursor to the specified location, scrolling the screen
530 ** If the new cursor position is exceeds the line width, the line
531 ** is padded with spaces up to (but not including) the new cursor
532 ** position (just adjust the line width since the line is already
533 ** filled with spaces).
534 ** if (cursorColumn == width)
535 ** then the cursor is at the end of the line
537 ** if (cursorColumn > width)
538 ** then the cursor is past the end of the line,
539 ** pad the line by setting width = cursorColumn
542 _DtTermPrimCursorMove
549 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
550 struct termData *tpd = tw->term.tpd;
553 ** Constrain col to buffer width.
559 else if (col >= COLS(tpd->termBuffer))
561 col = COLS(tpd->termBuffer) - 1;
563 tpd->cursorColumn = col;
566 ** Constraint row to >= 0. Height is open ended...
575 ** Scroll the window as necessary.
577 if (row < tpd->topRow) {
578 /* scroll so that row is the topRow... */
579 _DtTermPrimScrollTextTo(w, row);
581 } else if (row >= tpd->topRow + tw->term.rows) {
582 /* scroll so that row is the bottomRow... */
583 _DtTermPrimScrollTextTo(w, row - tw->term.rows + 1);
584 tpd->cursorRow = tw->term.rows - 1;
586 /* we just need to move the cursor... */
587 tpd->cursorRow = row - tpd->topRow;
592 ** Make sure the line is padded properly.
594 ** NOTE: we no longer do this, it might be necessary for hpterm3.0
595 ** but I will double check then
597 _DtTermPrimRenderPadLine(w);
602 _DtTermPrimSetCursorVisible
608 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
609 struct termData *tpd = tw->term.tpd;
611 /* make sure the cursor is off... */
612 _DtTermPrimCursorOff(w);
616 tpd->cursorVisible = True;
620 tpd->cursorVisible = False;
625 _DtTermPrimGetCursorVisible
630 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
631 struct termData *tpd = tw->term.tpd;
633 return(tpd->cursorVisible);