source: trunk/third/x3270/scroll.c @ 9081

Revision 9081, 8.5 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9080, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright 1994, 1995 by Paul Mattes.
3 *  Permission to use, copy, modify, and distribute this software and its
4 *  documentation for any purpose and without fee is hereby granted,
5 *  provided that the above copyright notice appear in all copies and that
6 *  both that copyright notice and this permission notice appear in
7 *  supporting documentation.
8 */
9
10/*
11 *      scroll.c
12 *              Scrollbar support
13 */
14
15#include "globals.h"
16#include "appres.h"
17#include "ctlr.h"
18
19#include "ctlrc.h"
20#include "kybdc.h"
21#include "screenc.h"
22#include "scrollc.h"
23#include "selectc.h"
24#include "statusc.h"
25
26/* Globals */
27Boolean scroll_initted = False;
28
29/* Statics */
30static unsigned char **buf_save = (unsigned char **) NULL;
31static struct ea **ea_save = (struct ea **) NULL;
32static int      n_saved = 0;
33static int      scroll_next = 0;
34static float    thumb_top = 0.0;
35static float    thumb_top_base = 0.0;
36static float    thumb_shown = 1.0;
37static int      scrolled_back = 0;
38static Boolean  need_saving = True;
39static Boolean  vscreen_swapped = False;
40static char    *sbuf = CN;
41static int      sa_bufsize;
42static char    *zbuf = CN;
43static void     sync_scroll();
44
45/*
46 * Initialize (or re-initialize) the scrolling parameters and save area.
47 */
48void
49scroll_init()
50{
51        register int i;
52        int sa_size;
53        unsigned char *s;
54
55        if (appres.save_lines % maxROWS)
56                appres.save_lines =
57                    ((appres.save_lines+maxROWS-1)/maxROWS) * maxROWS;
58        if (!appres.save_lines)
59                appres.save_lines = maxROWS;
60        if (sbuf != CN) {
61                XtFree(sbuf);
62                XtFree(zbuf);
63                XtFree((char *)buf_save);
64                XtFree((char *)ea_save);
65        }
66        sa_size = appres.save_lines + maxROWS;
67        buf_save = (unsigned char **)XtCalloc(sizeof(unsigned char *), sa_size);
68        ea_save = (struct ea **)XtCalloc(sizeof(struct ea *), sa_size);
69        sa_bufsize = (sa_size * (sizeof(unsigned char) + sizeof(struct ea))) * maxCOLS;
70        sbuf = XtMalloc(sa_bufsize);
71        zbuf = XtMalloc(maxCOLS);
72        (void) memset(zbuf, '\0', maxCOLS);
73        s = (unsigned char *)sbuf;
74        for (i = 0; i < sa_size; s += maxCOLS, i++)
75                buf_save[i] = s;
76        for (i = 0; i < sa_size; s += (maxCOLS * sizeof(struct ea)), i++)
77                ea_save[i] = (struct ea *)s;
78        scroll_reset();
79        scroll_initted = True;
80}
81
82/*
83 * Reset the scrolling parameters and erase the save area.
84 */
85void
86scroll_reset()
87{
88        (void) memset(sbuf, 0, sa_bufsize);
89        scroll_next = 0;
90        n_saved = 0;
91        scrolled_back = 0;
92        thumb_top_base = thumb_top = 0.0;
93        thumb_shown = 1.0;
94        need_saving = True;
95        screen_set_thumb(thumb_top, thumb_shown);
96        enable_cursor(True);
97}
98
99/*
100 * Save <n> lines of data from the top of the screen.
101 */
102void
103scroll_save(n, trim_blanks)
104int n;
105Boolean trim_blanks;
106{
107        int i;
108
109        /* Trim trailing blank lines from 'n', if requested */
110        if (trim_blanks) {
111                while (n) {
112                        if (memcmp((char *)(screen_buf+((n-1)*COLS)),
113                                   zbuf, COLS))
114                                break;
115                        else
116                                n--;
117                }
118                if (!n)
119                        return;
120        }
121
122        /* Scroll to bottom on "output". */
123        if (scrolled_back)
124                sync_scroll(0);
125
126        /* Save the screen contents. */
127        for (i = 0; i < n; i++) {
128                if (i < COLS) {
129                        MEMORY_MOVE((char *)buf_save[scroll_next],
130                            (char *)screen_buf+(i*COLS),
131                            COLS);
132                        MEMORY_MOVE((char *)ea_save[scroll_next],
133                            (char *)(ea_buf+(i*COLS)),
134                            COLS*sizeof(struct ea));
135                        if (COLS < maxCOLS) {
136                                (void) memset((char *)(buf_save[scroll_next] + COLS), '\0',
137                                    maxCOLS - COLS);
138                                (void) memset((char *)(ea_save[scroll_next] + COLS), '\0',
139                                    (maxCOLS - COLS)*sizeof(struct ea));
140                        }
141                } else {
142                        (void) memset((char *)buf_save[scroll_next], '\0',
143                            maxCOLS);
144                        (void) memset((char *)ea_save[scroll_next], '\0',
145                            maxCOLS*sizeof(struct ea));
146                }
147                scroll_next = (scroll_next + 1) % appres.save_lines;
148                if (n_saved < appres.save_lines)
149                        n_saved++;
150        }
151
152        /* Reset the thumb. */
153        thumb_top_base =
154            thumb_top =
155            ((float)n_saved / (float)(appres.save_lines + maxROWS));
156        thumb_shown = 1.0 - thumb_top;
157        screen_set_thumb(thumb_top, thumb_shown);
158}
159
160/*
161 * Add blank lines to the scroll buffer to make it a multiple of the
162 * screen size.
163 */
164void
165scroll_round()
166{
167        int n;
168
169        if (!(n_saved % maxROWS))
170                return;
171
172        /* Zero the scroll buffer. */
173        for (n = maxROWS - (n_saved % maxROWS); n; n--) {
174                (void) memset((char *)buf_save[scroll_next], '\0', maxCOLS);
175                (void) memset((char *)ea_save[scroll_next], '\0',
176                            maxCOLS*sizeof(struct ea));
177                scroll_next = (scroll_next + 1) % appres.save_lines;
178                if (n_saved < appres.save_lines)
179                        n_saved++;
180        }
181
182        /* Reset the thumb. */
183        thumb_top_base =
184            thumb_top =
185            ((float)n_saved / (float)(appres.save_lines + maxROWS));
186        thumb_shown = 1.0 - thumb_top;
187        screen_set_thumb(thumb_top, thumb_shown);
188}
189
190/*
191 * Jump to the bottom of the scroll buffer.
192 */
193void
194scroll_to_bottom()
195{
196        if (scrolled_back) {
197                sync_scroll(0);
198                /* screen_set_thumb(thumb_top, thumb_shown); */
199        }
200        need_saving = True;
201}
202
203/*
204 * Save the current screen image, if it hasn't been saved since last updated.
205 */
206void
207save_image()
208{
209        int i;
210
211        if (!need_saving)
212                return;
213        for (i = 0; i < maxROWS; i++) {
214                MEMORY_MOVE((char *)buf_save[appres.save_lines+i],
215                            (char *)screen_buf + (i*COLS),
216                            COLS);
217                MEMORY_MOVE((char *)ea_save[appres.save_lines+i],
218                            (char *)(ea_buf + (i*COLS)),
219                            COLS*sizeof(struct ea));
220        }
221        need_saving = False;
222}
223
224/*
225 * Redraw the display so it begins back <sb> lines.
226 */
227static void
228sync_scroll(sb)
229int sb;
230{
231        int slop;
232        int i;
233        int scroll_first;
234        float tt0;
235
236        (void) unselect(0, ROWS*COLS);
237
238        /*
239         * If in 3270 mode, round to a multiple of the screen size and
240         * set the scroll bar.
241         */
242        if (ever_3270) {
243                if ((slop = (sb % maxROWS))) {
244                        if (slop <= maxROWS/2)
245                                sb -= slop;
246                        else
247                                sb += maxROWS - slop;
248                }
249                if (sb)
250                        kybd_scroll_lock(True);
251                else
252                        kybd_scroll_lock(False);
253        }
254
255        /* Update the status line. */
256        if (ever_3270)
257                status_scrolled(sb / maxROWS);
258        else
259                status_scrolled(0);
260
261        /* Swap screen sizes. */
262        if (sb && !scrolled_back && ((COLS < maxCOLS) || (ROWS < maxROWS))) {
263                COLS = maxCOLS;
264                ROWS = maxROWS;
265                vscreen_swapped = True;
266        } else if (!sb && scrolled_back && vscreen_swapped) {
267                ctlr_shrink();
268                COLS = 80;
269                ROWS = 24;
270                vscreen_swapped = False;
271        }
272
273        scroll_first = (scroll_next+appres.save_lines-sb) % appres.save_lines;
274
275        /* Update the screen. */
276        for (i = 0; i < maxROWS; i++)
277                if (i < sb) {
278                        MEMORY_MOVE((char *)screen_buf + (i*COLS),
279                                    (char *)buf_save[(scroll_first+i) % appres.save_lines],
280                                    COLS);
281                        MEMORY_MOVE((char *)(ea_buf + (i*COLS)),
282                                    (char *)ea_save[(scroll_first+i) % appres.save_lines],
283                                    COLS*sizeof(struct ea));
284                } else {
285                        MEMORY_MOVE((char *)screen_buf + (i*COLS),
286                                    (char *)buf_save[appres.save_lines+i-sb],
287                                    COLS);
288                        MEMORY_MOVE((char *)(ea_buf + (i*COLS)),
289                                    (char *)ea_save[appres.save_lines+i-sb],
290                                    COLS*sizeof(struct ea));
291                }
292
293        /* Disable the cursor if we're scrolled back, enable it if not. */
294        enable_cursor(sb == 0);
295
296        scrolled_back = sb;
297        ctlr_changed(0, ROWS*COLS);
298        blink_start();
299
300        tt0 = ((float)n_saved / (float)(appres.save_lines + maxROWS));
301        thumb_shown = 1.0 - tt0;
302        thumb_top = ((float)(n_saved-sb) / (float)(appres.save_lines + maxROWS));
303        screen_set_thumb(thumb_top, thumb_shown);
304}
305
306/*
307 * Callback for "scroll" action (incrementing the thumb in one direction).
308 */
309void
310scroll_proc(n, total)
311int n;
312int total;
313{
314        float pct;
315        int nss;
316        int nsr;
317
318        if (!n_saved)
319                return;
320        if (n < 0)
321                pct = (float)(-n) / (float)total;
322        else
323                pct = (float)n / (float)total;
324        /*printf("scroll_proc(%d, %d) %f\n", n, total, pct);*/
325        nss = pct * thumb_shown * n_saved;
326        if (!nss)
327                nss = 1;
328        save_image();
329        if (n > 0) {    /* scroll forward */
330                if (nss > scrolled_back)
331                        sync_scroll(0);
332                else {
333                        nsr = scrolled_back - nss;
334                        if (ever_3270 && (nsr % maxROWS))
335                                nsr -= nsr % maxROWS;
336                        sync_scroll(nsr);
337                }
338        } else {        /* scroll back */
339                if (scrolled_back + nss > n_saved)
340                        sync_scroll(n_saved);
341                else {
342                        nsr = scrolled_back + nss;
343                        if (ever_3270 && (nsr % maxROWS))
344                                nsr += maxROWS - (nsr % maxROWS);
345                        sync_scroll(nsr);
346                }
347        }
348
349        screen_set_thumb((float)(n_saved - scrolled_back) / (float)(appres.save_lines + maxROWS),
350            thumb_shown);
351}
352
353/*
354 * Callback for "jump" action (moving the thumb to a particular spot).
355 */
356void
357jump_proc(top)
358float top;
359{
360        /*printf("jump_proc(%f)\n", top);*/
361        if (!n_saved) {
362                screen_set_thumb(thumb_top, thumb_shown);
363                return;
364        }
365        if (top > thumb_top_base) {     /* too far down */
366                screen_set_thumb(thumb_top_base, thumb_shown);
367                sync_scroll(0);
368        } else {
369                save_image();
370                sync_scroll((int)((1.0 - top) * n_saved));
371        }
372}
373
374/*
375 * Resynchronize the thumb (called when the scrollbar is turned on).
376 */
377void
378rethumb()
379{
380        screen_set_thumb(thumb_top, thumb_shown);
381}
Note: See TracBrowser for help on using the repository browser.