1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/scroll.c,v 1.8 2011/05/16 16:21:59 william Exp $
19 */
20
21 #define _INCLUDE_FROM_SCROLL_C_
22
23 #include "tgifdefs.h"
24
25 #include "choice.e"
26 #include "cursor.e"
27 #include "dialog.e"
28 #include "drawing.e"
29 #include "dup.e"
30 #include "exec.e"
31 #include "grid.e"
32 #include "mainloop.e"
33 #include "menu.e"
34 #include "miniline.e"
35 #include "msg.e"
36 #include "obj.e"
37 #include "page.e"
38 #include "raster.e"
39 #include "rect.e"
40 #include "ruler.e"
41 #include "scroll.e"
42 #include "setup.e"
43 #include "strtbl.e"
44 #include "text.e"
45 #include "util.e"
46
47 #include "xbm/scrl_up.xbm"
48
49 #define FAKE_CM 80
50
51 int autoPan=TRUE;
52
53 int scrollingCanvas=INVALID;
54 int smoothScrollingCanvas=JUMP_SCROLLING;
55
56 int resetOriginOnAdvancePage=FALSE;
57
58 static int scrollAreaH=0, scrollAreaW=0;
59
TgAnyButtonDown(dpy,win)60 int TgAnyButtonDown(dpy, win)
61 Display *dpy;
62 Window win;
63 {
64 Window root_win=None, child_win=None;
65 unsigned int status;
66 int parent_root_x, parent_root_y, x=0, y=0;
67
68 XQueryPointer(dpy, win, &root_win, &child_win,
69 &parent_root_x, &parent_root_y, &x, &y, &status);
70 return ((status & BUTTONSMASK) != 0);
71 }
72
TgPressButtonLoop(dpy,win,pbbox,psbci)73 int TgPressButtonLoop(dpy, win, pbbox, psbci)
74 Display *dpy;
75 Window win;
76 struct BBRec *pbbox;
77 ScrollBtnCallbackInfo *psbci;
78 /* returns TRUE if need to scroll one more time */
79 {
80 time_t tv_usec=(time_t)0;
81 int done=FALSE, need_to_scroll_once=TRUE, initial_timeout=TRUE;
82
83 if (pbbox != NULL) {
84 TgDrawThreeDButton(dpy, win, textMenuGC, pbbox, TGBS_LOWRED, 2, FALSE);
85 }
86 if (!TgAnyButtonDown(dpy, win)) {
87 if (pbbox != NULL) {
88 TgDrawThreeDButton(dpy, win, textMenuGC, pbbox, TGBS_RAISED, 2, FALSE);
89 }
90 return need_to_scroll_once;
91 }
92 tv_usec = (psbci->ms*1000);
93
94 XGrabPointer(dpy, win, False,
95 ButtonReleaseMask, GrabModeAsync,
96 GrabModeAsync, None, handCursor, CurrentTime);
97
98 do {
99 struct timeval timeout;
100 fd_set fdset;
101 int select_width=XConnectionNumber(dpy)+1, status=0;
102
103 timeout.tv_sec = 0;
104 timeout.tv_usec = (initial_timeout ? 600000 : tv_usec);
105 FD_ZERO(&fdset);
106 FD_SET(select_width-1, &fdset);
107 #ifdef __hpux
108 status = select(select_width, (int*)&fdset, NULL, NULL, &timeout);
109 #else /* !__hpux */
110 status = select(select_width, &fdset, NULL, NULL, &timeout);
111 #endif /* __hpux */
112 initial_timeout = FALSE;
113
114 if (status < 0) {
115 if (errno == EINTR) {
116 /* interrupted by a system call, do it again */
117 if (TgAnyButtonDown(dpy, win)) {
118 need_to_scroll_once = FALSE;
119 if ((psbci->pf_scroll_btn_callback)(psbci->pv_userdata)) {
120 XUngrabPointer(dpy, CurrentTime);
121 return TRUE;
122 }
123 }
124 } else {
125 XUngrabPointer(dpy, CurrentTime);
126 sprintf(gszMsgBox, TgLoadString(STID_FUNC_SELECT_SYS_CALL_FAILED),
127 "TgPressButtonLoop()");
128 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
129 break;
130 }
131 } else if (status == 0 && TgAnyButtonDown(dpy, win)) {
132 need_to_scroll_once = FALSE;
133 if ((psbci->pf_scroll_btn_callback)(psbci->pv_userdata)) {
134 XUngrabPointer(dpy, CurrentTime);
135 return TRUE;
136 }
137 } else {
138 XUngrabPointer(dpy, CurrentTime);
139 XFlush(dpy);
140 XSync(dpy, False);
141 if (pbbox != NULL) {
142 TgDrawThreeDButton(dpy, win, textMenuGC, pbbox, TGBS_RAISED, 2,
143 FALSE);
144 }
145 done = TRUE;
146 return need_to_scroll_once;
147 }
148 } while (!done);
149
150 return need_to_scroll_once;
151 }
152
TgGetScrollHit(x,y,orientation,scroll_area_w,scroll_area_h,start_frac,length,total,pn_btn_offset)153 int TgGetScrollHit(x, y, orientation, scroll_area_w, scroll_area_h,
154 start_frac, length, total, pn_btn_offset)
155 int x, y, scroll_area_w, scroll_area_h, length, total, *pn_btn_offset;
156 double start_frac;
157 {
158 int block_start=0, block_size=0, min_block_size=1+(windowPadding<<1);
159 int block_area=((orientation==VERT_SCROLLBAR)?scroll_area_h:scroll_area_w);
160 double frac=(double)0;
161
162 if (pn_btn_offset != NULL) *pn_btn_offset = 0;
163 if (orientation == VERT_SCROLLBAR) {
164 y -= scrollBarW;
165 } else {
166 x -= scrollBarW;
167 }
168 block_area -= (scrollBarW<<1);
169 if (total == 0) {
170 frac = (double)1.0;
171 } else {
172 frac = (double)((double)length / (double)total);
173 }
174 if (frac > 1.0) frac = 1.0;
175 block_start = ((int)(block_area * start_frac));
176 if (start_frac + frac >= 1.0) {
177 block_size = block_area - block_start;
178 } else {
179 block_size = (int)(block_area * frac);
180 }
181 if (block_size < min_block_size) block_size = min_block_size;
182 if (orientation == VERT_SCROLLBAR) {
183 if (block_start > scroll_area_h-min_block_size) {
184 block_start = scroll_area_h-min_block_size;
185 }
186 } else {
187 if (block_start > scroll_area_w-min_block_size) {
188 block_start = scroll_area_w-min_block_size;
189 }
190 }
191 if (orientation == VERT_SCROLLBAR) {
192 if (y < block_start) {
193 return (-1);
194 } else if (y < block_start+block_size) {
195 if (pn_btn_offset != NULL) *pn_btn_offset = block_start-y;
196 return 0;
197 }
198 } else {
199 if (x < block_start) {
200 return (-1);
201 } else if (x < block_start+block_size) {
202 if (pn_btn_offset != NULL) *pn_btn_offset = block_start-x;
203 return 0;
204 }
205 }
206 return 1;
207 }
208
TgDrawScrollBar(dpy,win,orientation,x_off,y_off,scroll_area_w,scroll_area_h,start_frac,length,total)209 void TgDrawScrollBar(dpy, win, orientation, x_off, y_off, scroll_area_w,
210 scroll_area_h, start_frac, length, total)
211 Display *dpy;
212 Window win;
213 int x_off, y_off, scroll_area_w, scroll_area_h, length, total;
214 double start_frac;
215 {
216 int block_start=0, block_size=0, min_block_size=1+(windowPadding<<1);
217 int block_area=((orientation==VERT_SCROLLBAR)?scroll_area_h:scroll_area_w);
218 double frac=(double)0;
219 XGCValues values;
220
221 if (threeDLook) {
222 struct BBRec bbox;
223
224 if (orientation == VERT_SCROLLBAR) {
225 values.foreground = myFgPixel;
226 values.background = myLtGryPixel;
227 values.fill_style = FillOpaqueStippled;
228 values.stipple = scrlBitmap[SCRL_UP];
229 values.ts_x_origin = x_off+(windowPadding<<1);
230 values.ts_y_origin = y_off+1+(windowPadding<<1);
231 XChangeGC(mainDisplay, textMenuGC,
232 GCForeground | GCBackground | GCFillStyle | GCStipple |
233 GCTileStipXOrigin | GCTileStipYOrigin, &values);
234 XFillRectangle(dpy, win, textMenuGC, values.ts_x_origin,
235 values.ts_y_origin, scrl_up_width, scrl_up_height);
236 values.stipple = scrlBitmap[SCRL_DN];
237 values.ts_y_origin =
238 y_off+scroll_area_h-scrollBarW+1+(windowPadding<<1);
239 XChangeGC(mainDisplay, textMenuGC,
240 GCStipple | GCTileStipYOrigin, &values);
241 XFillRectangle(dpy, win, textMenuGC, values.ts_x_origin,
242 values.ts_y_origin, scrl_up_width, scrl_up_height);
243 values.fill_style = FillSolid;
244 values.ts_x_origin = 0;
245 values.ts_y_origin = 0;
246 XChangeGC(mainDisplay, textMenuGC,
247 GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin, &values);
248 SetBBRec(&bbox, x_off, y_off, x_off+scrollBarW, y_off+scrollBarW);
249 TgDrawThreeDButton(dpy, win, textMenuGC, &bbox, TGBS_RAISED, 2, FALSE);
250 SetBBRec(&bbox, x_off, y_off+scroll_area_h-scrollBarW,
251 x_off+scrollBarW, y_off+scroll_area_h);
252 TgDrawThreeDButton(dpy, win, textMenuGC, &bbox, TGBS_RAISED, 2, FALSE);
253 } else {
254 values.foreground = myFgPixel;
255 values.background = myLtGryPixel;
256 values.fill_style = FillOpaqueStippled;
257 values.stipple = scrlBitmap[SCRL_LF];
258 values.ts_x_origin = x_off+(windowPadding<<1);
259 values.ts_y_origin = y_off+(windowPadding<<1);
260 XChangeGC(mainDisplay, textMenuGC,
261 GCForeground | GCBackground | GCFillStyle | GCStipple |
262 GCTileStipXOrigin | GCTileStipYOrigin, &values);
263 XFillRectangle(dpy, win, textMenuGC, values.ts_x_origin,
264 values.ts_y_origin, scrl_up_width, scrl_up_height);
265 values.stipple = scrlBitmap[SCRL_RT];
266 values.ts_x_origin = x_off+scroll_area_w-scrollBarW+(windowPadding<<1);
267 XChangeGC(mainDisplay, textMenuGC,
268 GCStipple | GCTileStipXOrigin, &values);
269 XFillRectangle(dpy, win, textMenuGC, values.ts_x_origin,
270 values.ts_y_origin, scrl_up_width, scrl_up_height);
271 values.fill_style = FillSolid;
272 values.ts_x_origin = 0;
273 values.ts_y_origin = 0;
274 XChangeGC(mainDisplay, textMenuGC,
275 GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin, &values);
276 SetBBRec(&bbox, x_off, y_off, x_off+scrollBarW, y_off+scrollBarW);
277 TgDrawThreeDButton(dpy, win, textMenuGC, &bbox, TGBS_RAISED, 2, FALSE);
278 SetBBRec(&bbox, x_off+scroll_area_w-scrollBarW, y_off,
279 x_off+scroll_area_w, y_off+scrollBarW);
280 TgDrawThreeDButton(dpy, win, textMenuGC, &bbox, TGBS_RAISED, 2, FALSE);
281 }
282 block_area -= (scrollBarW<<1);
283 if (total == 0) {
284 frac = (double)1.0;
285 } else {
286 frac = (double)((double)length / (double)total);
287 }
288 if (frac > 1.0) frac = 1.0;
289 block_start = scrollBarW + ((int)(block_area * start_frac));
290 if (start_frac + frac >= 1.0) {
291 block_size = block_area - block_start + scrollBarW;
292 } else {
293 block_size = (int)(block_area * frac);
294 }
295 if (block_size < min_block_size) block_size = min_block_size;
296 if (orientation == VERT_SCROLLBAR) {
297 if (block_start > scroll_area_h-scrollBarW-min_block_size) {
298 block_start = scroll_area_h-scrollBarW-min_block_size;
299 }
300 } else {
301 if (block_start > scroll_area_w-scrollBarW-min_block_size) {
302 block_start = scroll_area_w-scrollBarW-min_block_size;
303 }
304 }
305 values.foreground = myLtGryPixel;
306 values.background = myBgPixel;
307 values.fill_style = FillOpaqueStippled;
308 values.stipple = patPixmap[SCROLLPAT];
309 XChangeGC(dpy, patGC,
310 GCForeground | GCBackground | GCFillStyle | GCStipple, &values);
311 if (orientation == VERT_SCROLLBAR) {
312 XFillRectangle(dpy, win, patGC, x_off, y_off+scrollBarW, scroll_area_w,
313 scroll_area_h-(scrollBarW<<1));
314 } else {
315 XFillRectangle(dpy, win, patGC, x_off+scrollBarW, y_off,
316 scroll_area_w-(scrollBarW<<1), scroll_area_h);
317 }
318 values.foreground = myLtGryPixel;
319 values.background = myLtGryPixel;
320 values.function = GXcopy;
321 values.fill_style = FillSolid;
322 XChangeGC(dpy, patGC,
323 GCForeground | GCBackground | GCFunction | GCFillStyle, &values);
324 if (orientation == VERT_SCROLLBAR) {
325 XFillRectangle(dpy, win, patGC, x_off, y_off+block_start,
326 scroll_area_w, block_size);
327 SetBBRec(&bbox, x_off, y_off+block_start, x_off+scroll_area_w,
328 y_off+block_start+block_size);
329 } else {
330 XFillRectangle(dpy, win, patGC, x_off+block_start, y_off, block_size,
331 scroll_area_h);
332 SetBBRec(&bbox, x_off+block_start, y_off, x_off+block_start+block_size,
333 y_off+scroll_area_h);
334 }
335 TgDrawThreeDButton(dpy, win, textMenuGC, &bbox, TGBS_RAISED, 2, FALSE);
336 } else {
337 if (total == 0) {
338 frac = (double)1.0;
339 } else {
340 frac = (double)((double)length / (double)total);
341 }
342 if (frac > 1.0) frac = 1.0;
343 block_start = (int)(block_area * start_frac);
344 if (start_frac + frac >= 1.0) {
345 block_size = block_area - block_start;
346 } else {
347 block_size = (int)(block_area * frac);
348 }
349 if (block_size <= 0) block_size = 1;
350
351 values.foreground = myBgPixel;
352 values.background = myFgPixel;
353 values.function = GXcopy;
354 values.fill_style = FillSolid;
355 XChangeGC(dpy, patGC,
356 GCForeground | GCBackground | GCFunction | GCFillStyle, &values);
357 XFillRectangle(dpy, win, patGC, x_off, y_off, scroll_area_w,
358 scroll_area_h);
359
360 values.foreground = myFgPixel;
361 values.background = myBgPixel;
362 values.fill_style = FillOpaqueStippled;
363 values.stipple = patPixmap[SCROLLPAT];
364 XChangeGC(dpy, patGC,
365 GCForeground | GCBackground | GCFillStyle | GCStipple, &values);
366 if (orientation == VERT_SCROLLBAR) {
367 XFillRectangle(dpy, win, patGC, x_off, y_off+block_start,
368 scroll_area_w, block_size);
369 } else {
370 XFillRectangle(dpy, win, patGC, x_off+block_start, y_off, block_size,
371 scroll_area_h);
372 }
373 }
374 }
375
RedrawVScrollWindow()376 void RedrawVScrollWindow()
377 {
378 double start_frac=(double)0;
379 int total=max(paperHeight,(drawOrigY+drawWinH));
380 XEvent ev;
381
382 XSync(mainDisplay, False);
383 while (XCheckWindowEvent(mainDisplay, vSBarWindow, ExposureMask, &ev)) ;
384
385 if (total == 0) {
386 start_frac = (double)1.0;
387 } else {
388 start_frac = (double)((double)drawOrigY / (double)total);
389 }
390 if (start_frac > 1.0) start_frac = 1.0;
391 TgDrawScrollBar(mainDisplay, vSBarWindow, VERT_SCROLLBAR,
392 0, 0, scrollBarW, scrollAreaH, start_frac, drawWinH, total);
393 }
394
RedrawHScrollWindow()395 void RedrawHScrollWindow()
396 {
397 double start_frac=(double)0;
398 int total=max(paperWidth,(drawOrigX+drawWinW));
399 XEvent ev;
400
401 XSync(mainDisplay, False);
402 while (XCheckWindowEvent(mainDisplay, hSBarWindow, ExposureMask, &ev)) ;
403
404 if (total == 0) {
405 start_frac = (double)1.0;
406 } else {
407 start_frac = (double)((double)drawOrigX / (double)total);
408 }
409 if (start_frac > 1.0) start_frac = 1.0;
410 TgDrawScrollBar(mainDisplay, hSBarWindow, HORI_SCROLLBAR,
411 0, 0, scrollAreaW, scrollBarW, start_frac, drawWinW, total);
412 }
413
RedrawScrollBars()414 void RedrawScrollBars()
415 {
416 if (vSBarWindow != None) RedrawVScrollWindow();
417 if (hSBarWindow != None) RedrawHScrollWindow();
418 }
419
GetMaxScrollOrigin(pn_orig_x,pn_orig_y)420 void GetMaxScrollOrigin(pn_orig_x, pn_orig_y)
421 int *pn_orig_x, *pn_orig_y;
422 {
423 if (pn_orig_y != NULL) {
424 if (paperHeight <= drawWinH) {
425 *pn_orig_y = 0;
426 } else {
427 switch (gridSystem) {
428 case ENGLISH_GRID:
429 if ((paperHeight-drawWinH) % ABS_SIZE(HALF_INCH) == 0) {
430 *pn_orig_y = paperHeight-drawWinH;
431 } else {
432 *pn_orig_y = max(0, ((int)((paperHeight-drawWinH)/
433 ABS_SIZE(HALF_INCH)) + 1) * ABS_SIZE(HALF_INCH));
434 }
435 break;
436 case METRIC_GRID:
437 if (zoomedIn && zoomScale > 1) {
438 if ((paperHeight-drawWinH) % ABS_SIZE(FAKE_CM) == 0) {
439 *pn_orig_y = paperHeight-drawWinH;
440 } else {
441 *pn_orig_y = max(0, ((int)((paperHeight-drawWinH)/
442 ABS_SIZE(FAKE_CM)) + 1) * ABS_SIZE(FAKE_CM));
443 }
444 } else {
445 if ((paperHeight-drawWinH) % ABS_SIZE(ONE_CM) == 0) {
446 *pn_orig_y = paperHeight-drawWinH;
447 } else {
448 *pn_orig_y = max(0, ((int)((paperHeight-drawWinH)/
449 ABS_SIZE(ONE_CM)) + 1) * ABS_SIZE(ONE_CM));
450 }
451 }
452 break;
453 }
454 }
455 *pn_orig_y = ABS_SIZE(ZOOMED_SIZE(*pn_orig_y));
456 }
457 if (pn_orig_x != NULL) {
458 if (paperWidth <= drawWinW) {
459 *pn_orig_x = 0;
460 } else {
461 switch (gridSystem) {
462 case ENGLISH_GRID:
463 if ((paperWidth-drawWinW) % ABS_SIZE(HALF_INCH) == 0) {
464 *pn_orig_x = paperWidth-drawWinW;
465 } else {
466 *pn_orig_x = max(0, ((int)((paperWidth-drawWinW)/
467 ABS_SIZE(HALF_INCH)) + 1) * ABS_SIZE(HALF_INCH));
468 }
469 break;
470 case METRIC_GRID:
471 if (zoomedIn && zoomScale > 1) {
472 if ((paperWidth-drawWinW) % ABS_SIZE(FAKE_CM) == 0) {
473 *pn_orig_x = paperWidth-drawWinW;
474 } else {
475 *pn_orig_x = max(0, ((int)((paperWidth-drawWinW)/
476 ABS_SIZE(FAKE_CM)) + 1) * ABS_SIZE(FAKE_CM));
477 }
478 } else {
479 if ((paperWidth-drawWinW) % ABS_SIZE(ONE_CM) == 0) {
480 *pn_orig_x = paperWidth-drawWinW;
481 } else {
482 *pn_orig_x = max(0, ((int)((paperWidth-drawWinW)/
483 ABS_SIZE(ONE_CM)) + 1) * ABS_SIZE(ONE_CM));
484 }
485 }
486 break;
487 }
488 }
489 *pn_orig_x = ABS_SIZE(ZOOMED_SIZE(*pn_orig_x));
490 }
491 }
492
ScrollTo(XOff,YOff)493 void ScrollTo(XOff, YOff)
494 int XOff, YOff;
495 {
496 int h_adjust=0, v_adjust=0;
497 static int first_auto_pan_msg=TRUE;
498
499 if (!autoPan || (XOff >= 0 && ABS_SIZE(XOff) < drawWinW &&
500 YOff >= 0 && ABS_SIZE(YOff) < drawWinH)) {
501 return;
502 }
503 if (XOff < 0) {
504 if (ABS_SIZE(-XOff) > drawOrigX) {
505 h_adjust = (-ZOOMED_SIZE(drawOrigX));
506 } else {
507 switch (gridSystem) {
508 case ENGLISH_GRID:
509 h_adjust = ((-XOff) % HALF_INCH == 0) ? (XOff) :
510 (((int)((-XOff)/HALF_INCH))+1) * (-HALF_INCH);
511 break;
512 case METRIC_GRID:
513 if (zoomedIn && zoomScale > 1) {
514 h_adjust = ((-XOff) % FAKE_CM == 0) ? (XOff) :
515 (((int)((-XOff)/FAKE_CM))+1) * (-FAKE_CM);
516 } else {
517 h_adjust = ((-XOff) % ONE_CM == 0) ? (XOff) :
518 (((int)((-XOff)/ONE_CM))+1) * (-ONE_CM);
519 }
520 break;
521 }
522 }
523 } else if (ABS_SIZE(XOff) >= drawWinW) {
524 switch (gridSystem) {
525 case ENGLISH_GRID:
526 h_adjust = (((int)((XOff-ZOOMED_SIZE(drawWinW))/HALF_INCH))+1) *
527 HALF_INCH;
528 break;
529 case METRIC_GRID:
530 if (zoomedIn && zoomScale > 1) {
531 h_adjust = (((int)((XOff-ZOOMED_SIZE(drawWinW))/FAKE_CM))+1) *
532 FAKE_CM;
533 } else {
534 h_adjust = (((int)((XOff-ZOOMED_SIZE(drawWinW))/ONE_CM))+1) *
535 ONE_CM;
536 }
537 break;
538 }
539 }
540 if (YOff < 0) {
541 if (ABS_SIZE(-YOff) > drawOrigY) {
542 v_adjust = (-ZOOMED_SIZE(drawOrigY));
543 } else {
544 switch (gridSystem) {
545 case ENGLISH_GRID:
546 v_adjust = ((-YOff) % HALF_INCH == 0) ? (YOff) :
547 (((int)((-YOff)/HALF_INCH))+1) * (-HALF_INCH);
548 break;
549 case METRIC_GRID:
550 if (zoomedIn && zoomScale > 1) {
551 v_adjust = ((-YOff) % FAKE_CM == 0) ? (YOff) :
552 (((int)((-YOff)/FAKE_CM))+1) * (-FAKE_CM);
553 } else {
554 v_adjust = ((-YOff) % ONE_CM == 0) ? (YOff) :
555 (((int)((-YOff)/ONE_CM))+1) * (-ONE_CM);
556 }
557 break;
558 }
559 }
560 } else if (ABS_SIZE(YOff+(textCursorH>>1)) >= drawWinH) {
561 switch (gridSystem) {
562 case ENGLISH_GRID:
563 v_adjust = (((int)((YOff+(textCursorH>>1) -
564 ZOOMED_SIZE(drawWinH))/HALF_INCH))+1) * HALF_INCH;
565 break;
566 case METRIC_GRID:
567 if (zoomedIn && zoomScale > 1) {
568 v_adjust = (((int)((YOff+(textCursorH>>1) -
569 ZOOMED_SIZE(drawWinH))/FAKE_CM))+1) * FAKE_CM;
570 } else {
571 v_adjust = (((int)((YOff+(textCursorH>>1) -
572 ZOOMED_SIZE(drawWinH))/ONE_CM))+1) * ONE_CM;
573 }
574 break;
575 }
576 }
577 if (h_adjust == 0 && v_adjust == 0) return;
578
579 if (first_auto_pan_msg) {
580 first_auto_pan_msg = FALSE;
581 sprintf(gszMsgBox, TgLoadString(STID_TURN_OFF_AUTO_PAN_SET_XDEF),
582 TOOL_NAME, "AutoPanInEditText");
583 Msg(gszMsgBox);
584 }
585 drawOrigX += ABS_SIZE(h_adjust);
586 drawOrigY += ABS_SIZE(v_adjust);
587 RedrawScrollBars();
588 UpdDrawWinBBox();
589 AdjSplineVs();
590 AdjustCurText((-h_adjust), (-v_adjust));
591 RedrawRulers();
592 ClearAndRedrawDrawWindow();
593 }
594
ScrollUp(button_ev)595 void ScrollUp(button_ev)
596 XButtonEvent *button_ev;
597 {
598 int adjustment=0;
599
600 if (drawOrigY != 0) {
601 switch (gridSystem) {
602 case ENGLISH_GRID:
603 if (button_ev!=NULL &&
604 (button_ev->state & (ShiftMask|ControlMask))) {
605 adjustment = ((int)(ZOOMED_SIZE(drawWinH)/HALF_INCH))*HALF_INCH;
606 if (drawOrigY-ABS_SIZE(adjustment) < 0) {
607 adjustment = ZOOMED_SIZE(drawOrigY);
608 }
609 } else {
610 adjustment = HALF_INCH;
611 }
612 break;
613 case METRIC_GRID:
614 if (zoomedIn && zoomScale > 1) {
615 if (button_ev!=NULL &&
616 (button_ev->state & (ShiftMask|ControlMask))) {
617 adjustment = ((int)(ZOOMED_SIZE(drawWinH)/FAKE_CM))*FAKE_CM;
618 if (drawOrigY-ABS_SIZE(adjustment) < 0)
619 adjustment = ZOOMED_SIZE(drawOrigY);
620 } else {
621 adjustment = FAKE_CM;
622 }
623 } else {
624 if (button_ev!=NULL &&
625 (button_ev->state & (ShiftMask|ControlMask))) {
626 adjustment = ((int)(ZOOMED_SIZE(drawWinH)/ONE_CM))*ONE_CM;
627 if (drawOrigY-ABS_SIZE(adjustment) < 0)
628 adjustment = ZOOMED_SIZE(drawOrigY);
629 } else {
630 adjustment = ONE_CM;
631 }
632 }
633 break;
634 }
635 if (drawOrigY >= ABS_SIZE(adjustment)) {
636 drawOrigY -= ABS_SIZE(adjustment);
637 } else {
638 adjustment = ZOOMED_SIZE(drawOrigY);
639 drawOrigY -= ABS_SIZE(adjustment);
640 if (drawOrigY < 0) drawOrigY = 0;
641 }
642 RedrawVScrollWindow();
643 UpdDrawWinBBox();
644 AdjSplineVs();
645 AdjustCurText(0, adjustment);
646 RedrawRulers();
647 ClearAndRedrawDrawWindow();
648 }
649 }
650
ForceScrollDown(ScrollAFullWindow)651 void ForceScrollDown(ScrollAFullWindow)
652 int ScrollAFullWindow;
653 {
654 int adjustment=0;
655
656 switch (gridSystem) {
657 case ENGLISH_GRID:
658 if (ScrollAFullWindow) {
659 adjustment = ((int)(ZOOMED_SIZE(drawWinH)/HALF_INCH))*HALF_INCH;
660 } else {
661 adjustment = HALF_INCH;
662 }
663 break;
664 case METRIC_GRID:
665 if (zoomedIn && zoomScale > 1) {
666 if (ScrollAFullWindow) {
667 adjustment = ((int)(ZOOMED_SIZE(drawWinH)/FAKE_CM))*FAKE_CM;
668 } else {
669 adjustment = FAKE_CM;
670 }
671 } else {
672 if (ScrollAFullWindow) {
673 adjustment = ((int)(ZOOMED_SIZE(drawWinH)/ONE_CM))*ONE_CM;
674 } else {
675 adjustment = ONE_CM;
676 }
677 }
678 break;
679 }
680 drawOrigY += ABS_SIZE(adjustment);
681 RedrawVScrollWindow();
682 UpdDrawWinBBox();
683 AdjSplineVs();
684 AdjustCurText(0, -adjustment);
685 RedrawRulers();
686 ClearAndRedrawDrawWindow();
687 }
688
ScrollDown(button_ev)689 void ScrollDown(button_ev)
690 XButtonEvent *button_ev;
691 {
692 if (paperHeight <= drawWinH) return;
693
694 if (drawOrigY+drawWinH < paperHeight) {
695 ForceScrollDown(button_ev != NULL &&
696 (button_ev->state & (ShiftMask|ControlMask)));
697 }
698 }
699
700 typedef struct tagSBarInfo {
701 int scroll_page, scroll_dir;
702 } SBarInfo;
703
704 static
ScrollBtnCallback(pv_userdata)705 int ScrollBtnCallback(pv_userdata)
706 void *pv_userdata;
707 /* returns TRUE to cancel scrolling */
708 {
709 SBarInfo *psbi=((SBarInfo*)(pv_userdata));
710 XButtonEvent btn_ev;
711
712 btn_ev.state = (psbi->scroll_page ? ShiftMask : 0);
713 switch (psbi->scroll_dir) {
714 case SCRL_UP: ScrollUp(&btn_ev); break;
715 case SCRL_DN: ScrollDown(&btn_ev); break;
716 case SCRL_LF: ScrollLeft(&btn_ev); break;
717 case SCRL_RT: ScrollRight(&btn_ev); break;
718 }
719 return FALSE;
720 }
721
722 static
DoSBarBtnScroll(dpy,win,scroll_page,scroll_dir,pbbox)723 int DoSBarBtnScroll(dpy, win, scroll_page, scroll_dir, pbbox)
724 Display *dpy;
725 Window win;
726 int scroll_page, scroll_dir;
727 struct BBRec *pbbox;
728 /* returns TRUE if the done scrolling */
729 {
730 ScrollBtnCallbackInfo sbci;
731 SBarInfo sbi;
732
733 memset(&sbi, 0, sizeof(SBarInfo));
734 sbi.scroll_page = scroll_page;
735 sbi.scroll_dir = scroll_dir;
736
737 memset(&sbci, 0, sizeof(ScrollBtnCallbackInfo));
738 sbci.ms = (scroll_page ? 300 : 200);
739 sbci.pv_userdata = ((void*)(&sbi));
740 sbci.pf_scroll_btn_callback = ScrollBtnCallback;
741 if (TgPressButtonLoop(dpy, win, pbbox, &sbci)) {
742 XButtonEvent btn_ev;
743
744 btn_ev.state = (scroll_page ? ShiftMask : 0);
745 switch (scroll_dir) {
746 case SCRL_UP: ScrollUp(&btn_ev); break;
747 case SCRL_DN: ScrollDown(&btn_ev); break;
748 case SCRL_LF: ScrollLeft(&btn_ev); break;
749 case SCRL_RT: ScrollRight(&btn_ev); break;
750 }
751 }
752 return FALSE;
753 }
754
755 static
DragToInVSBar(lty,block_start,block_h)756 void DragToInVSBar(lty, block_start, block_h)
757 int lty, block_start, block_h;
758 {
759 double start_frac=(double)0.0;
760 int saved_y=drawOrigY, adjustment=0, scroll_all_the_way=FALSE;
761
762 if (threeDLook) {
763 start_frac = (double)(((double)(lty-scrollBarW)) /
764 ((double)(scrollAreaH-(scrollBarW<<1))));
765 if (lty+block_h >= scrollAreaH-scrollBarW) {
766 scroll_all_the_way = TRUE;
767 }
768 } else {
769 start_frac = (double)(((double)block_start)/((double)scrollAreaH));
770 if (block_start+block_h >= scrollAreaH) {
771 scroll_all_the_way = TRUE;
772 }
773 }
774 if (start_frac < 0.0) start_frac = 0.0;
775 if (start_frac > 1.0) start_frac = 1.0;
776 if (scroll_all_the_way) {
777 GetMaxScrollOrigin(NULL, &drawOrigY);
778 } else {
779 double dv=(double)0;
780
781 switch (gridSystem) {
782 case ENGLISH_GRID:
783 dv = ((double)paperHeight) * start_frac;
784 break;
785 case METRIC_GRID:
786 if (zoomedIn && zoomScale > 1) {
787 dv = ((double)paperHeight) * start_frac;
788 } else {
789 dv = ((double)paperHeight) * start_frac;
790 }
791 break;
792 }
793 drawOrigY = round(dv);
794 drawOrigY = ABS_SIZE(ZOOMED_SIZE(drawOrigY));
795 }
796 adjustment = saved_y - drawOrigY;
797 if (adjustment != 0) {
798 RedrawVScrollWindow();
799 UpdDrawWinBBox();
800 AdjSplineVs();
801 AdjustCurText(0, ZOOMED_SIZE(adjustment));
802 RedrawRulers();
803 ClearAndRedrawDrawWindow();
804 } else {
805 RedrawVScrollWindow();
806 }
807 }
808
809 static
DoDragInVSBar(btn_y,btn_offset)810 void DoDragInVSBar(btn_y, btn_offset)
811 int btn_y, btn_offset;
812 {
813 double frac=(double)0.0, start_frac=(double)0.0;
814 int block_h=0, block_start=0, continuous_drag=FALSE;
815 int done=FALSE, lty=0, min_block_size=1+(windowPadding<<1);
816 int total=max(paperHeight,(drawOrigY+drawWinH));
817 XEvent ev;
818
819 scrollingCanvas = SCRL_UP;
820 if (smoothScrollingCanvas == SMOOTH_SCROLLING) {
821 BeginExecAnimate();
822 if (!TgAnyButtonDown(mainDisplay, vSBarWindow)) {
823 EndExecAnimate();
824 ClearAndRedrawDrawWindow();
825 return;
826 }
827 continuous_drag = execAnimating;
828 }
829 block_start = btn_y+btn_offset;
830 frac = (double)((double)drawWinH / (double)(paperHeight));
831 if (threeDLook) {
832 start_frac = (double)(((double)(block_start-scrollBarW)) /
833 ((double)(scrollAreaH-(scrollBarW<<1))));
834 block_h = (frac >= 1.0) ? (scrollAreaH-(scrollBarW<<1)) :
835 (int)(((double)(scrollAreaH-(scrollBarW<<1))) * frac);
836 if (block_h < min_block_size) block_h = min_block_size;
837 lty = (start_frac + frac >= 1.0) ? scrollAreaH-scrollBarW-block_h :
838 block_start;
839 start_frac = (double)(((double)(lty-scrollBarW)) /
840 ((double)(scrollAreaH-(scrollBarW<<1))));
841 } else {
842 start_frac = (double)(((double)block_start)/((double)scrollAreaH));
843 block_h = (frac >= 1.0) ? scrollAreaH :
844 (int)(((double)scrollAreaH) * frac);
845 if (block_h < 1) block_h = 1;
846 lty = (start_frac + frac >= 1.0) ? scrollAreaH-block_h : block_start;
847 start_frac = (double)(((double)lty)/((double)scrollAreaH));
848 }
849 TgDrawScrollBar(mainDisplay, vSBarWindow, VERT_SCROLLBAR, 0, 0, scrollBarW,
850 scrollAreaH, start_frac, drawWinH, total);
851 XGrabPointer(mainDisplay, vSBarWindow, False,
852 PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
853 GrabModeAsync, None, handCursor, CurrentTime);
854
855 while (!done) {
856 XNextEvent(mainDisplay, &ev);
857
858 if (ev.type == Expose || ev.type == VisibilityNotify) {
859 ExposeEventHandler(&ev, TRUE);
860 } else if (ev.type == ButtonRelease) {
861 XUngrabPointer(mainDisplay, CurrentTime);
862 done = TRUE;
863 } else if (ev.type == MotionNotify) {
864 int new_y=0;
865
866 block_start = ev.xmotion.y;
867
868 if (threeDLook) {
869 new_y = ev.xmotion.y+btn_offset;
870 if (new_y < scrollBarW) {
871 new_y = scrollBarW;
872 } else if (new_y+block_h >= scrollAreaH-scrollBarW) {
873 new_y = scrollAreaH-block_h-scrollBarW;
874 }
875 if (new_y != lty) {
876 lty = new_y;
877 start_frac = (double)(((double)(lty-scrollBarW)) /
878 ((double)(scrollAreaH-(scrollBarW<<1))));
879 TgDrawScrollBar(mainDisplay, vSBarWindow, VERT_SCROLLBAR, 0, 0,
880 scrollBarW, scrollAreaH, start_frac, drawWinH, total);
881 }
882 } else {
883 if (block_start <= 0) {
884 new_y = 0;
885 } else if (block_start+block_h >= scrollAreaH) {
886 new_y = scrollAreaH-block_h;
887 } else {
888 new_y = block_start;
889 }
890 if (new_y != lty) {
891 lty = new_y;
892 start_frac = (double)(((double)lty)/((double)scrollAreaH));
893 TgDrawScrollBar(mainDisplay, vSBarWindow, VERT_SCROLLBAR, 0, 0,
894 scrollBarW, scrollAreaH, start_frac, drawWinH, total);
895 }
896 }
897 if (continuous_drag) {
898 int scroll_all_the_way=FALSE;
899
900 if (threeDLook) {
901 start_frac = (double)(((double)(lty-scrollBarW)) /
902 ((double)(scrollAreaH-(scrollBarW<<1))));
903 if (lty+block_h >= scrollAreaH-scrollBarW) {
904 scroll_all_the_way = TRUE;
905 }
906 } else {
907 start_frac = (double)(((double)lty)/((double)scrollAreaH));
908 if (block_start+block_h >= scrollAreaH) {
909 scroll_all_the_way = TRUE;
910 }
911 }
912 RedrawAreaFromCache(start_frac, scroll_all_the_way);
913 } else if (smoothScrollingCanvas == JUMP_SCROLLING) {
914 DragToInVSBar(lty, block_start, block_h);
915 }
916 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
917 }
918 }
919 if (smoothScrollingCanvas == SMOOTH_SCROLLING) {
920 EndExecAnimate();
921 RedrawCurText();
922 }
923 scrollingCanvas = INVALID;
924
925 DragToInVSBar(lty, block_start, block_h);
926 }
927
928 static
VSBarHandler(button_ev)929 void VSBarHandler(button_ev)
930 XButtonEvent *button_ev;
931 {
932 int do_drag=FALSE, btn_offset=0;
933 int total=max(paperHeight,(drawOrigY+drawWinH));
934
935 if (!threeDLook && button_ev->button == Button3 &&
936 button_ev->type == ButtonPress) {
937 DoSBarBtnScroll(mainDisplay, vSBarWindow,
938 ((button_ev->state & (ShiftMask|ControlMask)) != 0), SCRL_UP, NULL);
939 } else if (!threeDLook && button_ev->button == Button1 &&
940 button_ev->type == ButtonPress) {
941 DoSBarBtnScroll(mainDisplay, vSBarWindow,
942 ((button_ev->state & (ShiftMask|ControlMask)) != 0), SCRL_DN, NULL);
943 } else if (button_ev->button == Button1 && button_ev->type == ButtonPress) {
944 if (button_ev->y < scrollBarW ||
945 button_ev->y >= scrollAreaH-scrollBarW) {
946 int which=0;
947 struct BBRec bbox;
948
949 if (button_ev->y < scrollBarW) {
950 which = SCRL_UP;
951 SetBBRec(&bbox, 0, 0, scrollBarW, scrollBarW);
952 } else {
953 which = SCRL_DN;
954 SetBBRec(&bbox, 0, scrollAreaH-scrollBarW, scrollBarW,
955 scrollAreaH);
956 }
957 DoSBarBtnScroll(mainDisplay, vSBarWindow, FALSE, which, &bbox);
958 } else {
959 double start_frac=(double)0.0;
960 int hit=0;
961
962 if (total == 0) {
963 start_frac = (double)1.0;
964 } else {
965 start_frac = (double)((double)drawOrigY / (double)total);
966 }
967 if (start_frac > 1.0) start_frac = 1.0;
968 hit = TgGetScrollHit(button_ev->x, button_ev->y, VERT_SCROLLBAR,
969 scrollBarW, scrollAreaH, start_frac, drawWinH, total,
970 &btn_offset);
971 if (hit == 0) {
972 do_drag = TRUE;
973 } else {
974 DoSBarBtnScroll(mainDisplay, vSBarWindow, TRUE,
975 (hit < 0 ? SCRL_UP : SCRL_DN), NULL);
976 }
977 }
978 } else if (!threeDLook && button_ev->button == Button2 &&
979 button_ev->type == ButtonPress) {
980 do_drag = TRUE;
981 }
982 if (do_drag) {
983 DoDragInVSBar(button_ev->y, btn_offset);
984 }
985 }
986
ScrollLeft(button_ev)987 void ScrollLeft(button_ev)
988 XButtonEvent *button_ev;
989 {
990 int adjustment=0;
991
992 if (drawOrigX != 0) {
993 switch (gridSystem) {
994 case ENGLISH_GRID:
995 if (button_ev!=NULL &&
996 (button_ev->state & (ShiftMask|ControlMask))) {
997 adjustment = ((int)(ZOOMED_SIZE(drawWinW)/HALF_INCH))*HALF_INCH;
998 if (drawOrigX-ABS_SIZE(adjustment) < 0) {
999 adjustment = ZOOMED_SIZE(drawOrigX);
1000 }
1001 } else {
1002 adjustment = HALF_INCH;
1003 }
1004 break;
1005 case METRIC_GRID:
1006 if (zoomedIn && zoomScale > 1) {
1007 if (button_ev!=NULL &&
1008 (button_ev->state & (ShiftMask|ControlMask))) {
1009 adjustment = ((int)(ZOOMED_SIZE(drawWinW)/FAKE_CM))*FAKE_CM;
1010 if (drawOrigX-ABS_SIZE(adjustment) < 0) {
1011 adjustment = ZOOMED_SIZE(drawOrigX);
1012 }
1013 } else {
1014 adjustment = FAKE_CM;
1015 }
1016 } else {
1017 if (button_ev!=NULL &&
1018 (button_ev->state & (ShiftMask|ControlMask))) {
1019 adjustment = ((int)(ZOOMED_SIZE(drawWinW)/ONE_CM))*ONE_CM;
1020 if (drawOrigX-ABS_SIZE(adjustment) < 0) {
1021 adjustment = ZOOMED_SIZE(drawOrigX);
1022 }
1023 } else {
1024 adjustment = ONE_CM;
1025 }
1026 }
1027 break;
1028 }
1029 if (drawOrigX >= ABS_SIZE(adjustment)) {
1030 drawOrigX -= ABS_SIZE(adjustment);
1031 } else {
1032 adjustment = ZOOMED_SIZE(drawOrigX);
1033 drawOrigX -= ABS_SIZE(adjustment);
1034 if (drawOrigX < 0) drawOrigX = 0;
1035 }
1036 RedrawHScrollWindow();
1037 UpdDrawWinBBox();
1038 AdjSplineVs();
1039 AdjustCurText(adjustment, 0);
1040 RedrawHRulerWindow();
1041 ClearAndRedrawDrawWindow();
1042 }
1043 }
1044
ScrollRight(button_ev)1045 void ScrollRight(button_ev)
1046 XButtonEvent *button_ev;
1047 {
1048 int adjustment=0;
1049
1050 if (paperWidth <= drawWinW) return;
1051
1052 if (drawOrigX+drawWinW < paperWidth) {
1053 switch (gridSystem) {
1054 case ENGLISH_GRID:
1055 if (button_ev!=NULL && (button_ev->state & (ShiftMask|ControlMask))) {
1056 adjustment = ((int)(ZOOMED_SIZE(drawWinW)/HALF_INCH))*HALF_INCH;
1057 } else {
1058 adjustment = HALF_INCH;
1059 }
1060 break;
1061 case METRIC_GRID:
1062 if (zoomedIn && zoomScale > 1) {
1063 if (button_ev!=NULL &&
1064 (button_ev->state & (ShiftMask|ControlMask))) {
1065 adjustment = ((int)(ZOOMED_SIZE(drawWinW)/FAKE_CM))*FAKE_CM;
1066 } else {
1067 adjustment = FAKE_CM;
1068 }
1069 } else {
1070 if (button_ev!=NULL &&
1071 (button_ev->state & (ShiftMask|ControlMask))) {
1072 adjustment = ((int)(ZOOMED_SIZE(drawWinW)/ONE_CM))*ONE_CM;
1073 } else {
1074 adjustment = ONE_CM;
1075 }
1076 }
1077 break;
1078 }
1079 drawOrigX += ABS_SIZE(adjustment);
1080 RedrawHScrollWindow();
1081 UpdDrawWinBBox();
1082 AdjSplineVs();
1083 AdjustCurText(-adjustment, 0);
1084 RedrawHRulerWindow();
1085 ClearAndRedrawDrawWindow();
1086 }
1087 }
1088
1089 static
DragToInHSBar(ltx,block_start,block_w)1090 void DragToInHSBar(ltx, block_start, block_w)
1091 int ltx, block_start, block_w;
1092 {
1093 double start_frac=(double)0.0;
1094 int saved_x=drawOrigX, adjustment=0, scroll_all_the_way=FALSE;
1095
1096 if (threeDLook) {
1097 start_frac = (double)((double)(ltx-scrollBarW) /
1098 (double)(scrollAreaW-(scrollBarW<<1)));
1099 if (ltx+block_w >= scrollAreaW-scrollBarW) {
1100 scroll_all_the_way = TRUE;
1101 }
1102 } else {
1103 start_frac = (double)((double)(block_start)/(double)(scrollAreaW));
1104 if (block_start+block_w >= scrollAreaW) {
1105 scroll_all_the_way = TRUE;
1106 }
1107 }
1108 if (start_frac < 0.0) start_frac = 0.0;
1109 if (start_frac > 1.0) start_frac = 1.0;
1110 if (scroll_all_the_way) {
1111 GetMaxScrollOrigin(&drawOrigX, NULL);
1112 } else {
1113 double dv=(double)0;
1114
1115 switch (gridSystem) {
1116 case ENGLISH_GRID:
1117 dv = ((double)paperWidth) * start_frac;
1118 break;
1119 case METRIC_GRID:
1120 if (zoomedIn && zoomScale > 1) {
1121 dv = ((double)paperWidth) * start_frac;
1122 } else {
1123 dv = ((double)paperWidth) * start_frac;
1124 }
1125 break;
1126 }
1127 drawOrigX = round(dv);
1128 drawOrigX = ABS_SIZE(ZOOMED_SIZE(drawOrigX));
1129 }
1130 adjustment = saved_x - drawOrigX;
1131 if (adjustment != 0) {
1132 RedrawHScrollWindow();
1133 UpdDrawWinBBox();
1134 AdjSplineVs();
1135 AdjustCurText(ZOOMED_SIZE(adjustment), 0);
1136 RedrawHRulerWindow();
1137 ClearAndRedrawDrawWindow();
1138 } else {
1139 RedrawHScrollWindow();
1140 }
1141 }
1142
1143 static
DoDragInHSBar(btn_x,btn_offset)1144 void DoDragInHSBar(btn_x, btn_offset)
1145 int btn_x, btn_offset;
1146 {
1147 double frac=(double)0.0, start_frac=(double)0.0;
1148 int block_w=0, block_start=0, continuous_drag=FALSE;
1149 int done=FALSE, ltx=0, min_block_size=1+(windowPadding<<1);
1150 int total=max(paperWidth,(drawOrigX+drawWinW));
1151 XEvent ev;
1152
1153 scrollingCanvas = SCRL_LF;
1154 if (smoothScrollingCanvas == SMOOTH_SCROLLING) {
1155 BeginExecAnimate();
1156 if (!TgAnyButtonDown(mainDisplay, vSBarWindow)) {
1157 EndExecAnimate();
1158 ClearAndRedrawDrawWindow();
1159 return;
1160 }
1161 continuous_drag = execAnimating;
1162 }
1163 block_start = btn_x+btn_offset;
1164 frac = (double)(((double)drawWinW) / ((double)paperWidth));
1165 if (threeDLook) {
1166 start_frac = (double)(((double)(block_start-scrollBarW)) /
1167 ((double)(scrollAreaW-(scrollBarW<<1))));
1168 block_w = (frac >= 1.0) ? (scrollAreaW-(scrollBarW<<1)) :
1169 (int)(((double)(scrollAreaW-(scrollBarW<<1))) * frac);
1170 if (block_w < min_block_size) block_w = min_block_size;
1171 ltx = (start_frac + frac >= 1.0) ? scrollAreaW-scrollBarW-block_w :
1172 block_start;
1173 start_frac = (double)(((double)(ltx-scrollBarW)) /
1174 ((double)(scrollAreaW-(scrollBarW<<1))));
1175 } else {
1176 start_frac = (double)(((double)block_start)/((double)scrollAreaW));
1177 block_w = (frac >= 1.0) ? scrollAreaW :
1178 (int)(((double)scrollAreaW) * frac);
1179 if (block_w <= 0) block_w = 1;
1180 ltx = (start_frac + frac >= 1.0) ? scrollAreaW-block_w : block_start;
1181 start_frac = (double)(((double)ltx)/((double)scrollAreaW));
1182 }
1183 TgDrawScrollBar(mainDisplay, hSBarWindow, HORI_SCROLLBAR,
1184 0, 0, scrollAreaW, scrollBarW, start_frac, drawWinW, total);
1185 XGrabPointer(mainDisplay, hSBarWindow, False,
1186 PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
1187 GrabModeAsync, None, handCursor, CurrentTime);
1188
1189 while (!done) {
1190 XNextEvent(mainDisplay, &ev);
1191
1192 if (ev.type == Expose || ev.type == VisibilityNotify) {
1193 ExposeEventHandler(&ev, TRUE);
1194 } else if (ev.type == ButtonRelease) {
1195 XUngrabPointer(mainDisplay, CurrentTime);
1196 done = TRUE;
1197 } else if (ev.type == MotionNotify) {
1198 int new_x=0;
1199
1200 block_start = ev.xmotion.x;
1201
1202 if (threeDLook) {
1203 new_x = ev.xmotion.x+btn_offset;
1204 if (new_x < scrollBarW) {
1205 new_x = scrollBarW;
1206 } else if (new_x+block_w >= scrollAreaW-scrollBarW) {
1207 new_x = scrollAreaW-block_w-scrollBarW;
1208 }
1209 if (new_x != ltx) {
1210 ltx = new_x;
1211 start_frac = (double)(((double)(ltx-scrollBarW)) /
1212 ((double)(scrollAreaW-(scrollBarW<<1))));
1213 TgDrawScrollBar(mainDisplay, hSBarWindow, HORI_SCROLLBAR, 0, 0,
1214 scrollAreaW, scrollBarW, start_frac, drawWinW, total);
1215 }
1216 } else {
1217 if (block_start <= 0) {
1218 new_x = 0;
1219 } else if (block_start+block_w >= scrollAreaW) {
1220 new_x = scrollAreaW-block_w;
1221 } else {
1222 new_x = block_start;
1223 }
1224 if (new_x != ltx) {
1225 ltx = new_x;
1226 start_frac = (double)(((double)ltx)/((double)scrollAreaW));
1227 TgDrawScrollBar(mainDisplay, hSBarWindow, HORI_SCROLLBAR, 0, 0,
1228 scrollAreaW, scrollBarW, start_frac, drawWinW, total);
1229 }
1230 }
1231 if (continuous_drag) {
1232 int scroll_all_the_way=FALSE;
1233
1234 if (threeDLook) {
1235 start_frac = (double)(((double)(ltx-scrollBarW)) /
1236 ((double)(scrollAreaW-(scrollBarW<<1))));
1237 if (ltx+block_w >= scrollAreaW-scrollBarW) {
1238 scroll_all_the_way = TRUE;
1239 }
1240 } else {
1241 start_frac = (double)(((double)ltx)/((double)scrollAreaW));
1242 if (block_start+block_w >= scrollAreaW) {
1243 scroll_all_the_way = TRUE;
1244 }
1245 }
1246 RedrawAreaFromCache(start_frac, scroll_all_the_way);
1247 } else if (smoothScrollingCanvas == JUMP_SCROLLING) {
1248 DragToInHSBar(ltx, block_start, block_w);
1249 }
1250 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1251 }
1252 }
1253 if (smoothScrollingCanvas == SMOOTH_SCROLLING) {
1254 EndExecAnimate();
1255 RedrawCurText();
1256 }
1257 scrollingCanvas = INVALID;
1258
1259 DragToInHSBar(ltx, block_start, block_w);
1260 }
1261
1262 static
HSBarHandler(button_ev)1263 void HSBarHandler(button_ev)
1264 XButtonEvent *button_ev;
1265 {
1266 int do_drag=FALSE, btn_offset=0;
1267 int total=max(paperWidth,(drawOrigX+drawWinW));
1268
1269 if (!threeDLook && button_ev->button == Button3 &&
1270 button_ev->type == ButtonPress) {
1271 DoSBarBtnScroll(mainDisplay, hSBarWindow,
1272 ((button_ev->state & (ShiftMask|ControlMask)) != 0), SCRL_LF, NULL);
1273 } else if (!threeDLook && button_ev->button == Button1 &&
1274 button_ev->type == ButtonPress) {
1275 DoSBarBtnScroll(mainDisplay, hSBarWindow,
1276 ((button_ev->state & (ShiftMask|ControlMask)) != 0), SCRL_RT, NULL);
1277 } else if (button_ev->button == Button1 && button_ev->type == ButtonPress) {
1278 if (button_ev->x < scrollBarW ||
1279 button_ev->x >= scrollAreaW-scrollBarW) {
1280 int which=0;
1281 struct BBRec bbox;
1282
1283 if (button_ev->x < scrollBarW) {
1284 which = SCRL_LF;
1285 SetBBRec(&bbox, 0, 0, scrollBarW, scrollBarW);
1286 } else {
1287 which = SCRL_RT;
1288 SetBBRec(&bbox, scrollAreaW-scrollBarW, 0, scrollAreaW,
1289 scrollBarW);
1290 }
1291 DoSBarBtnScroll(mainDisplay, hSBarWindow, FALSE, which, &bbox);
1292 } else {
1293 double start_frac=(double)0.0;
1294 int hit=0;
1295
1296 if (total == 0) {
1297 start_frac = (double)1.0;
1298 } else {
1299 start_frac = (double)((double)drawOrigX / (double)total);
1300 }
1301 if (start_frac > 1.0) start_frac = 1.0;
1302 hit = TgGetScrollHit(button_ev->x, button_ev->y, HORI_SCROLLBAR,
1303 scrollAreaW, scrollBarW, start_frac, drawWinW, total,
1304 &btn_offset);
1305 if (hit == 0) {
1306 do_drag = TRUE;
1307 } else {
1308 DoSBarBtnScroll(mainDisplay, hSBarWindow, TRUE,
1309 (hit < 0 ? SCRL_LF : SCRL_RT), NULL);
1310 }
1311 }
1312 } else if (!threeDLook && button_ev->button == Button2 &&
1313 button_ev->type == ButtonPress) {
1314 do_drag = TRUE;
1315 }
1316 if (do_drag) {
1317 DoDragInHSBar(button_ev->x, btn_offset);
1318 }
1319 }
1320
ScrollEventHandler(input)1321 void ScrollEventHandler(input)
1322 XEvent *input;
1323 {
1324 if (input->xany.window == vSBarWindow) {
1325 if (input->type == Expose) {
1326 XSync(mainDisplay, False);
1327 RedrawVScrollWindow();
1328 return;
1329 } else if (input->type == MotionNotify) {
1330 if (threeDLook) {
1331 if (input->xmotion.y < scrollBarW) {
1332 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_UP), "", "");
1333 } else if (input->xmotion.y >= scrollAreaH-scrollBarW) {
1334 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_DOWN), "", "");
1335 } else {
1336 int total=max(paperHeight,(drawOrigY+drawWinH)), hit=FALSE;
1337 double start_frac=(double)0.0;
1338
1339 if (total == 0) {
1340 start_frac = (double)1.0;
1341 } else {
1342 start_frac = (double)((double)drawOrigY / (double)total);
1343 }
1344 if (start_frac > 1.0) start_frac = 1.0;
1345 hit = TgGetScrollHit(input->xmotion.x, input->xmotion.y,
1346 VERT_SCROLLBAR, scrollBarW, scrollAreaH, start_frac,
1347 drawWinH, total, NULL);
1348 if (hit < 0) {
1349 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_PAGE_UP),
1350 "", "");
1351 } else if (hit > 0) {
1352 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_PAGE_DOWN),
1353 "", "");
1354 } else {
1355 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_VERTICALLY),
1356 "", "");
1357 }
1358 }
1359 }
1360 return;
1361 } else if (input->type == EnterNotify) {
1362 if (threeDLook) {
1363 SetMouseStatus("", "", "");
1364 } else {
1365 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_DOWN),
1366 TgLoadCachedString(CSTID_SCROLL_VERTICALLY),
1367 TgLoadCachedString(CSTID_SCROLL_UP));
1368 }
1369 return;
1370 }
1371 Msg("");
1372 VSBarHandler(&(input->xbutton));
1373 return;
1374 } else if (input->xany.window == hSBarWindow) {
1375 if (input->type == Expose) {
1376 XSync(mainDisplay, False);
1377 RedrawHScrollWindow();
1378 return;
1379 } else if (input->type == MotionNotify) {
1380 if (threeDLook) {
1381 if (input->xmotion.x < scrollBarW) {
1382 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_LEFT), "", "");
1383 } else if (input->xmotion.x >= scrollAreaW-scrollBarW) {
1384 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_RIGHT), "", "");
1385 } else {
1386 int total=max(paperWidth,(drawOrigX+drawWinW)), hit=FALSE;
1387 double start_frac=(double)0.0;
1388
1389 if (total == 0) {
1390 start_frac = (double)1.0;
1391 } else {
1392 start_frac=(double)((double)drawOrigX / (double)total);
1393 }
1394 if (start_frac > 1.0) start_frac = 1.0;
1395 hit = TgGetScrollHit(input->xmotion.x, input->xmotion.y,
1396 HORI_SCROLLBAR, scrollAreaW, scrollBarW, start_frac,
1397 drawWinW, total, NULL);
1398 if (hit < 0) {
1399 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_PAGE_LEFT),
1400 "", "");
1401 } else if (hit > 0) {
1402 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_PAGE_RIGHT),
1403 "", "");
1404 } else {
1405 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_HORIZONTALLY),
1406 "", "");
1407 }
1408 }
1409 }
1410 return;
1411 } else if (input->type == EnterNotify) {
1412 if (threeDLook) {
1413 SetMouseStatus("", "", "");
1414 } else {
1415 SetMouseStatus(TgLoadCachedString(CSTID_SCROLL_RIGHT),
1416 TgLoadCachedString(CSTID_SCROLL_HORIZONTALLY),
1417 TgLoadCachedString(CSTID_SCROLL_LEFT));
1418 }
1419 return;
1420 }
1421 Msg("");
1422 HSBarHandler(&(input->xbutton));
1423 return;
1424 }
1425 }
1426
ScrollToSpecifiedOrigin(cur_page_num,orig_x,orig_y,zoom_scale,zoomed_in)1427 void ScrollToSpecifiedOrigin(cur_page_num, orig_x, orig_y, zoom_scale,
1428 zoomed_in)
1429 int cur_page_num, orig_x, orig_y, zoom_scale, zoomed_in;
1430 {
1431 int adj_caches=(zoomScale != zoom_scale || zoomedIn != zoomed_in);
1432
1433 if (cur_page_num <= 0 || cur_page_num > lastPageNum) return;
1434 if (drawOrigX == orig_x && drawOrigY == orig_y &&
1435 cur_page_num == curPageNum && !adj_caches) {
1436 return;
1437 }
1438 drawOrigX = orig_x;
1439 drawOrigY = orig_y;
1440 zoomScale = zoom_scale;
1441 zoomedIn = zoomed_in;
1442 UpdDrawWinWH();
1443
1444 UpdDrawWinBBox();
1445 AdjSplineVs();
1446 if (adj_caches) { AdjCaches(); ShowZoom(); }
1447
1448 if (cur_page_num != curPageNum) {
1449 GotoPageNum(cur_page_num);
1450 ShowPage();
1451 }
1452 ClearAndRedrawDrawWindow();
1453 RedrawRulers();
1454 RedrawScrollBars();
1455 justDupped = FALSE;
1456 }
1457
1458 static int xOrigin=0, yOrigin=0, zoomScaleOrigin=0, zoomedInOrigin=FALSE;
1459
ScrollToOrigin()1460 int ScrollToOrigin()
1461 /*
1462 * return TRUE of scrolled or zoomed
1463 */
1464 {
1465 int adj_caches=(zoomScale!=zoomScaleOrigin || zoomedIn!=zoomedInOrigin);
1466
1467 if (drawOrigX==xOrigin && drawOrigY==yOrigin && !adj_caches) {
1468 return FALSE;
1469 }
1470 TieLooseEnds();
1471 SetCurChoice(NOTHING);
1472
1473 drawOrigX = xOrigin;
1474 drawOrigY = yOrigin;
1475 zoomScale = zoomScaleOrigin;
1476 zoomedIn = zoomedInOrigin;
1477 UpdDrawWinWH();
1478
1479 UpdDrawWinBBox();
1480 AdjSplineVs();
1481 if (adj_caches) { AdjCaches(); ShowZoom(); }
1482 ClearAndRedrawDrawWindow();
1483 RedrawRulers();
1484 RedrawScrollBars();
1485 justDupped = FALSE;
1486
1487 return TRUE;
1488 }
1489
SaveOrigin()1490 void SaveOrigin()
1491 {
1492 xOrigin = drawOrigX;
1493 yOrigin = drawOrigY;
1494 zoomScaleOrigin = zoomScale;
1495 zoomedInOrigin = zoomedIn;
1496 }
1497
SetOrigin(x,y,zoom_scale,zoomed_in)1498 void SetOrigin(x, y, zoom_scale, zoomed_in)
1499 int x, y, zoom_scale, zoomed_in;
1500 {
1501 xOrigin = x;
1502 yOrigin = y;
1503 zoomScaleOrigin = zoom_scale;
1504 zoomedInOrigin = zoomed_in;
1505 }
1506
GetOrigin(pn_x,pn_y,pn_zoom_scale,pn_zoomed_in)1507 void GetOrigin(pn_x, pn_y, pn_zoom_scale, pn_zoomed_in)
1508 int *pn_x, *pn_y, *pn_zoom_scale, *pn_zoomed_in;
1509 {
1510 *pn_x = xOrigin;
1511 *pn_y = yOrigin;
1512 *pn_zoom_scale = zoomScaleOrigin;
1513 *pn_zoomed_in = zoomedInOrigin;
1514 }
1515
CleanUpScrolls()1516 void CleanUpScrolls()
1517 {
1518 if (scrl_up_bits == NULL) { }
1519 }
1520
UpdScrollWinWH()1521 void UpdScrollWinWH()
1522 {
1523 scrollAreaH = vSBarH;
1524 scrollAreaW = hSBarW;
1525 RedrawScrollBars();
1526 }
1527
InitScroll()1528 void InitScroll()
1529 {
1530 char *c_ptr=NULL;
1531
1532 smoothScrollingCanvas = JUMP_SCROLLING;
1533 if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "SmoothScrollingCanvas")) !=
1534 NULL) {
1535 if (UtilStrICmp(c_ptr, "smooth") == 0) {
1536 smoothScrollingCanvas = SMOOTH_SCROLLING;
1537 } else if (UtilStrICmp(c_ptr, "jump") == 0) {
1538 smoothScrollingCanvas = JUMP_SCROLLING;
1539 } else if (UtilStrICmp(c_ptr, "off") == 0) {
1540 smoothScrollingCanvas = NO_UPDATE_SCROLLING;
1541 } else {
1542 fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
1543 TOOL_NAME, "SmoothScrollingCanvas", c_ptr, "jump");
1544 fprintf(stderr, "\n");
1545 }
1546 }
1547 resetOriginOnAdvancePage = FALSE;
1548 if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"ResetOriginOnAdvancePage")) !=
1549 NULL && UtilStrICmp(c_ptr, "true") == 0) {
1550 resetOriginOnAdvancePage = TRUE;
1551 }
1552 UpdScrollWinWH();
1553 }
1554
ChangeScrollMode(ModeIndex)1555 void ChangeScrollMode(ModeIndex)
1556 int ModeIndex;
1557 {
1558 smoothScrollingCanvas = ModeIndex;
1559
1560 switch (smoothScrollingCanvas) {
1561 case SMOOTH_SCROLLING:
1562 sprintf(gszMsgBox, TgLoadString(STID_WILL_UPD_WIN_SMOOTH_SCROLL));
1563 break;
1564 case JUMP_SCROLLING:
1565 sprintf(gszMsgBox, TgLoadString(STID_WILL_UPD_WIN_JUMP_SCROLL));
1566 break;
1567 case NO_UPDATE_SCROLLING:
1568 sprintf(gszMsgBox, TgLoadString(STID_WILL_NOT_UPD_WIN_SCROLL));
1569 break;
1570 }
1571 Msg(gszMsgBox);
1572 }
1573
RefreshScrollModeMenu(menu)1574 int RefreshScrollModeMenu(menu)
1575 TgMenu *menu;
1576 {
1577 int i, rc=TRUE, num_items=menu->num_items;
1578 TgMenuItem *menuitems=menu->menuitems;
1579
1580 for (i=0; i < num_items; i++) {
1581 TgMenuItem *menu_item=(&menuitems[i]);
1582 TgMenuItem stMenuItem;
1583
1584 memset(&stMenuItem, 0, sizeof(TgMenuItem));
1585 stMenuItem.state = TGBS_NORMAL;
1586 stMenuItem.checked = (i == smoothScrollingCanvas);
1587 if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_RADIO,
1588 &stMenuItem)) {
1589 rc = FALSE;
1590 }
1591 }
1592 return rc;
1593 }
1594
CreateScrollModeMenu(parent_menu,x,y,menu_info,status_str_xlated)1595 TgMenu *CreateScrollModeMenu(parent_menu, x, y, menu_info, status_str_xlated)
1596 TgMenu *parent_menu;
1597 int x, y;
1598 TgMenuInfo *menu_info;
1599 int status_str_xlated; /* ignored, always 0 */
1600 {
1601 TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
1602
1603 if (menu != NULL) {
1604 menu->track_menubar = TRUE;
1605 if (!RefreshScrollModeMenu(menu)) {
1606 return TgDestroyMenu(menu, TRUE);
1607 }
1608 menu->refresh_proc = ((RefreshMenuFunc*)RefreshScrollModeMenu);
1609 }
1610 return menu;
1611 }
1612