home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1994, 1995, 1999 by Paul Mattes.
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- */
-
- /*
- * scroll.c
- * Scrollbar support
- */
-
- #include "globals.h"
- #include "appres.h"
- #include "ctlr.h"
-
- #include "ctlrc.h"
- #include "kybdc.h"
- #include "screenc.h"
- #include "scrollc.h"
- #include "selectc.h"
- #include "statusc.h"
-
- /* Globals */
- Boolean scroll_initted = False;
-
- /* Statics */
- static unsigned char **buf_save = (unsigned char **) NULL;
- static struct ea **ea_save = (struct ea **) NULL;
- static int n_saved = 0;
- static int scroll_next = 0;
- static float thumb_top = 0.0;
- static float thumb_top_base = 0.0;
- static float thumb_shown = 1.0;
- static int scrolled_back = 0;
- static Boolean need_saving = True;
- static Boolean vscreen_swapped = False;
- static char *sbuf = CN;
- static int sa_bufsize;
- static char *zbuf = CN;
- static void sync_scroll(int sb);
- static void save_image(void);
- static void scroll_reset(void);
-
- /*
- * Initialize (or re-initialize) the scrolling parameters and save area.
- */
- void
- scroll_init(void)
- {
- register int i;
- int sa_size;
- unsigned char *s;
-
- if (appres.save_lines % maxROWS)
- appres.save_lines =
- ((appres.save_lines+maxROWS-1)/maxROWS) * maxROWS;
- if (!appres.save_lines)
- appres.save_lines = maxROWS;
- if (sbuf != CN) {
- XtFree(sbuf);
- XtFree(zbuf);
- XtFree((char *)buf_save);
- XtFree((char *)ea_save);
- }
- sa_size = appres.save_lines + maxROWS;
- buf_save = (unsigned char **)XtCalloc(sizeof(unsigned char *), sa_size);
- ea_save = (struct ea **)XtCalloc(sizeof(struct ea *), sa_size);
- sa_bufsize = (sa_size * (sizeof(unsigned char) + sizeof(struct ea))) * maxCOLS;
- sbuf = XtMalloc(sa_bufsize);
- zbuf = XtMalloc(maxCOLS);
- (void) memset(zbuf, '\0', maxCOLS);
- s = (unsigned char *)sbuf;
- for (i = 0; i < sa_size; s += maxCOLS, i++)
- buf_save[i] = s;
- for (i = 0; i < sa_size; s += (maxCOLS * sizeof(struct ea)), i++)
- ea_save[i] = (struct ea *)s;
- scroll_reset();
- scroll_initted = True;
- }
-
- /*
- * Reset the scrolling parameters and erase the save area.
- */
- static void
- scroll_reset(void)
- {
- (void) memset(sbuf, 0, sa_bufsize);
- scroll_next = 0;
- n_saved = 0;
- scrolled_back = 0;
- thumb_top_base = thumb_top = 0.0;
- thumb_shown = 1.0;
- need_saving = True;
- screen_set_thumb(thumb_top, thumb_shown);
- enable_cursor(True);
- }
-
- /*
- * Save <n> lines of data from the top of the screen.
- */
- void
- scroll_save(int n, Boolean trim_blanks)
- {
- int i;
-
- /* Trim trailing blank lines from 'n', if requested */
- if (trim_blanks) {
- while (n) {
- if (memcmp((char *)(screen_buf+((n-1)*COLS)),
- zbuf, COLS))
- break;
- else
- n--;
- }
- if (!n)
- return;
- }
-
- /* Scroll to bottom on "output". */
- if (scrolled_back)
- sync_scroll(0);
-
- /* Save the screen contents. */
- for (i = 0; i < n; i++) {
- if (i < COLS) {
- (void) memmove(buf_save[scroll_next],
- screen_buf+(i*COLS),
- COLS);
- (void) memmove(ea_save[scroll_next],
- (ea_buf+(i*COLS)),
- COLS*sizeof(struct ea));
- if (COLS < maxCOLS) {
- (void) memset((char *)(buf_save[scroll_next] + COLS), '\0',
- maxCOLS - COLS);
- (void) memset((char *)(ea_save[scroll_next] + COLS), '\0',
- (maxCOLS - COLS)*sizeof(struct ea));
- }
- } else {
- (void) memset((char *)buf_save[scroll_next], '\0',
- maxCOLS);
- (void) memset((char *)ea_save[scroll_next], '\0',
- maxCOLS*sizeof(struct ea));
- }
- scroll_next = (scroll_next + 1) % appres.save_lines;
- if (n_saved < appres.save_lines)
- n_saved++;
- }
-
- /* Reset the thumb. */
- thumb_top_base =
- thumb_top =
- ((float)n_saved / (float)(appres.save_lines + maxROWS));
- thumb_shown = 1.0 - thumb_top;
- screen_set_thumb(thumb_top, thumb_shown);
- }
-
- /*
- * Add blank lines to the scroll buffer to make it a multiple of the
- * screen size.
- */
- void
- scroll_round(void)
- {
- int n;
-
- if (!(n_saved % maxROWS))
- return;
-
- /* Zero the scroll buffer. */
- for (n = maxROWS - (n_saved % maxROWS); n; n--) {
- (void) memset((char *)buf_save[scroll_next], '\0', maxCOLS);
- (void) memset((char *)ea_save[scroll_next], '\0',
- maxCOLS*sizeof(struct ea));
- scroll_next = (scroll_next + 1) % appres.save_lines;
- if (n_saved < appres.save_lines)
- n_saved++;
- }
-
- /* Reset the thumb. */
- thumb_top_base =
- thumb_top =
- ((float)n_saved / (float)(appres.save_lines + maxROWS));
- thumb_shown = 1.0 - thumb_top;
- screen_set_thumb(thumb_top, thumb_shown);
- }
-
- /*
- * Jump to the bottom of the scroll buffer.
- */
- void
- scroll_to_bottom(void)
- {
- if (scrolled_back) {
- sync_scroll(0);
- /* screen_set_thumb(thumb_top, thumb_shown); */
- }
- need_saving = True;
- }
-
- /*
- * Save the current screen image, if it hasn't been saved since last updated.
- */
- static void
- save_image(void)
- {
- int i;
-
- if (!need_saving)
- return;
- for (i = 0; i < maxROWS; i++) {
- (void) memmove(buf_save[appres.save_lines+i],
- screen_buf + (i*COLS),
- COLS);
- (void) memmove(ea_save[appres.save_lines+i],
- (ea_buf + (i*COLS)),
- COLS*sizeof(struct ea));
- }
- need_saving = False;
- }
-
- /*
- * Redraw the display so it begins back <sb> lines.
- */
- static void
- sync_scroll(int sb)
- {
- int slop;
- int i;
- int scroll_first;
- float tt0;
-
- unselect(0, ROWS*COLS);
-
- /*
- * If in 3270 mode, round to a multiple of the screen size and
- * set the scroll bar.
- */
- if (ever_3270) {
- if ((slop = (sb % maxROWS))) {
- if (slop <= maxROWS/2)
- sb -= slop;
- else
- sb += maxROWS - slop;
- }
- if (sb)
- kybd_scroll_lock(True);
- else
- kybd_scroll_lock(False);
- }
-
- /* Update the status line. */
- if (ever_3270)
- status_scrolled(sb / maxROWS);
- else
- status_scrolled(0);
-
- /* Swap screen sizes. */
- if (sb && !scrolled_back && ((COLS < maxCOLS) || (ROWS < maxROWS))) {
- COLS = maxCOLS;
- ROWS = maxROWS;
- vscreen_swapped = True;
- } else if (!sb && scrolled_back && vscreen_swapped) {
- ctlr_shrink();
- COLS = 80;
- ROWS = 24;
- vscreen_swapped = False;
- }
-
- scroll_first = (scroll_next+appres.save_lines-sb) % appres.save_lines;
-
- /* Update the screen. */
- for (i = 0; i < maxROWS; i++)
- if (i < sb) {
- (void) memmove(screen_buf + (i*COLS),
- buf_save[(scroll_first+i) % appres.save_lines],
- COLS);
- (void) memmove((ea_buf + (i*COLS)),
- ea_save[(scroll_first+i) % appres.save_lines],
- COLS*sizeof(struct ea));
- } else {
- (void) memmove(screen_buf + (i*COLS),
- buf_save[appres.save_lines+i-sb],
- COLS);
- (void) memmove((ea_buf + (i*COLS)),
- ea_save[appres.save_lines+i-sb],
- COLS*sizeof(struct ea));
- }
-
- /* Disable the cursor if we're scrolled back, enable it if not. */
- enable_cursor(sb == 0);
-
- scrolled_back = sb;
- ctlr_changed(0, ROWS*COLS);
- blink_start();
-
- tt0 = ((float)n_saved / (float)(appres.save_lines + maxROWS));
- thumb_shown = 1.0 - tt0;
- thumb_top = ((float)(n_saved-sb) / (float)(appres.save_lines + maxROWS));
- screen_set_thumb(thumb_top, thumb_shown);
- }
-
- /*
- * Callback for "scroll" action (incrementing the thumb in one direction).
- */
- void
- scroll_proc(int n, int total)
- {
- float pct;
- int nss;
- int nsr;
-
- if (!n_saved)
- return;
- if (n < 0)
- pct = (float)(-n) / (float)total;
- else
- pct = (float)n / (float)total;
- /*printf("scroll_proc(%d, %d) %f\n", n, total, pct);*/
- nss = pct * thumb_shown * n_saved;
- if (!nss)
- nss = 1;
- save_image();
- if (n > 0) { /* scroll forward */
- if (nss > scrolled_back)
- sync_scroll(0);
- else {
- nsr = scrolled_back - nss;
- if (ever_3270 && (nsr % maxROWS))
- nsr -= nsr % maxROWS;
- sync_scroll(nsr);
- }
- } else { /* scroll back */
- if (scrolled_back + nss > n_saved)
- sync_scroll(n_saved);
- else {
- nsr = scrolled_back + nss;
- if (ever_3270 && (nsr % maxROWS))
- nsr += maxROWS - (nsr % maxROWS);
- sync_scroll(nsr);
- }
- }
-
- screen_set_thumb((float)(n_saved - scrolled_back) / (float)(appres.save_lines + maxROWS),
- thumb_shown);
- }
-
- /*
- * Callback for "jump" action (moving the thumb to a particular spot).
- */
- void
- jump_proc(float top)
- {
- /*printf("jump_proc(%f)\n", top);*/
- if (!n_saved) {
- screen_set_thumb(thumb_top, thumb_shown);
- return;
- }
- if (top > thumb_top_base) { /* too far down */
- screen_set_thumb(thumb_top_base, thumb_shown);
- sync_scroll(0);
- } else {
- save_image();
- sync_scroll((int)((1.0 - top) * n_saved));
- }
- }
-
- /*
- * Resynchronize the thumb (called when the scrollbar is turned on).
- */
- void
- rethumb(void)
- {
- screen_set_thumb(thumb_top, thumb_shown);
- }
-