+#ifdef DEBUG
+ __CTRACE("quickch:bsize=%d,starts=%d,startw=%d,curw=%d,curs=%d,top=%d,bot=%d\n",
+ bsize, starts, startw, curw, curs, top, bot);
+#endif
+
+ /*
+ * Make sure that there is no overlap between the bottom and top
+ * regions and the middle scrolled block.
+ */
+ if (bot < curs)
+ bot = curs - 1;
+ if (top > starts)
+ top = starts;
+
+ n = startw - starts;
+
+#ifdef DEBUG
+ __CTRACE("#####################################\n");
+ for (i = 0; i < curscr->maxy; i++) {
+ __CTRACE("C: %d:", i);
+ __CTRACE(" 0x%x \n", curscr->lines[i]->hash);
+ for (j = 0; j < curscr->maxx; j++)
+ __CTRACE("%c",
+ curscr->lines[i]->line[j].ch);
+ __CTRACE("\n");
+ for (j = 0; j < curscr->maxx; j++)
+ __CTRACE("%x",
+ curscr->lines[i]->line[j].attr);
+ __CTRACE("\n");
+ __CTRACE("W: %d:", i);
+ __CTRACE(" 0x%x \n", win->lines[i]->hash);
+ __CTRACE(" 0x%x ", win->lines[i]->flags);
+ for (j = 0; j < win->maxx; j++)
+ __CTRACE("%c",
+ win->lines[i]->line[j].ch);
+ __CTRACE("\n");
+ for (j = 0; j < win->maxx; j++)
+ __CTRACE("%x",
+ win->lines[i]->line[j].attr);
+ __CTRACE("\n");
+ }
+#endif
+
+ /* So we don't have to call __hash() each time */
+ for (i = 0; i < win->maxx; i++) {
+ buf[i].ch = ' ';
+ buf[i].attr = 0;
+ }
+ blank_hash = __hash((char *) buf, win->maxx * __LDATASIZE);
+
+ /*
+ * Perform the rotation to maintain the consistency of curscr.
+ * This is hairy since we are doing an *in place* rotation.
+ * Invariants of the loop:
+ * - I is the index of the current line.
+ * - Target is the index of the target of line i.
+ * - Tmp1 points to current line (i).
+ * - Tmp2 and points to target line (target);
+ * - Cur_period is the index of the end of the current period.
+ * (see below).
+ *
+ * There are 2 major issues here that make this rotation non-trivial:
+ * 1. Scrolling in a scrolling region bounded by the top
+ * and bottom regions determined (whose size is sc_region).
+ * 2. As a result of the use of the mod function, there may be a
+ * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and
+ * 0 to 2, which then causes all odd lines not to be rotated.
+ * To remedy this, an index of the end ( = beginning) of the
+ * current 'period' is kept, cur_period, and when it is reached,
+ * the next period is started from cur_period + 1 which is
+ * guaranteed not to have been reached since that would mean that
+ * all records would have been reached. (think about it...).
+ *
+ * Lines in the rotation can have 3 attributes which are marked on the
+ * line so that curscr is consistent with the visual screen.
+ * 1. Not dirty -- lines inside the scrolled block, top region or
+ * bottom region.
+ * 2. Blank lines -- lines in the differential of the scrolling
+ * region adjacent to top and bot regions
+ * depending on scrolling direction.
+ * 3. Dirty line -- all other lines are marked dirty.
+ */
+ sc_region = bot - top + 1;
+ i = top;
+ tmp1 = curscr->lines[top];
+ cur_period = top;
+ for (j = top; j <= bot; j++) {
+ target = (i - top + n + sc_region) % sc_region + top;
+ tmp2 = curscr->lines[target];
+ curscr->lines[target] = tmp1;
+ /* Mark block as clean and blank out scrolled lines. */
+ clp = curscr->lines[target];
+#ifdef DEBUG
+ __CTRACE("quickch: n=%d startw=%d curw=%d i = %d target=%d ",
+ n, startw, curw, i, target);
+#endif
+ if ((target >= startw && target < curw) || target < top
+ || target > bot) {
+#ifdef DEBUG
+ __CTRACE("-- notdirty");
+#endif
+ win->lines[target]->flags &= ~__ISDIRTY;
+ } else if ((n > 0 && target >= top && target < top + n) ||
+ (n < 0 && target <= bot && target > bot + n)) {
+ if (clp->hash != blank_hash || memcmp(clp->line,
+ buf, win->maxx * __LDATASIZE) !=0) {
+ (void)memcpy(clp->line, buf,
+ win->maxx * __LDATASIZE);
+#ifdef DEBUG
+ __CTRACE("-- blanked out: dirty");
+#endif
+ clp->hash = blank_hash;
+ __touchline(win, target, 0, win->maxx - 1, 0);
+ } else {
+ __touchline(win, target, 0, win->maxx - 1, 0);
+#ifdef DEBUG
+ __CTRACE(" -- blank line already: dirty");
+#endif
+ }
+ } else {
+#ifdef DEBUG
+ __CTRACE(" -- dirty");
+#endif
+ __touchline(win, target, 0, win->maxx - 1, 0);
+ }
+#ifdef DEBUG
+ __CTRACE("\n");
+#endif
+ if (target == cur_period) {
+ i = target + 1;
+ tmp1 = curscr->lines[i];
+ cur_period = i;
+ } else {
+ tmp1 = tmp2;
+ i = target;
+ }
+ }
+#ifdef DEBUG
+ __CTRACE("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
+ for (i = 0; i < curscr->maxy; i++) {
+ __CTRACE("C: %d:", i);
+ for (j = 0; j < curscr->maxx; j++)
+ __CTRACE("%c",
+ curscr->lines[i]->line[j].ch);
+ __CTRACE("\n");
+ __CTRACE("W: %d:", i);
+ for (j = 0; j < win->maxx; j++)
+ __CTRACE("%c",
+ win->lines[i]->line[j].ch);
+ __CTRACE("\n");
+ }
+#endif
+ if (n != 0) {
+ WINDOW *wp;
+ scrolln(win, starts, startw, curs, bot, top);
+ /*
+ * Need to repoint any subwindow lines to the rotated
+ * line structured.
+ */
+ for (wp = win->nextp; wp != win; wp = wp->nextp)
+ __set_subwin(win, wp);