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: TermPrimScroll.c /main/1 1996/04/21 19:19:17 drk $";
26 #endif /* VERBOSE_REV_INFO */
30 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
31 * (c) Copyright 1993, 1994 International Business Machines Corp. *
32 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
33 * (c) Copyright 1993, 1994 Novell, Inc. *
36 #include "TermHeader.h"
37 #include "TermPrimDebug.h"
38 #include "TermPrimP.h"
39 #include "TermPrimI.h"
40 #include "TermPrimData.h"
41 #include "TermPrimBuffer.h"
44 waitOnCopyArea(Widget w)
46 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
47 struct termData *tpd = tw->term.tpd;
51 while (tpd->scrollInProgress) {
52 (void) XWindowEvent(XtDisplay(w), XtWindow(w), ExposureMask, ev);
55 Debug('e', fprintf(stderr,
56 ">>_waitOnCopyArea() Expose event received\n"));
58 /* refresh the border... */
59 (void) _DtTermPrimDrawShadow(w);
61 /* just refresh the exposed area...
63 Debug('e', fprintf(stderr,
64 ">>_waitOnCopyArea() exposing Expose area\n"));
65 Debug('e', fprintf(stderr,
66 ">> x=%d y=%d width=%d height=%d\n",
67 ev->xexpose.x, ev->xexpose.y,
68 ev->xexpose.width, ev->xexpose.height));
69 (void) _DtTermPrimExposeText(w, ev->xexpose.x, ev->xexpose.y,
70 ev->xexpose.width, ev->xexpose.height, True);
74 /* refresh the exposed area and, if this is the last graphics
75 * exposure, we are done and can fall through to the noExpose
78 Debug('e', fprintf(stderr,
79 ">>_DtTermPrimScrollWait() GraphicsExpose event received, count=%d\n",
80 ev->xgraphicsexpose.count));
81 Debug('e', fprintf(stderr,
82 ">>_waitOnCopyArea() exposing GraphicsExpose area\n"));
83 Debug('e', fprintf(stderr,
84 ">> x=%d y=%d width=%d height=%d\n",
85 ev->xgraphicsexpose.x, ev->xgraphicsexpose.y,
86 ev->xgraphicsexpose.width, ev->xgraphicsexpose.height));
87 (void) _DtTermPrimExposeText(w,
88 ev->xgraphicsexpose.x, ev->xgraphicsexpose.y,
89 ev->xgraphicsexpose.width, ev->xgraphicsexpose.height,
91 if (ev->xgraphicsexpose.count > 0) {
98 Debug('e', fprintf(stderr,
99 ">>_waitOnCopyArea() NoExpose event received\n"));
100 tpd->scrollInProgress = False;
107 _DtTermPrimScrollWait(Widget w)
109 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
110 struct termData *tpd = tw->term.tpd;
116 Debug('s', fprintf(stderr, ">>_DtTermPrimScrollWait() starting\n"));
117 Debug('s', fprintf(stderr,
118 ">>_DtTermPrimScrollWait() scrollLines=%d, scrollsPending=%d\n",
119 tpd->scroll.jump.scrollLines, tpd->scroll.jump.scrollsPending));
121 /* make sure the cursor is off... */
122 (void) _DtTermPrimCursorOff(w);
124 if (tpd->scroll.jump.scrollLines != 0) {
125 /* flush so that we can be sure the output was visible before we
128 (void) XFlush(XtDisplay(w));
130 /* figure out the height of the copy area... */
131 if (tpd->scroll.jump.scrollLines > 0) {
132 /* scrolling memory up... */
133 Debug('s', fprintf(stderr,
134 ">>_DtTermPrimScrollWait() up, scrollLines=%d cellHeight=%d\n",
135 tpd->scroll.jump.scrollLines, tpd->cellHeight));
136 if (tpd->scroll.jump.scrollLines >=
137 tpd->scrollBottomRow - tpd->scrollTopRow + 1) {
138 /* a full screen or more -- we can avoid the copy area... */
139 tpd->scrollHeight = 0;
140 exposeY = tpd->offsetY + tpd->cellHeight *
142 exposeHeight = tpd->cellHeight *
143 (tpd->scrollBottomRow - tpd->scrollTopRow + 1);
144 Debug('s', fprintf(stderr,
145 ">>_DtTermPrimScrollWait() height=%d expose Y=%d height=%d\n",
146 tpd->scrollHeight, exposeY, exposeHeight));
148 tpd->scrollHeight = tpd->cellHeight *
149 (tpd->scrollBottomRow - tpd->scrollTopRow + 1 -
150 tpd->scroll.jump.scrollLines);
151 tpd->scrollSrcY = tpd->offsetY + tpd->cellHeight *
152 (tpd->scrollTopRow + tpd->scroll.jump.scrollLines);
153 tpd->scrollDestY = tpd->offsetY + tpd->cellHeight *
155 exposeY = tpd->offsetY + tpd->cellHeight *
156 (tpd->scrollBottomRow + 1 -
157 tpd->scroll.jump.scrollLines);
158 exposeHeight = tpd->cellHeight *
159 (tpd->scroll.jump.scrollLines);
160 Debug('s', fprintf(stderr,
161 ">>_DtTermPrimScrollWait() height=%d SrcY=%d DestY=%d expose Y=%d height=%d\n",
162 tpd->scrollHeight, tpd->scrollSrcY, tpd->scrollDestY,
163 exposeY, exposeHeight));
166 /* scrolling memory down... */
167 Debug('s', fprintf(stderr,
168 ">>_DtTermPrimScrollWait() down, scrollLines=%d cellHeight=%d\n",
169 tpd->scroll.jump.scrollLines, tpd->cellHeight));
170 if (tpd->scroll.jump.scrollLines <=
171 -(tpd->scrollBottomRow - tpd->scrollTopRow + 1)) {
172 /* a full screen or more -- we can avoid the copy area... */
173 tpd->scrollHeight = 0;
174 exposeY = tpd->offsetY + tpd->cellHeight *
176 exposeHeight = tpd->cellHeight *
177 (tpd->scrollBottomRow - tpd->scrollTopRow + 1);
178 Debug('s', fprintf(stderr,
179 ">>_DtTermPrimScrollWait() height=%d expose Y=%d height=%d\n",
180 tpd->scrollHeight, exposeY, exposeHeight));
182 /* remember: scrollLines is **NEGATIVE**...
184 tpd->scrollHeight = tpd->cellHeight * (tpd->scrollBottomRow -
185 tpd->scrollTopRow + 1 - -tpd->scroll.jump.scrollLines);
186 tpd->scrollSrcY = tpd->offsetY + tpd->cellHeight *
188 tpd->scrollDestY = tpd->offsetY + tpd->cellHeight *
189 (tpd->scrollTopRow + -tpd->scroll.jump.scrollLines);
190 exposeY = tpd->offsetY + tpd->cellHeight *
192 exposeHeight = tpd->cellHeight *
193 (-tpd->scroll.jump.scrollLines);
194 Debug('s', fprintf(stderr,
195 ">>_DtTermPrimScrollWait() height=%d SrcY=%d DestY=%d expose Y=%d height=%d\n",
196 tpd->scrollHeight, tpd->scrollSrcY, tpd->scrollDestY,
197 exposeY, exposeHeight));
201 /* we need to do a copy area... */
202 if (tpd->scrollHeight > 0) {
203 /* calculate scroll area... */
204 tpd->scrollWidth = tpd->cellWidth * tw->term.columns;
205 tpd->scrollSrcX = tpd->offsetX;
206 tpd->scrollDestX = tpd->offsetX;
208 (void) XCopyArea(XtDisplay(w),
210 XtWindow(w), /* Source */
211 XtWindow(w), /* Destination */
212 tpd->renderGC.gc, /* GC */
213 tpd->scrollSrcX, /* source X */
214 tpd->scrollSrcY, /* source Y */
215 tpd->scrollWidth, /* width */
216 tpd->scrollHeight, /* height */
217 tpd->scrollDestX, /* destination X */
218 tpd->scrollDestY); /* destination Y */
219 tpd->scrollInProgress = True;
222 /* expose the exposed area. We need to expose the exposed area
223 * as well as any lines that have been changed. While we really
224 * could just expose the exposed area and then go back and fill
225 * in any remaining lines that have the flag set, we will first
226 * fill in any lines above the expose area with their flag set,
227 * fill in the expose area, and then fill in any lines below
228 * the expose area with their flag set. This fills things in
229 * from top to bottom which is much more pleasing visually.
231 Debug('s', fprintf(stderr,
232 ">>_DtTermPrimScrollWait() exposing scroll area\n"));
233 Debug('s', fprintf(stderr,
234 ">> x=%d y=%d width=%d height=%d\n",
237 tpd->cellWidth * tw->term.columns,
240 /* set scrollLines == 0, or renderText will not render them... */
241 scrolledLines = tpd->scroll.jump.scrollLines;
242 tpd->scroll.jump.scrollLines = 0;
243 /* clear the scrolled flag... */
244 tpd->scroll.jump.scrolled = False;
246 /* refresh any lines above the expose zone that have their
247 * scrollRefreshRows flag set...
249 for (i = 0; i < (exposeY - tpd->offsetX) / tpd->cellHeight; i++) {
250 if (tpd->scrollRefreshRows[i]) {
251 (void) _DtTermPrimRefreshText(w, 0, i, tw->term.columns, i);
254 /* expose the refresh expose area... */
255 (void) _DtTermPrimExposeText(w,
258 tpd->cellWidth * tw->term.columns,
262 /* refresh any lines below the expose zone that have their
263 * scrollRefreshRows flag set...
265 for (i = (exposeY - tpd->offsetX + exposeHeight) / tpd->cellHeight;
266 i < tw->term.rows; i++) {
267 if (tpd->scrollRefreshRows[i]) {
268 (void) _DtTermPrimRefreshText(w, 0, i, tw->term.columns, i);
272 if (tpd->scrollHeight > 0)
273 tpd->scroll.jump.scrollsPending++;
275 (void) _DtTermPrimCursorUpdate(w);
277 /* scrollLines == 0...
280 /* flush so that we can be sure the output was visible before we
283 (void) XFlush(XtDisplay(w));
285 /* clear the scrolled flag... */
286 tpd->scroll.jump.scrolled = False;
288 /* refresh any lines below the expose zone that have their
289 * scrollRefreshRows flag set...
292 for (i = 0; i < tw->term.rows; i++) {
293 if (tpd->scrollRefreshRows[i]) {
294 (void) _DtTermPrimRefreshText(w, 0, i, tw->term.columns, i);
299 while (tpd->scroll.jump.scrollsPending > 0) {
300 (void) waitOnCopyArea(w);
301 tpd->scroll.jump.scrollsPending--;
304 Debug('s', fprintf(stderr, ">>_DtTermPrimScrollWait() finished\n"));
308 doActualScroll(Widget w, int lines)
310 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
311 struct termData *tpd = tw->term.tpd;
316 /* make sure the cursor is off... */
317 (void) _DtTermPrimCursorOff(w);
319 /* figure out the height of the copy area... */
321 /* scrolling memory up... */
322 if (lines >= tpd->scrollBottomRow - tpd->scrollTopRow + 1) {
323 /* we are scrolling a full screen or more, so there is nothing
326 tpd->scrollHeight = 0;
327 exposeY = tpd->offsetY + tpd->cellHeight * tpd->scrollTopRow;
328 exposeHeight = tpd->cellHeight *
329 (tpd->scrollBottomRow - tpd->scrollTopRow + 1);
331 tpd->scrollHeight = tpd->cellHeight *
332 (tpd->scrollBottomRow - tpd->scrollTopRow + 1 - lines);
333 tpd->scrollSrcY = tpd->offsetY + tpd->cellHeight *
334 (tpd->scrollTopRow + lines);
335 tpd->scrollDestY = tpd->offsetY + tpd->cellHeight *
338 /* expose bottom lines lines... */
339 exposeY = tpd->offsetY + tpd->cellHeight *
340 (tpd->scrollBottomRow + 1 - lines);
341 exposeHeight = tpd->cellHeight * lines;
344 /* scrolling memory down... */
345 /* lines are negative -- make positive... */
347 if (lines >= tw->term.rows) {
348 /* we are scrolling a full screen or more, so there is nothing
351 tpd->scrollHeight = 0;
352 exposeY = tpd->offsetY + tpd->cellHeight * tpd->scrollTopRow;
353 exposeHeight = tpd->cellHeight *
354 (tpd->scrollBottomRow - tpd->scrollTopRow + 1);
356 tpd->scrollHeight = tpd->cellHeight *
357 (tpd->scrollBottomRow - tpd->scrollTopRow + 1 - lines);
358 tpd->scrollSrcY = tpd->offsetY + tpd->cellHeight *
360 tpd->scrollDestY = tpd->offsetY + tpd->cellHeight *
361 (tpd->scrollTopRow + lines);
363 /* expose top lines lines... */
364 exposeY = tpd->offsetY + tpd->cellHeight *
366 exposeHeight = tpd->cellHeight * lines;
370 /* scroll the display... */
371 if (tpd->scrollHeight > 0) {
372 /* calculate scroll area... */
373 tpd->scrollWidth = tpd->cellWidth * tw->term.columns;
374 tpd->scrollSrcX = tpd->offsetX;
375 tpd->scrollDestX = tpd->offsetX;
377 /* copy the area... */
378 XCopyArea(XtDisplay(w), /* Display */
379 XtWindow(w), /* Source */
380 XtWindow(w), /* Destination */
381 tpd->renderGC.gc, /* GC */
382 tpd->scrollSrcX, /* source X */
383 tpd->scrollSrcY, /* source Y */
384 tpd->scrollWidth, /* width */
385 tpd->scrollHeight, /* height */
386 tpd->scrollDestX, /* destination X */
387 tpd->scrollDestY); /* destination Y */
388 tpd->scrollInProgress = True;
391 /* clear the old area... */
392 (void) XFillRectangle(XtDisplay(w), /* Display */
393 XtWindow(w), /* Drawable */
394 tpd->clearGC.gc, /* GC */
395 tpd->offsetX, /* x */
397 tw->term.columns * tpd->cellWidth,
399 exposeHeight); /* height */
401 /* expose the old area... */
402 (void) _DtTermPrimExposeText(w,
405 tw->term.columns * tpd->cellWidth,
406 exposeHeight, False);
408 (void) _DtTermPrimCursorUpdate(w);
411 /**************************************************************************
413 * _DtTermPrimScrollText(): scroll the terminal window
416 * Widget w: widget to scroll
417 * int lines: lines to scroll
424 * This function will scroll the terminals window. It supports
425 * both jump scroll and non-jump scroll (single line at a time).
426 * In jump scroll, the maximum number of lines that will be
427 * scrolled at a time is the length of the display. This insures
428 * that all text will be displayed for at least an instant.
430 * In jump scroll mode, scrolling is performed as follows:
432 * - Scroll request is made:
434 * + Number of lines to scroll is incremented.
436 * + If the number of lines is < the length of the screen,
437 * rendering is discontinued and the actual scroll request is
438 * delayed until the the cursor is turned back on (i.e.,
439 * select(2) says there is no more input on the pty).
441 * + If the number of lines is >= the length of the screen, the
442 * copy area is performed, and the world blocks on exposure
443 * events on the window. When a no-expose request, or the
444 * last graphics expose request is received, any remaining
445 * lines will be queue'ed up.
447 * - The code that processes data coming over the pty determines
448 * via select(2) that there is no data to be read.
450 * + The copy area is performed, and the world blocks on
451 * exposure events on the window. When a no-expose request,
452 * or the last graphics expose request is received, the
453 * scroll is complete.
456 * In non-jump scroll mode, the following actions are performed:
458 * - If there is no scroll in progress, the copy area is performed.
459 * Any additional input is processed as normal.
461 * - When the generated no-expose or final graphics expose event is
462 * processed, the pending scroll flag is cleared.
464 * - If there is a scroll in progress, the new scroll is queued up.
465 * Any remaining pty input will be queued and the pty will be
466 * dropped from Xt input select.
468 * - When the generated no-expose or final graphics expose event is
469 * processed, the queued copy area will be performed. Any queued
470 * pty input will be processed and the pty will be added to the
475 _DtTermPrimScrollText(Widget w, short lines)
477 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
478 struct termData *tpd = tw->term.tpd;
484 /* figure out what our new top row will be. It is limitied by the
485 * beginning of memory (i.e., we can't scroll above line 0) and the
486 * lastUsedRow (i.e., we can't scroll the lastUsedRow off the screen).
487 * we will then use this value to clip lines...
489 oldTopRow = tpd->topRow;
491 newTopRow = tpd->topRow + lines;
492 /* don't scroll past the lastUsedRow... */
493 if (newTopRow > (tpd->lastUsedRow - tpd->scrollLockTopRow)) {
494 newTopRow = tpd->lastUsedRow - tpd->scrollLockTopRow;
497 if (tpd->useHistoryBuffer) {
498 if ((tpd->topRow + tpd->lastUsedHistoryRow) >= -lines)
499 newTopRow = tpd->topRow - -lines;
501 newTopRow = -tpd->lastUsedHistoryRow;
503 if (tpd->topRow >= -lines)
504 newTopRow = tpd->topRow - -lines;
510 /* adjust lines to the clipped newTopRow... */
511 lines = newTopRow - oldTopRow;
513 /* we don't need to do any for 0... */
517 if ((tw->term.jumpScroll &&
518 ((lines + tpd->scroll.jump.scrollLines) >
520 tpd->scrollLockTopRow -
521 (tw->term.rows - 1 - tpd->scrollLockBottomRow)))) ||
522 ((lines + tpd->scroll.jump.scrollLines) <
524 tpd->scrollLockTopRow -
525 (tw->term.rows - 1 - tpd->scrollLockBottomRow))) ||
526 (tpd->scrollTopRow != tpd->scrollLockTopRow) ||
527 (tpd->scrollBottomRow != tpd->scrollLockBottomRow)) {
528 /* scroll out the queued up jump scroll lines... */
529 if (tpd->scroll.jump.scrollLines != 0) {
530 (void) _DtTermPrimScrollWait(w);
534 /* move the memory locked region in screen memory...
536 /* Assuming a 24 line buffer with lock on 10 and 20 and 30 lines
537 * of screen buffer, with one below and scrolling 3 lines, we do
540 * oooooLLLLLLLLLL LLLLo
541 * ||||||||||||||||||||||||||||||
542 * 000000000011111111112222222222
543 * 012345678901234567890123456789
545 * move lines 15-17 to the top of the buffer:
547 * ooooooooLLLLLLLLLL LLLLo
548 * ||||||||||||||||||||||||||||||
549 * 111000000000011111112222222222
550 * 567012345678901234890123456789
552 * move line 29 to the bottom of the unlocked area:
554 * ooooooooLLLLLLLLLL LLLL
555 * ||||||||||||||||||||||||||||||
556 * 111000000000011111112222222222
557 * 567012345678901234890123495678
559 * clear the top2 lines and move it to the bottom of the
562 * ooooooLLLLLLLLLL LLLL
563 * ||||||||||||||||||||||||||||||
564 * 100000000001111111222221122222
565 * 701234567890123489012345695678
569 /* if we have a history buffer and we are going to be scrolling lines
570 * off of the buffer, we should move them into the history buffer.
572 if ((tpd->scrollLockTopRow == 0) &&
573 (tpd->scrollLockBottomRow >= (tw->term.rows - 1))) {
577 /* first move the top lock area... */
578 if (tpd->scrollLockTopRow > 0) {
579 (void) _DtTermPrimBufferMoveLockArea(tpd->termBuffer,
580 tpd->topRow + lines, tpd->topRow, tpd->scrollLockTopRow);
583 /* now move the bottom lock area... */
584 if (tpd->scrollLockBottomRow < (tw->term.rows - 1)) {
585 /* if we are moving up, let's move as many rows as we can from
586 * bottom offscreen memory...
590 if ((lines > 0) && (tpd->bufferRows > (tpd->topRow + tw->term.rows))) {
591 /* clip lines2 to the number of lines that we can obtain
592 * from the bottom of the buffer...
595 if (lines2 > (tpd->bufferRows - (tpd->topRow + tw->term.rows))) {
596 lines2 = tpd->bufferRows - (tpd->topRow + tw->term.rows);
601 (void) _DtTermPrimBufferMoveLockArea(tpd->termBuffer,
602 tpd->topRow + tpd->scrollLockBottomRow - lines2,
603 tpd->topRow + tpd->scrollLockBottomRow,
604 (tw->term.rows - 1) - tpd->scrollLockBottomRow);
608 /* figure out how many lines we will need to take from the
611 lines2 = lines - lines2;
613 for (i = 0; i < lines2; i++) {
614 (void) _DtTermPrimBufferClearLine(tpd->termBuffer, i, 0);
616 (void) _DtTermPrimBufferMoveLockArea(tpd->termBuffer,
619 tpd->topRow + tpd->scrollLockBottomRow + 1 - lines);
625 tpd->topRow = newTopRow;
627 if (tw->term.jumpScroll) {
630 /* queue up the lines for scrolling... */
631 tpd->scroll.jump.scrollLines += lines;
632 tpd->scroll.jump.scrolled = True;
633 tpd->scrollTopRow = tpd->scrollLockTopRow;
634 tpd->scrollBottomRow = tpd->scrollLockBottomRow;
636 /* scroll out the scrollRefreshRows flags now... */
637 /* NOTE: we loose the refresh flag for all rows that are scrolled
638 * off. The result of this is that if we do a scroll up followed
639 * by a scroll down, we will (at a minimum) refresh the top and
640 * bottom lines. One workaround would be to tripple the buffer
641 * and keep the lines that get scrolled off the top or bottom.
642 * This would probably break something, since there are times
643 * that the scrolled off line gets modified or even cleared (such
644 * as delete line off of the top of the display), so this might
645 * not be a very good idea.
648 /* scroll them up... */
649 for (i = tpd->scrollTopRow;
650 i <= tpd->scrollBottomRow - lines; i++) {
651 tpd->scrollRefreshRows[i] =
652 tpd->scrollRefreshRows[i + lines];
654 /* set the rest... */
655 for (; i <= tpd->scrollBottomRow; i++) {
656 tpd->scrollRefreshRows[i] = True;
659 /* remember, lines is negative... */
660 for (i = tpd->scrollBottomRow;
661 i >= tpd->scrollTopRow + -lines; i--) {
662 tpd->scrollRefreshRows[i] =
663 tpd->scrollRefreshRows[i - -lines];
665 for (; i >= tpd->scrollTopRow; i--) {
666 tpd->scrollRefreshRows[i] = True;
670 /* non jump-scroll...
672 if (tpd->scrollInProgress) {
673 /* let's queue up the scroll and bail out...
675 tpd->scroll.nojump.pendingScrollLines += lines;
676 /*DKS!!! v v v v v v v v v v v v v v v v v v v v v v */
677 if (tpd->scroll.nojump.pendingScrollLines > 1)
678 (void) fprintf(stderr,
679 "tell Dave _DtTermPrimScrollText has pendingScrollLines=%d\n",
680 tpd->scroll.nojump.pendingScrollLines);
681 /*DKS!!! ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ */
682 tpd->scroll.nojump.pendingScroll = True;
683 tpd->scroll.nojump.pendingScrollTopRow = tpd->scrollLockTopRow;
684 tpd->scroll.nojump.pendingScrollBottomRow = tpd->scrollLockBottomRow;
685 (void) _DtTermPrimStartOrStopPtyInput(w);
689 /* no scroll in progress, let's scroll it... */
690 tpd->scrollTopRow = tpd->scrollLockTopRow;
691 tpd->scrollBottomRow = tpd->scrollLockBottomRow;
692 (void) doActualScroll(w, lines);
695 /* This case: (tpd->scrollLockTopRow > 0)
696 is handled elsewhere.
698 if ( lines > 0 && tpd->scrollLockBottomRow < (tw->term.rows-1)) {
699 _DtTermPrimSelectMoveLines(w, tpd->scrollLockTopRow + lines,
700 tpd->scrollLockTopRow,
701 tpd->scrollLockBottomRow - tpd->scrollLockTopRow);
708 _DtTermPrimScrollTextTo(Widget w, short topRow)
710 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
711 struct termData *tpd = tw->term.tpd;
714 if (topRow == tpd->topRow) {
715 /* already there... */
719 (void) _DtTermPrimScrollText(w, topRow - tpd->topRow);
724 _DtTermPrimScrollTextArea(Widget w, short scrollStart, short scrollLength,
725 short scrollDistance)
727 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
728 struct termData *tpd = tw->term.tpd;
735 if (scrollDistance > 0) {
736 /* scrolling text up... */
737 if (tpd->lastUsedRow <= tpd->topRow + scrollStart) {
738 /* scrolling past lastUsedRow -- nothing to scroll... */
743 /* clip the length... */
744 if (scrollStart + scrollLength > tw->term.rows) {
745 scrollLength = tw->term.rows - scrollStart;
748 /* we don't need to do anything for 0 distance... */
749 if (0 == scrollDistance) {
753 /* if we are in jumpscroll mode and:
754 * -our region differs (scrollTopRow and scrollBottomRow), or
755 * -we are going to queue more lines than the scroll region
756 * we need to complete the queued scroll...
758 if (tw->term.jumpScroll &&
759 ((scrollDistance + tpd->scroll.jump.scrollLines > scrollLength) ||
760 (scrollDistance + tpd->scroll.jump.scrollLines < -scrollLength) ||
761 (tpd->scrollTopRow != scrollStart) ||
762 (tpd->scrollBottomRow != scrollStart + scrollLength - 1))) {
763 /* scroll out the queued up jump scroll lines... */
764 if (tpd->scroll.jump.scrolled != 0) {
765 (void) _DtTermPrimScrollWait(w);
769 if (tw->term.jumpScroll) {
772 /* queue up the lines for scrolling... */
773 tpd->scroll.jump.scrollLines += scrollDistance;
774 tpd->scroll.jump.scrolled = True;
775 tpd->scrollTopRow = scrollStart;
776 tpd->scrollBottomRow = scrollStart + scrollLength - 1;
778 /* scroll out the scrollRefreshRows flags now... */
779 if (scrollDistance > 0) {
780 /* scroll them up... */
781 for (i = tpd->scrollTopRow;
782 i <= tpd->scrollBottomRow - scrollDistance; i++) {
783 tpd->scrollRefreshRows[i] =
784 tpd->scrollRefreshRows[i + scrollDistance];
786 /* set the rest... */
787 for (; i <= tpd->scrollBottomRow; i++) {
788 tpd->scrollRefreshRows[i] = True;
791 for (i = tpd->scrollBottomRow;
792 i >= tpd->scrollTopRow + -scrollDistance; i--) {
793 tpd->scrollRefreshRows[i] =
794 tpd->scrollRefreshRows[i - -scrollDistance];
796 for (; i >= tpd->scrollTopRow; i--) {
797 tpd->scrollRefreshRows[i] = True;
801 /* non jump scroll...
803 if (tpd->scrollInProgress) {
804 /* let's queue up the scroll and bail out...
806 tpd->scroll.nojump.pendingScrollLines += scrollDistance;
807 /*DKS!!! v v v v v v v v v v v v v v v v v v v v v v */
808 if (tpd->scroll.nojump.pendingScrollLines > 1)
809 (void) fprintf(stderr,
810 "tell Dave _DtTermPrimScrollText has pendingScrollLines=%d\n",
811 tpd->scroll.nojump.pendingScrollLines);
812 /*DKS!!! ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ */
813 tpd->scroll.nojump.pendingScroll = True;
814 tpd->scroll.nojump.pendingScrollTopRow = scrollStart;
815 tpd->scroll.nojump.pendingScrollBottomRow =
816 scrollStart + scrollLength - 1;
817 (void) _DtTermPrimStartOrStopPtyInput(w);
821 /* no scroll in progress, let's scroll it... */
822 tpd->scrollTopRow = scrollStart;
823 tpd->scrollBottomRow = scrollStart + scrollLength - 1;
824 (void) doActualScroll(w, scrollDistance);
825 tpd->scrollInProgress = True;
829 /**************************************************************************
831 * _DtTermPrimScrollComplete(): finish a scroll. This is normall called
832 * to complete a non-jump scroll, or if it is necessary to
833 * complete and flush any scroll.
836 * Widget w: widget to scroll
843 * This function is used in non-jump scroll only!!!
845 * This function is called by the Term widget when a no-expose or
846 * final graphics expose event is received (which was generated by
847 * the previous scroll's copy area). It will invoke the scroll that
848 * was queued up and caused pty input to be blocked.
852 _DtTermPrimScrollComplete(Widget w, Boolean flush)
854 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
855 struct termData *tpd = tw->term.tpd;
857 if (tw->term.jumpScroll) {
861 /* we need to finish any pending scrolls...
863 /* In jump scroll, all we need to do is to invoke the scroll.
864 * _DtTermPrimScrollWait() will perform the actual copy area and
865 * wait for the generated graphics expose / no expose events...
867 if (tpd->scroll.jump.scrolled) {
868 Debug('s', fprintf(stderr,
869 ">>_DtTermPrimScrollComplete() calling _DtTermPrimScrollWait()\n"));
870 (void) _DtTermPrimScrollWait(w);
874 /* non-jump scroll...
877 if (flush && tpd->scrollInProgress) {
878 /* if we have a pending scroll, we need to wait for it to
879 * complete. Normally, we would service this out of the
880 * XtMainLoop() dispatch loop, but for some reason we need
883 (void) waitOnCopyArea(w);
884 tpd->scrollInProgress = False;
887 if (!tw->term.jumpScroll && tpd->scroll.nojump.pendingScroll) {
888 /* do the queued scroll... */
889 tpd->scrollTopRow = tpd->scroll.nojump.pendingScrollTopRow;
890 tpd->scrollBottomRow = tpd->scroll.nojump.pendingScrollBottomRow;
891 (void) doActualScroll(w, tpd->scroll.nojump.pendingScrollLines);
893 /* no lines pending, but there is a scroll in progress... */
894 tpd->scroll.nojump.pendingScrollLines = 0;
895 tpd->scrollInProgress = True;
896 tpd->scroll.nojump.pendingScroll = False;
899 /* wait for it to complete...
901 (void) waitOnCopyArea(w);
902 tpd->scrollInProgress = False;
904 /* If there is any pending input or if we need to reinstall
905 * the input select, force a pty read...
907 (void) XtAppAddTimeOut(XtWidgetToApplicationContext(w),
908 0, _DtTermPrimForcePtyRead, (XtPointer) w);
915 _DtTermPrimScrollCompleteIfNecessary(Widget w, short scrollTopRow,
916 short scrollBottomRow, short lines)
918 DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
919 struct termData *tpd = tw->term.tpd;
920 short maxJumpScrollLines;
922 if ((scrollTopRow != tpd->scrollTopRow) ||
923 (scrollBottomRow != tpd->scrollBottomRow)) {
924 (void) _DtTermPrimScrollComplete(w, True);
928 if (tw->term.jumpScroll) {
929 maxJumpScrollLines = tpd->scrollBottomRow - tpd->scrollTopRow + 1;
930 if ((lines + tpd->scroll.jump.scrollLines > maxJumpScrollLines) ||
931 (lines + tpd->scroll.jump.scrollLines < -maxJumpScrollLines))
932 (void) _DtTermPrimScrollComplete(w, True);
935 if (!tw->term.jumpScroll && tpd->scroll.nojump.pendingScroll) {
936 (void) _DtTermPrimScrollComplete(w, True);