1 /* SCCS-info %W% %E% */
2 
3 /*--------------------------------------------------------------------*/
4 /*                                                                    */
5 /*              VCG : Visualization of Compiler Graphs                */
6 /*              --------------------------------------                */
7 /*                                                                    */
8 /*   file:         fisheye.c                                          */
9 /*   version:      1.00.00                                            */
10 /*   creation:     14.4.1993                                          */
11 /*   author:       I. Lemke  (...-Version 0.99.99)                    */
12 /*                 G. Sander (Version 1.00.00-...)                    */
13 /*                 Universitaet des Saarlandes, 66041 Saarbruecken    */
14 /*                 ESPRIT Project #5399 Compare                       */
15 /*   description:  Fisheye co-ordinate transformations                */
16 /*   status:       in work                                            */
17 /*                                                                    */
18 /*--------------------------------------------------------------------*/
19 
20 #ifndef lint
21 static char *id_string="$Id: fisheye.c,v 1.3 1995/02/08 16:29:00 sander Exp $";
22 #endif
23 
24 /*
25  *   Copyright (C) 1993-2005 Saarland University
26  *
27  *  This program and documentation is free software; you can redistribute
28  *  it under the terms of the  GNU General Public License as published by
29  *  the  Free Software Foundation;  either version 2  of the License,  or
30  *  (at your option) any later version.
31  *
32  *  This  program  is  distributed  in  the hope that it will be useful,
33  *  but  WITHOUT ANY WARRANTY;  without  even  the  implied  warranty of
34  *  MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE.  See  the
35  *  GNU General Public License for more details.
36  *
37  *  You  should  have  received a copy of the GNU General Public License
38  *  along  with  this  program;  if  not,  write  to  the  Free Software
39  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40  *
41  *  The software is available per anonymous ftp at ftp.cs.uni-sb.de.
42  *  Contact  sander@cs.uni-sb.de  for additional information.
43  */
44 
45 
46 /*
47  * $Log: fisheye.c,v $
48  * Revision 1.3  1995/02/08  16:29:00  sander
49  * Small bug with K&R C solved.
50  *
51  * Revision 1.2  1995/02/08  11:11:14  sander
52  * Distribution version 1.3.
53  *
54  * Revision 1.1  1994/12/23  18:12:45  sander
55  * Initial revision
56  *
57  */
58 
59 
60 /****************************************************************************
61  * This file contains the different co-ordinate transformations used
62  * to implement the different fisheye views, which are:
63  *    1) a carthesian self adaptable continuous fisheye
64  *    2) a polar      self adaptable continuous fisheye
65  *    3) a carthesian fixed size continuous fisheye
66  *    4) a polar      fixed size continuous fisheye
67  *
68  * Fisheye views are used to see a small region with a high scaling
69  * while inspecting the remaining region with a low scaling.
70  *
71  * Note: the continuous fisheyes preserves bendings but do not
72  * preserve crossings, i.e. the fisheye view may show more or less
73  * crossings than the normal view, due to speed requirements.
74  * The noncontinous fisheyes preserve crossings but do not preserve
75  * bendings, i.e. some originally straight edges may be shown with bendings.
76  * The carthesian fisheyes do not preserve angles, while the polar
77  * fisheyes preserves at least the angle between rays starting at the
78  * focus point.
79  ***************************************************************************/
80 
81 
82 #include <stdio.h>
83 #include <stdlib.h>
84 #include <math.h>
85 #include "globals.h"
86 #include "grammar.h"
87 #include "main.h"
88 #include "options.h"
89 #include "alloc.h"
90 #include "steps.h"
91 #include "fisheye.h"
92 
93 #undef DEBUG
94 #undef debugmessage
95 #ifdef DEBUG
96 #define debugmessage(a,b) {FPRINTF(stderr,"Debug: %s %s\n",a,b);}
97 #else
98 #define debugmessage(a,b) /**/
99 #endif
100 
101 
102 /* Prototypes
103  * ----------
104  */
105 
106 static int  change_cscf_sfocus  _PP((void));
107 static int  change_cscf_gfocus  _PP((long gfx, long gfy));
108 static long cscf_sx_to_gx       _PP((int x));
109 static long cscf_sy_to_gy       _PP((int y));
110 static int  change_fcscf_gfocus _PP((long gfx, long gfy));
111 static void normalize_scaling   _PP((void));
112 static void normalize_fe_parameters _PP((void));
113 static int  change_pscf_sfocus  _PP((void));
114 static int  change_pscf_gfocus  _PP((long gfx, long gfy));
115 static void pscf_g_to_s _PP((long x, long y, int *resx, int *resy));
116 
117 
118 /* Global Variables
119  * ----------------
120  */
121 
122 /* The fisheye view flag:
123  *      0   =   normal flat view, no fisheye
124  *      1   =   CSNF = carthesian self adaptable noncontinuous (trapeze) fisheye
125  *      2   =   CSCF = carthesian self adaptable continuous fisheye
126  *      3   =   PSCF = polar      self adaptable continuous fisheye
127  *      4   =   FCSCF= carthesian fixed continuous fisheye
128  *      5   =   FPSCF= polar      fixed continuous fisheye
129  */
130 
131 int fisheye_view = 0;
132 
133 
134 /* The coordinate hash tables. They have a fixed size.
135  * For the carthesian fisheye, they map the graph position to a screen
136  * position.
137  */
138 
139 #define COORD_HASHSIZE 20000L
140 
141 static short int *xcoord_hash = NULL;
142 static short int *ycoord_hash = NULL;
143 
144 static long xhashmin, xhashmax;
145 static long yhashmin, yhashmax;
146 
147 
148 /* The minimal and maximal coordinates of the screen
149  */
150 
151 static int screen_xmin;
152 static int screen_xmax;
153 static int screen_ymin;
154 static int screen_ymax;
155 
156 /* The coordinates of the focus point on the screen
157  */
158 
159 static int sfocus_x;
160 static int sfocus_y;
161 
162 /* For the self adaptable fisheyes:
163  * The minimal and maximal coordinates of the graph
164  */
165 
166 static long graph_xmin;
167 static long graph_xmax;
168 static long graph_ymin;
169 static long graph_ymax;
170 
171 /* For the fisheye with fixed width:
172  * the fisheye distance from the graph focus.
173  */
174 
175 long gfishdist = 500L;
176 
177 
178 
179 /* The coordinates of the focus point in the graph
180  */
181 
182 long gfocus_x;
183 long gfocus_y;
184 
185 /* The scaling factors in percent. fe_scaling = 100 means normal size.
186  */
187 
188 long fe_scaling;
189 
190 
191 /* Parameter that help a faster calculation of the coordinate
192  * transformation.
193  */
194 
195 static double par_p;
196 static long par_xlp1;
197 static long par_xlp2;
198 static long par_xrp1;
199 static long par_xrp2;
200 static long par_yup1;
201 static long par_yup2;
202 static long par_ylp1;
203 static long par_ylp2;
204 
205 
206 /*--------------------------------------------------------------------*/
207 /* Carthesian self adaptable continuous fisheye                       */
208 /*--------------------------------------------------------------------*/
209 
210 /* A cartesian self adaptable continuos fisheye transforms the
211  * coordinates according to the following formula:
212  *
213  *              k * d           where d ist the distance to the focus in the
214  *      f(d) = -----------      graph, k is the magnification, A is the
215  *              A * d + 1       alignment and f(d) the resulting distance
216  *                              to the focus on the screen.
217  * Note:
218  *                 k
219  *     f'(d) = -------------
220  *             (A * d + 1)^2
221  *
222  * Hence:
223  *   f(0) = 0    i.e. the graph focus is transformed into the sceen focus
224  *  f'(0) = k    i.e. the magnification at the focus is k
225  *
226  * The alignment A is selected such that the whole graph is visible, i.e.
227  *
228  *                                      k            1
229  *   f(d_max) = sd_max     i.e.   A = ------   -   -----
230  *                                    sd_max       d_max
231  *
232  * where d_max is the maximal distance to the focus in the graph
233  * and  sd_max is the maximal distance to the focus on the sceen.
234  * The cartesion fisheye allows to have different sd_max, if we go from
235  * the focus to the left, right, bottom, up.
236  *
237  * To avoid rounding errors, we use
238  *
239  *         k          1      par2       with  par2 = k * d_max - sd_max
240  *   A = ------  -  -----  = ----
241  *       sd_max     d_max    par1       and   par1 = d_max * sd_max
242  *
243  *
244  *                        sd_max^2
245  * Note that  f'(d_max) = -----------   is less than k, if k * d_max > sd_max
246  *                        k * d_max^2
247  *
248  * which means that in this case, the graph is shrinked at the borders of the
249  * fisheye. The focus is visible at normal size, but the borders are
250  * distort such that the whole graph is visible.
251  *
252  * The screen focus is self adaptable such that the relation of the position
253  * in the graph and the position of the screen are preserved,
254  * i.e.
255  *                         x - x_min
256  *        sxf - s_min =  -------------  * (s_max - s_min)
257  *                       x_max - x_min
258  *
259  * Implementation detail: we do not transfer straight lines into curves,
260  * because this would need to much time. As result, the following properties
261  * hold:
262  *
263  *    1) the fisheye preserve bendings
264  *    2) the fisheye does not preserve crossings
265  *    3) the fisheye does not preserve angles, since it is a carthesian
266  *       transformation.
267  */
268 
269 
270 
271 /*  Calculation of the auxiliary parameters
272  *  ---------------------------------------
273  *  A new calculation of the auxiliary parameters is necessary if
274  *    a) the scaling changes.
275  *    b) the position of the focus in the graph changes.
276  *    c) the position of the focus in the window chnages.
277  *    d) the size of the window changes.
278  */
279 
280 #ifdef ANSI_C
calc_cscf_parameters(void)281 static void calc_cscf_parameters(void)
282 #else
283 static void calc_cscf_parameters()
284 #endif
285 {
286 	long s, t;
287 	register int i;
288 	short int k;
289 
290 	debugmessage("calc_cscf_parameters","");
291 
292 	par_xrp1 = (long)(screen_xmax-sfocus_x)*(graph_xmax-gfocus_x);
293 	par_xrp2 = fe_scaling*(graph_xmax-gfocus_x)
294 			- 100L*(long)(screen_xmax-sfocus_x);
295 	par_xlp1 = (long)(sfocus_x-screen_xmin)*(gfocus_x-graph_xmin);
296 	par_xlp2 = fe_scaling*(gfocus_x-graph_xmin)
297 			- 100L*(long)(sfocus_x-screen_xmin);
298 	par_ylp1 = (long)(screen_ymax-sfocus_y)*(graph_ymax-gfocus_y);
299 	par_ylp2 = fe_scaling*(graph_ymax-gfocus_y)
300 			- 100L*(long)(screen_ymax-sfocus_y);
301 	par_yup1 = (long)(sfocus_y-screen_ymin)*(gfocus_y-graph_ymin);
302 	par_yup2 = fe_scaling*(gfocus_y-graph_ymin)
303 			- 100L*(sfocus_y-screen_ymin);
304 
305 	if (par_xrp1==0L) par_xrp1 = 1L;
306 	if (par_xlp1==0L) par_xlp1 = 1L;
307 	if (par_ylp1==0L) par_ylp1 = 1L;
308 	if (par_yup1==0L) par_yup1 = 1L;
309 	if (par_xrp2==0L) par_xrp2 = 1L;
310 	if (par_xlp2==0L) par_xlp2 = 1L;
311 	if (par_ylp2==0L) par_ylp2 = 1L;
312 	if (par_yup2==0L) par_yup2 = 1L;
313 
314 	normalize_fe_parameters();
315 
316 	if (xcoord_hash) {
317 		t = graph_xmax+1L;
318 		if (t>COORD_HASHSIZE) t = COORD_HASHSIZE;
319 		for (i=0; i<(int)t; i++) xcoord_hash[i]=(short)0;
320 		if (screen_xmin < screen_xmax)
321 			for (i=screen_xmin; i<=screen_xmax; i++) {
322 				s = cscf_sx_to_gx(i);
323 				if (s>=0 && s<COORD_HASHSIZE)
324 					xcoord_hash[s] = (short)i;
325 			}
326 		k = xcoord_hash[0];
327 		for (i=0; i<(int)t; i++) {
328 			if (xcoord_hash[i]==(short)0) xcoord_hash[i] = k;
329 			else k = xcoord_hash[i];
330 		}
331 	}
332 	if (ycoord_hash) {
333 		t = graph_ymax+1;
334 		if (t>COORD_HASHSIZE) t = COORD_HASHSIZE;
335 		for (i=0; i<(int)t; i++) ycoord_hash[i]=(short)0;
336 		if (screen_ymin < screen_ymax)
337 			for (i=screen_ymin; i<=screen_ymax; i++) {
338 				s = cscf_sy_to_gy(i);
339 				if (s>=0 && s<COORD_HASHSIZE)
340 					ycoord_hash[s] = (short)i;
341 			}
342 		k = ycoord_hash[0];
343 		for (i=0; i<t; i++) {
344 			if (ycoord_hash[i]==(short)0) ycoord_hash[i] = k;
345 			else k = ycoord_hash[i];
346 		}
347 	}
348 	xhashmin = 0L;
349 	xhashmax = COORD_HASHSIZE-1L;
350 	yhashmin = 0L;
351 	yhashmax = COORD_HASHSIZE-1L;
352 }
353 
354 
355 
356 /*  Initialization of the cscf_fisheye
357  *  ----------------------------------
358  */
359 
360 
361 #ifdef ANSI_C
init_cscf(int sxmin,int sxmax,int symin,int symax,long gfx,long gfy)362 static void init_cscf(int sxmin, int sxmax, int symin, int symax,
363 		long gfx, long gfy)
364 #else
365 static void init_cscf(sxmin, sxmax, symin, symax, gfx, gfy)
366 	int sxmin;
367 	int sxmax;
368 	int symin;
369 	int symax;
370 	long gfx;
371 	long gfy;
372 #endif
373 {
374 	debugmessage("init_cscf","");
375 
376 	if ((sxmin!=0) || (sxmax!=0) || (symin!=0) || (symax!=0)) {
377 		screen_xmin = sxmin;
378 		screen_xmax = sxmax;
379 		screen_ymin = symin;
380 		screen_ymax = symax;
381 	}
382 	graph_xmin = 0L;
383 	graph_xmax = maximal_xpos + (long)G_xbase;
384 	graph_ymin = 0L;
385 	graph_ymax = maximal_ypos + (long)G_ybase;
386 	gfocus_x    = gfx;
387 	gfocus_y    = gfy;
388 	sfocus_x    = (int)((long)(screen_xmax-screen_xmin)
389 			* (gfocus_x-graph_xmin) / (graph_xmax-graph_xmin));
390 	sfocus_y    = (int)((long)(screen_ymax-screen_ymin)
391 			* (gfocus_y-graph_ymin) / (graph_ymax-graph_ymin));
392 	if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
393 	if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
394 	if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
395 	if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
396 	if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
397 	if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
398 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
399 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
400 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
401 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
402 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
403 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
404 	V_xmin = 0L;
405 	V_xmax = MAXLONG;
406 	V_ymin = 0L;
407 	V_ymax = MAXLONG;
408 	calc_cscf_parameters();
409 }
410 
411 
412 /*  Change scaling
413  *  --------------
414  */
415 
416 #ifdef ANSI_C
change_cscf_scaling(void)417 static void change_cscf_scaling(void)
418 #else
419 static void change_cscf_scaling()
420 #endif
421 {
422 	debugmessage("change_cscf_scaling","");
423 
424 	calc_cscf_parameters();
425 }
426 
427 
428 /*  Change windowsize
429  *  -----------------
430  *  Returns 1, if a redraw is necessary.
431  */
432 
433 #ifdef ANSI_C
change_cscf_winsize(int sxmin,int sxmax,int symin,int symax)434 static int change_cscf_winsize(int sxmin, int sxmax, int symin, int symax)
435 #else
436 static int change_cscf_winsize(sxmin, sxmax, symin, symax)
437 	int sxmin;
438 	int sxmax;
439 	int symin;
440 	int symax;
441 #endif
442 {
443 	int oldsxmin, oldsxmax, oldsymin, oldsymax;
444 	int ret;
445 
446 	debugmessage("change_cscf_winsize","");
447 
448 	ret = 0;
449 	oldsxmin = screen_xmin;
450 	oldsxmax = screen_xmax;
451 	oldsymin = screen_ymin;
452 	oldsymax = screen_ymax;
453 	screen_xmin = sxmin;
454 	screen_xmax = sxmax;
455 	screen_ymin = symin;
456 	screen_ymax = symax;
457 	ret += change_cscf_sfocus();
458 	if (oldsxmin != screen_xmin) return(1);
459 	if (oldsxmax != screen_xmax) return(1);
460 	if (oldsymin != screen_ymin) return(1);
461 	if (oldsymax != screen_ymax) return(1);
462 	return(ret);
463 }
464 
465 
466 /*  Change screen focus
467  *  -------------------
468  *  Returns 1, if a redraw is necessary.
469  */
470 
471 #ifdef ANSI_C
change_cscf_sfocus(void)472 static int change_cscf_sfocus(void)
473 #else
474 static int change_cscf_sfocus()
475 #endif
476 {
477 	int oldsfx, oldsfy;
478 
479 	debugmessage("change_cscf_sfocus","");
480 
481 	oldsfx = sfocus_x;
482 	oldsfy = sfocus_y;
483 	sfocus_x    = (int)((long)(screen_xmax-screen_xmin)
484 			* (gfocus_x-graph_xmin) / (graph_xmax-graph_xmin));
485 	sfocus_y    = (int)((long)(screen_ymax-screen_ymin)
486 			* (gfocus_y-graph_ymin) / (graph_ymax-graph_ymin));
487 	if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
488 	if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
489 	if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
490 	if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
491 	if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
492 	if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
493 	calc_cscf_parameters();
494 	if (oldsfx != sfocus_x) return(1);
495 	if (oldsfy != sfocus_y) return(1);
496 	return(0);
497 }
498 
499 
500 /*  Change graph focus
501  *  ------------------
502  *  Returns 1, if a redraw is necessary.
503  */
504 
505 #ifdef ANSI_C
change_cscf_gfocus(long gfx,long gfy)506 static int change_cscf_gfocus(long gfx, long gfy)
507 #else
508 static int change_cscf_gfocus(gfx, gfy)
509 	long gfx;
510 	long gfy;
511 #endif
512 {
513 	int ret;
514 	long oldgfx, oldgfy;
515 
516 	debugmessage("change_cscf_gfocus","");
517 
518 	ret = 0;
519 	oldgfx = gfocus_x;
520 	oldgfy = gfocus_y;
521 	gfocus_x    = gfx;
522 	gfocus_y    = gfy;
523 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
524 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
525 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
526 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
527 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
528 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
529 	ret += change_cscf_sfocus();
530 	if (oldgfx != gfocus_x) return(1);
531 	if (oldgfy != gfocus_y) return(1);
532 	return(ret);
533 }
534 
535 
536 /*  Increment graph focus
537  *  ---------------------
538  *  Returns 1, if a redraw is necessary.
539  */
540 
541 #ifdef ANSI_C
incr_cscf_gfocus(long dfx,long dfy)542 static int incr_cscf_gfocus(long dfx, long dfy)
543 #else
544 static int incr_cscf_gfocus(dfx, dfy)
545 	long dfx;
546 	long dfy;
547 #endif
548 {
549 	debugmessage("incr_cscf_sfocus","");
550 
551 	if ((dfx==0L) && (dfy==0L)) return(0);
552 	gfocus_x    += dfx;
553 	gfocus_y    += dfy;
554 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
555 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
556 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
557 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
558 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
559 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
560 	(void)change_cscf_sfocus();
561 	return(1);
562 }
563 
564 
565 /*  Translate a x,y-coord. of the graph into a x,y-coord. of the screen
566  *  -------------------------------------------------------------------
567  */
568 
569 #ifdef ANSI_C
cscf_g_to_s(long x,long y,int * resx,int * resy)570 static void cscf_g_to_s(long x, long y, int *resx, int *resy)
571 #else
572 static void cscf_g_to_s(x, y, resx, resy)
573 	long x, y;
574 	int  *resx, *resy;
575 #endif
576 {
577 	long dist, help;
578 
579 	if ((xcoord_hash) && (x>=xhashmin) && (x<=xhashmax)) {
580 		/* NOTHING: this is handled in the entry point */;
581 	}
582 	else if (x > gfocus_x) {
583 		dist = x - gfocus_x;
584 		help = (par_xrp2 * dist * 10L) / par_xrp1 + 1000L;
585 		if (help<=0L) help = MAXLONG;
586 		*resx = sfocus_x +
587 			(int)((fe_scaling * dist * 10L) / help);
588 	}
589 	else {
590 		dist = gfocus_x - x;
591 		help = (par_xlp2 * dist * 10L) / par_xlp1 + 1000L;
592 		if (help<=0L) help = MAXLONG;
593 		*resx = sfocus_x -
594 			(int)((fe_scaling * dist * 10) / help);
595 	}
596 
597 	if ((ycoord_hash) && (y>=yhashmin) && (y<=yhashmax)) {
598 		/* NOTHING: this is handled in the entry point */;
599 	}
600 	else if (y > gfocus_y) {
601 		dist = y - gfocus_y;
602 		help = (par_ylp2 * dist * 10L) / par_ylp1 + 1000L;
603 		if (help<=0L) help = MAXLONG;
604 		*resy = sfocus_y +
605 			(int)((fe_scaling * dist * 10) / help);
606 	}
607 	else {
608 		dist = gfocus_y - y;
609 		help = (par_yup2 * dist * 10L) / par_yup1 + 1000L;
610 		if (help<=0L) help = MAXLONG;
611 		*resy = sfocus_y -
612 			(int)((fe_scaling * dist * 10) / help);
613 	}
614 }
615 
616 
617 
618 /*  Translate a x,y-coord. of the screen into a x,y-coord. of the graph
619  *  -------------------------------------------------------------------
620  */
621 
622 #ifdef ANSI_C
cscf_s_to_g(int x,int y,long * resx,long * resy)623 static void cscf_s_to_g(int x, int y, long *resx, long *resy)
624 #else
625 static void cscf_s_to_g(x, y, resx, resy)
626 	int x, y;
627 	long *resx, *resy;
628 #endif
629 {
630 	long dist, help;
631 
632 	if (x > sfocus_x) {
633 		dist = (long)(x - sfocus_x);
634 		help = - par_xrp2 * dist + par_xrp1 * fe_scaling;
635 		if (help!=0L)
636 			*resx = gfocus_x + (100L * dist * par_xrp1) / help;
637 		else    *resx = COORD_HASHSIZE;
638 	}
639 	else {
640 		dist = (long)(sfocus_x - x);
641 		help = - par_xlp2 * dist + par_xlp1 * fe_scaling;
642 		if (help!=0L)
643 			*resx = gfocus_x - (100L * dist * par_xlp1) / help;
644 		else    *resx = COORD_HASHSIZE;
645 	}
646 
647 	if (y > sfocus_y) {
648 		dist = (long)(y - sfocus_y);
649 		help = - par_ylp2 * dist + par_ylp1 * fe_scaling;
650 		if (help!=0L)
651 			*resy = gfocus_y + (100L * dist * par_ylp1) / help;
652 		else	*resy = COORD_HASHSIZE;
653 	}
654 	else {
655 		dist = (long)(sfocus_y - y);
656 		help = - par_yup2 * dist + par_yup1 * fe_scaling;
657 		if (help!=0L)
658 			*resy = gfocus_y - (100L * dist * par_yup1) / help;
659 		else 	*resy = COORD_HASHSIZE;
660 	}
661 }
662 
663 
664 /*  Translate a x-coordinate of the screen into a x-coordinate of the graph
665  *  -----------------------------------------------------------------------
666  *  This is exactly as above, however only for the x component.
667  */
668 
669 #ifdef ANSI_C
cscf_sx_to_gx(int x)670 static long cscf_sx_to_gx(int x)
671 #else
672 static long cscf_sx_to_gx(x)
673 	int x;
674 #endif
675 {
676 	long dist, help;
677 
678 	if (x > sfocus_x) {
679 		dist = (long)(x - sfocus_x);
680 		help = - par_xrp2 * dist + par_xrp1 * fe_scaling;
681 		if (help!=0L)
682 			return( gfocus_x + (100L * dist * par_xrp1) / help );
683 		return( COORD_HASHSIZE );
684 	}
685 	else {
686 		dist = (long)(sfocus_x - x);
687 		help = - par_xlp2 * dist + par_xlp1 * fe_scaling;
688 		if (help!=0L)
689 			return( gfocus_x - (100L * dist * par_xlp1) / help );
690 		return( COORD_HASHSIZE );
691 	}
692 }
693 
694 
695 /*  Translate a y-coordinate of the screen into a y-coordinate of the graph
696  *  -----------------------------------------------------------------------
697  *  This is exactly as above, however only for the y component.
698  */
699 
700 #ifdef ANSI_C
cscf_sy_to_gy(int y)701 static long cscf_sy_to_gy(int y)
702 #else
703 static long cscf_sy_to_gy(y)
704 	int y;
705 #endif
706 {
707 	long dist, help;
708 
709 	if (y > sfocus_y) {
710 		dist = (long)(y - sfocus_y);
711 		help = - par_ylp2 * dist + par_ylp1 * fe_scaling;
712 		if (help!=0L)
713 			return( gfocus_y + (100L * dist * par_ylp1) / help );
714 		return( COORD_HASHSIZE );
715 	}
716 	else {
717 		dist = (long)(sfocus_y - y);
718 		help = - par_yup2 * dist + par_yup1 * fe_scaling;
719 		if (help!=0L)
720 			return( gfocus_y - (100L * dist * par_yup1) / help );
721 		return( COORD_HASHSIZE );
722 	}
723 }
724 
725 
726 /*--------------------------------------------------------------------*/
727 /* Carthesian fixed width continuous fisheye                          */
728 /*--------------------------------------------------------------------*/
729 
730 /* A carthesian continuos fisheye with a fixed radius of visible range.
731  * For the formula, see the self adaptable continuous fisheye.
732  * Now, we fisheye focus is always at the middle of the screen
733  * and the maximal distance to the focus in the graph is gfishdist.
734  * In the formula, d_max is now gfishdist.
735  *
736  *  with  par2 = k * gfishdist - sd_max
737  *  and   par1 = gfishdist * sd_max
738  *
739  *
740  * Implementation detail: we do not transfer straight lines into curves,
741  * because this would need to much time. As result, the following properties
742  * hold:
743  *
744  *    1) the fisheye preserve bendings
745  *    2) the fisheye does not preserve crossings
746  *    3) the fisheye does not preserve angles, since it is a carthesian
747  *       transformation.
748  */
749 
750 
751 
752 /*  Calculation of the auxiliary parameters
753  *  ---------------------------------------
754  *  A new calculation of the auxiliary parameters is necessary if
755  *    a) the scaling changes.
756  *    b) the position of the focus in the graph changes.
757  *    c) the position of the focus in the window chnages.
758  *    d) the size of the window changes.
759  */
760 
761 
762 #ifdef ANSI_C
calc_fcscf_parameters(void)763 static void calc_fcscf_parameters(void)
764 #else
765 static void calc_fcscf_parameters()
766 #endif
767 {
768 	long s, t;
769 	register int i;
770 	short int k;
771 
772 	debugmessage("calc_fcscf_parameters","");
773 
774 	par_xrp1 = (long)(screen_xmax-sfocus_x) * gfishdist;
775 	par_xrp2 = fe_scaling * gfishdist
776 			- 100L*(long)(screen_xmax-sfocus_x);
777 	par_xlp1 = (long)(sfocus_x-screen_xmin) * gfishdist;
778 	par_xlp2 = fe_scaling * gfishdist
779 			- 100L*(long)(sfocus_x-screen_xmin);
780 	par_ylp1 = (long)(screen_ymax-sfocus_y) * gfishdist;
781 	par_ylp2 = fe_scaling * gfishdist
782 			- 100L*(long)(screen_ymax-sfocus_y);
783 	par_yup1 = (long)(sfocus_y-screen_ymin) * gfishdist;
784 	par_yup2 = fe_scaling * gfishdist
785 			- 100L*(sfocus_y-screen_ymin);
786 
787 	if (par_xrp1==0L) par_xrp1 = 1L;
788 	if (par_xlp1==0L) par_xlp1 = 1L;
789 	if (par_ylp1==0L) par_ylp1 = 1L;
790 	if (par_yup1==0L) par_yup1 = 1L;
791 	if (par_xrp2<=0L) par_xrp2 = 1L;
792 	if (par_xlp2<=0L) par_xlp2 = 1L;
793 	if (par_ylp2<=0L) par_ylp2 = 1L;
794 	if (par_yup2<=0L) par_yup2 = 1L;
795 
796 	normalize_fe_parameters();
797 
798 	if (xcoord_hash) {
799 		t = graph_xmax+1L;
800 		if (t>COORD_HASHSIZE) t = COORD_HASHSIZE;
801 		for (i=0; i<(int)t; i++) xcoord_hash[i]=(short)0;
802 		for (i=0; i<=G_xmax; i++) {
803 			s = cscf_sx_to_gx(i);
804 			if (s>=0 && s<COORD_HASHSIZE)
805 				xcoord_hash[s] = (short)i;
806 		}
807 		k = xcoord_hash[0];
808 		for (i=0; i<(int)t; i++) {
809 			if (xcoord_hash[i]==(short)0) xcoord_hash[i] = k;
810 			else k = xcoord_hash[i];
811 		}
812 		xhashmin = cscf_sx_to_gx(i);
813 		if (xhashmin < 0) xhashmin = 0;
814 		xhashmax = cscf_sx_to_gx(G_xmax);
815 		if (xhashmax>COORD_HASHSIZE-1)
816 			xhashmax = COORD_HASHSIZE-1;
817 	}
818 	if (ycoord_hash) {
819 		t = graph_ymax+1;
820 		if (t>COORD_HASHSIZE) t = COORD_HASHSIZE;
821 		for (i=0; i<(int)t; i++) ycoord_hash[i]=(short)0;
822 		i = 0;
823 		s = 0L;
824 		while ((s<COORD_HASHSIZE)&&(i<G_ymax)) {
825 			s = cscf_sy_to_gy(i);
826 			if (s>=0 && s<COORD_HASHSIZE)
827 				ycoord_hash[s] = (short)i;
828 			i++;
829 		}
830 		k = ycoord_hash[0];
831 		for (i=0; i<t; i++) {
832 			if (ycoord_hash[i]==(short)0) ycoord_hash[i] = k;
833 			else k = ycoord_hash[i];
834 		}
835 		yhashmin = cscf_sy_to_gy(i);
836 		if (yhashmin < 0) yhashmin = 0;
837 		yhashmax = cscf_sy_to_gy(G_ymax);
838 		if (yhashmax>COORD_HASHSIZE-1)
839 			yhashmax = COORD_HASHSIZE-1;
840 	}
841 }
842 
843 
844 
845 /*  Initialization of the fcscf_fisheye
846  *  -----------------------------------
847  */
848 
849 
850 #ifdef ANSI_C
init_fcscf(int sxmin,int sxmax,int symin,int symax,long gfx,long gfy)851 static void init_fcscf(int sxmin, int sxmax, int symin, int symax,
852 		long gfx, long gfy)
853 #else
854 static void init_fcscf(sxmin, sxmax, symin, symax, gfx, gfy)
855 	int sxmin;
856 	int sxmax;
857 	int symin;
858 	int symax;
859 	long gfx;
860 	long gfy;
861 #endif
862 {
863 	debugmessage("init_fcscf","");
864 
865 	if ((sxmin!=0) || (sxmax!=0) || (symin!=0) || (symax!=0)) {
866 		screen_xmin = sxmin;
867 		screen_xmax = sxmax;
868 		screen_ymin = symin;
869 		screen_ymax = symax;
870 	}
871 	graph_xmin = 0L;
872 	graph_xmax = maximal_xpos + (long)G_xbase;
873 	graph_ymin = 0L;
874 	graph_ymax = maximal_ypos + (long)G_ybase;
875 
876 	gfishdist = 2L * (long)(screen_xmax-screen_xmin);
877 	if (gfishdist<30L)  gfishdist = 30;
878 
879 	sfocus_x    = (screen_xmax+screen_xmin)/2;
880 	sfocus_y    = (screen_ymax+screen_ymin)/2;
881 	gfocus_x    = gfx;
882 	gfocus_y    = gfy;
883 
884 	if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
885 	if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
886 	if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
887 	if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
888 	if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
889 	if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
890 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
891 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
892 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
893 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
894 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
895 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
896 	V_xmin = 0L;
897 	V_xmax = MAXLONG;
898 	V_ymin = 0L;
899 	V_ymax = MAXLONG;
900 	calc_fcscf_parameters();
901 }
902 
903 
904 /*  Change scaling
905  *  --------------
906  */
907 
908 #ifdef ANSI_C
change_fcscf_scaling(void)909 static void change_fcscf_scaling(void)
910 #else
911 static void change_fcscf_scaling()
912 #endif
913 {
914 	debugmessage("change_fcscf_scaling","");
915 
916 	calc_fcscf_parameters();
917 }
918 
919 
920 /*  Change windowsize
921  *  -----------------
922  *  Returns 1, if a redraw is necessary.
923  */
924 
925 #ifdef ANSI_C
change_fcscf_winsize(int sxmin,int sxmax,int symin,int symax)926 static int change_fcscf_winsize(int sxmin, int sxmax, int symin, int symax)
927 #else
928 static int change_fcscf_winsize(sxmin, sxmax, symin, symax)
929 	int sxmin;
930 	int sxmax;
931 	int symin;
932 	int symax;
933 #endif
934 {
935 	int oldsxmin, oldsxmax, oldsymin, oldsymax;
936 
937 	debugmessage("change_fcscf_winsize","");
938 
939 	oldsxmin = screen_xmin;
940 	oldsxmax = screen_xmax;
941 	oldsymin = screen_ymin;
942 	oldsymax = screen_ymax;
943 	screen_xmin = sxmin;
944 	screen_xmax = sxmax;
945 	screen_ymin = symin;
946 	screen_ymax = symax;
947 	sfocus_x    = (screen_xmax+screen_xmin)/2;
948 	sfocus_y    = (screen_ymax+screen_ymin)/2;
949 	calc_fcscf_parameters();
950 	if (oldsxmin != screen_xmin) return(1);
951 	if (oldsxmax != screen_xmax) return(1);
952 	if (oldsymin != screen_ymin) return(1);
953 	if (oldsymax != screen_ymax) return(1);
954 	return(0);
955 }
956 
957 
958 
959 
960 /*  Change graph focus
961  *  ------------------
962  *  Returns 1, if a redraw is necessary.
963  */
964 
965 #ifdef ANSI_C
change_fcscf_gfocus(long gfx,long gfy)966 static int change_fcscf_gfocus(long gfx, long gfy)
967 #else
968 static int change_fcscf_gfocus(gfx, gfy)
969 	long gfx;
970 	long gfy;
971 #endif
972 {
973 	long oldgfx, oldgfy;
974 
975 	debugmessage("change_fcscf_gfocus","");
976 
977 	oldgfx = gfocus_x;
978 	oldgfy = gfocus_y;
979 	gfocus_x    = gfx;
980 	gfocus_y    = gfy;
981 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
982 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
983 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
984 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
985 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
986 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
987 
988 	/* The parameters don't change, but the hash tables may change */
989 	calc_fcscf_parameters();
990 
991 	if (oldgfx != gfocus_x) return(1);
992 	if (oldgfy != gfocus_y) return(1);
993 	return(0);
994 }
995 
996 
997 /*  Increment graph focus
998  *  ---------------------
999  *  Returns 1, if a redraw is necessary.
1000  */
1001 
1002 #ifdef ANSI_C
incr_fcscf_gfocus(long dfx,long dfy)1003 static int incr_fcscf_gfocus(long dfx, long dfy)
1004 #else
1005 static int incr_fcscf_gfocus(dfx, dfy)
1006 	long dfx;
1007 	long dfy;
1008 #endif
1009 {
1010 	debugmessage("incr_fcscf_sfocus","");
1011 
1012 	if ((dfx==0L) && (dfy==0L)) return(0);
1013 	gfocus_x    += dfx;
1014 	gfocus_y    += dfy;
1015 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1016 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1017 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1018 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1019 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1020 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1021 
1022 	/* The parameters don't change, but the hash tables may change */
1023 	calc_fcscf_parameters();
1024 
1025 	return(1);
1026 }
1027 
1028 
1029 /* Change the fisheye width
1030  * ------------------------
1031  * Returns 1, if a redraw is necessary.
1032  */
1033 
1034 #ifdef ANSI_C
set_fcscf_gfishdist(long gd)1035 static int set_fcscf_gfishdist(long gd)
1036 #else
1037 static int set_fcscf_gfishdist(gd)
1038 long gd;
1039 #endif
1040 {
1041 	int ret;
1042 
1043 	debugmessage("set_fcscf_gfishdist","");
1044 
1045 	if (gd<30L) return(0);
1046 
1047 	ret = (gfishdist != gd);
1048 	gfishdist = gd;
1049 	calc_fcscf_parameters();
1050 	return(ret);
1051 }
1052 
1053 
1054 
1055 /*--------------------------------------------------------------------*/
1056 /* Polar self adaptable continuous fisheye                            */
1057 /*--------------------------------------------------------------------*/
1058 
1059 /* A polar self adaptable continuos fisheye preserves the angles of the
1060  * vectors starting at the focus point. It transforms the distance from
1061  * the focus point according to the following formula:
1062  *
1063  *              k * d           where d ist the distance to the focus in the
1064  *      f(d) = -----------      graph, k is the magnification, A is the
1065  *              A * d + 1       alignment and f(d) the resulting distance
1066  *                              to the focus on the screen.
1067  * Note:
1068  *                 k
1069  *     f'(d) = -------------
1070  *             (A * d + 1)^2
1071  *
1072  * Hence:
1073  *   f(0) = 0    i.e. the graph focus is transformed into the sceen focus
1074  *  f'(0) = k    i.e. the magnification at the focus is k
1075  *
1076  * The alignment A is selected such that the whole graph is visible, i.e.
1077  *
1078  *                                      k            1
1079  *   f(d_max) = sd_max     i.e.   A = ------   -   -----
1080  *                                    sd_max       d_max
1081  *
1082  * where d_max is the maximal distance to the focus in the graph
1083  * and  sd_max is the maximal distance to the focus on the sceen.
1084  * The polar fisheye has only one d_max and sd_max.
1085  * d_max is the minimal radius around the graph focus which encloses
1086  * the whole graph.
1087  * sdmax is the maximal radius around the screen focus such that this
1088  * circle is inside the screen.
1089  *
1090  * To avoid rounding errors, we use
1091  *
1092  *         k          1      par2       with  par2 = k * d_max - sd_max
1093  *   A = ------  -  -----  = ----
1094  *       sd_max     d_max    par1       and   par1 = d_max * sd_max
1095  *
1096  *
1097  *                        sd_max^2
1098  * Note that  f'(d_max) = -----------   is less than k, if k * d_max > sd_max
1099  *                        k * d_max^2
1100  *
1101  * which means that in this case, the graph is shrinked at the borders of the
1102  * fisheye. The focus is visible at normal size, but the borders are
1103  * distort such that the whole graph is visible.
1104  *
1105  * The screen focus is self adaptable such that whole graph is visible.
1106  * We cannot give a good formula for the problem of finding the screen
1107  * focus. The reason is: if we have a screen focus, we can calculate
1108  * par1 and par2 such that the left part is completely visible, or such
1109  * that the right part is completely visible. But if the right part is
1110  * completely visible, the left part may be clipped, i.e. not completely
1111  * visible, or the left part may have to much free space.
1112  * To avoid this, we simply try out the screen focus and select the
1113  * position where the graph fits as best into the window.
1114  *
1115  * Implementation detail: we do not transfer straight lines into curves,
1116  * because this would need to much time. As result, the following properties
1117  * hold:
1118  *
1119  *    1) the fisheye preserve bendings
1120  *    2) the fisheye does not preserve crossings
1121  *    3) the fisheye does not preserve angles. However, it preserves
1122  *       angles of rays starting at the focus point, since it is a polar
1123  *       transformation.
1124  */
1125 
1126 
1127 
1128 /*  Calculation of the auxiliary parameters
1129  *  ---------------------------------------
1130  *  A new calculation of the auxiliary parameters is necessary if
1131  *    a) the scaling changes.
1132  *    b) the position of the focus in the graph changes.
1133  *    c) the position of the focus in the window chnages.
1134  *    d) the size of the window changes.
1135  */
1136 
1137 #ifdef ANSI_C
calc_pscf_parameters(void)1138 static void calc_pscf_parameters(void)
1139 #else
1140 static void calc_pscf_parameters()
1141 #endif
1142 {
1143 	long s, t;
1144 	int  x1, y1, diff, bestdiff, bestsf;
1145 	double bestpar1, bestpar2;
1146 
1147 	debugmessage("calc_pscf_parameters","");
1148 
1149 	xhashmin = 0L;
1150 	xhashmax = -1L;
1151 	yhashmin = 0L;
1152 	yhashmax = -1L;
1153 
1154 
1155 	bestdiff = MAXINT;
1156 	for (sfocus_x = screen_xmin+5; sfocus_x<screen_xmax-5; sfocus_x += 5) {
1157 		diff = 0;
1158 		s = (long)(screen_xmax-sfocus_x);
1159 		t = graph_xmax - gfocus_x;
1160 
1161 		par_xrp1 = s*t;
1162 		par_xrp2 = fe_scaling*t - 100L*s;
1163 
1164 		if (par_xrp1==0L) par_xrp1 = 1L;
1165 		if (par_xrp2==0L) par_xrp2 = 1L;
1166 		par_p = (double)par_xrp2 / (double)par_xrp1;
1167 		pscf_g_to_s(graph_xmin, gfocus_y, &x1, &y1);
1168 		if (x1<screen_xmin) diff += (screen_xmin-x1);
1169 		else diff += (x1-screen_xmin);
1170 		if (diff < bestdiff) {
1171 			bestdiff = diff;
1172 			bestpar1 = par_p;
1173 			bestsf  = sfocus_x;
1174 		}
1175 	}
1176 	sfocus_x = bestsf;
1177 
1178 	bestdiff = MAXINT;
1179 	for (sfocus_y = screen_ymin+5; sfocus_y<screen_ymax-5; sfocus_y += 5) {
1180 		diff = 0;
1181 		s = (long)(screen_ymax-sfocus_y);
1182 		t = graph_ymax - gfocus_y;
1183 
1184 		par_xrp1 = s*t;
1185 		par_xrp2 = fe_scaling*t - 100L*s;
1186 
1187 		if (par_xrp1==0L) par_xrp1 = 1L;
1188 		if (par_xrp2==0L) par_xrp2 = 1L;
1189 		par_p = (double)par_xrp2 / (double)par_xrp1;
1190 		pscf_g_to_s(gfocus_x, graph_ymin, &x1, &y1);
1191 		if (y1<screen_ymin) diff += (screen_ymin-y1);
1192 		else diff += (y1-screen_ymin);
1193 		if (diff < bestdiff) {
1194 			bestdiff = diff;
1195 			bestpar2 = par_p;
1196 			bestsf   = sfocus_y;
1197 		}
1198 	}
1199 	sfocus_y = bestsf;
1200 
1201 	if (bestpar2>bestpar1) par_p = bestpar2;
1202 	else par_p = bestpar1;
1203 }
1204 
1205 
1206 
1207 /*  Initialization of the pscf_fisheye
1208  *  ----------------------------------
1209  */
1210 
1211 
1212 #ifdef ANSI_C
init_pscf(int sxmin,int sxmax,int symin,int symax,long gfx,long gfy)1213 static void init_pscf(int sxmin, int sxmax, int symin, int symax,
1214 		long gfx, long gfy)
1215 #else
1216 static void init_pscf(sxmin, sxmax, symin, symax, gfx, gfy)
1217 	int sxmin;
1218 	int sxmax;
1219 	int symin;
1220 	int symax;
1221 	long gfx;
1222 	long gfy;
1223 #endif
1224 {
1225 	debugmessage("init_pscf","");
1226 
1227 	if ((sxmin!=0) || (sxmax!=0) || (symin!=0) || (symax!=0)) {
1228 		screen_xmin = sxmin;
1229 		screen_xmax = sxmax;
1230 		screen_ymin = symin;
1231 		screen_ymax = symax;
1232 	}
1233 	graph_xmin = 0L;
1234 	graph_xmax = maximal_xpos + (long)G_xbase;
1235 	graph_ymin = 0L;
1236 	graph_ymax = maximal_ypos + (long)G_ybase;
1237 	gfocus_x    = gfx;
1238 	gfocus_y    = gfy;
1239 	sfocus_x    = (int)((long)(screen_xmax-screen_xmin)
1240 			* (gfocus_x-graph_xmin) / (graph_xmax-graph_xmin));
1241 	sfocus_y    = (int)((long)(screen_ymax-screen_ymin)
1242 			* (gfocus_y-graph_ymin) / (graph_ymax-graph_ymin));
1243 	if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
1244 	if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
1245 	if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
1246 	if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
1247 	if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
1248 	if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
1249 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1250 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1251 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1252 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1253 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1254 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1255 	V_xmin = 0L;
1256 	V_xmax = MAXLONG;
1257 	V_ymin = 0L;
1258 	V_ymax = MAXLONG;
1259 	calc_pscf_parameters();
1260 }
1261 
1262 
1263 /*  Change scaling
1264  *  --------------
1265  */
1266 
1267 #ifdef ANSI_C
change_pscf_scaling(void)1268 static void change_pscf_scaling(void)
1269 #else
1270 static void change_pscf_scaling()
1271 #endif
1272 {
1273 	debugmessage("change_pscf_scaling","");
1274 
1275 	calc_pscf_parameters();
1276 }
1277 
1278 
1279 /*  Change windowsize
1280  *  -----------------
1281  *  Returns 1, if a redraw is necessary.
1282  */
1283 
1284 #ifdef ANSI_C
change_pscf_winsize(int sxmin,int sxmax,int symin,int symax)1285 static int change_pscf_winsize(int sxmin, int sxmax, int symin, int symax)
1286 #else
1287 static int change_pscf_winsize(sxmin, sxmax, symin, symax)
1288 	int sxmin;
1289 	int sxmax;
1290 	int symin;
1291 	int symax;
1292 #endif
1293 {
1294 	int oldsxmin, oldsxmax, oldsymin, oldsymax;
1295 	int ret;
1296 
1297 	debugmessage("change_pscf_winsize","");
1298 
1299 	ret = 0;
1300 	oldsxmin = screen_xmin;
1301 	oldsxmax = screen_xmax;
1302 	oldsymin = screen_ymin;
1303 	oldsymax = screen_ymax;
1304 	screen_xmin = sxmin;
1305 	screen_xmax = sxmax;
1306 	screen_ymin = symin;
1307 	screen_ymax = symax;
1308 	ret += change_pscf_sfocus();
1309 	if (oldsxmin != screen_xmin) return(1);
1310 	if (oldsxmax != screen_xmax) return(1);
1311 	if (oldsymin != screen_ymin) return(1);
1312 	if (oldsymax != screen_ymax) return(1);
1313 	return(ret);
1314 }
1315 
1316 
1317 /*  Change screen focus
1318  *  -------------------
1319  *  Returns 1, if a redraw is necessary.
1320  */
1321 
1322 #ifdef ANSI_C
change_pscf_sfocus(void)1323 static int change_pscf_sfocus(void)
1324 #else
1325 static int change_pscf_sfocus()
1326 #endif
1327 {
1328 	int oldsfx, oldsfy;
1329 
1330 	debugmessage("change_pscf_sfocus","");
1331 
1332 	oldsfx = sfocus_x;
1333 	oldsfy = sfocus_y;
1334 	sfocus_x    = (int)((long)(screen_xmax-screen_xmin)
1335 			* (gfocus_x-graph_xmin) / (graph_xmax-graph_xmin));
1336 	sfocus_y    = (int)((long)(screen_ymax-screen_ymin)
1337 			* (gfocus_y-graph_ymin) / (graph_ymax-graph_ymin));
1338 	if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
1339 	if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
1340 	if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
1341 	if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
1342 	if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
1343 	if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
1344 	calc_pscf_parameters();
1345 	if (oldsfx != sfocus_x) return(1);
1346 	if (oldsfy != sfocus_y) return(1);
1347 	return(0);
1348 }
1349 
1350 
1351 /*  Change graph focus
1352  *  ------------------
1353  *  Returns 1, if a redraw is necessary.
1354  */
1355 
1356 #ifdef ANSI_C
change_pscf_gfocus(long gfx,long gfy)1357 static int change_pscf_gfocus(long gfx, long gfy)
1358 #else
1359 static int change_pscf_gfocus(gfx, gfy)
1360 	long gfx;
1361 	long gfy;
1362 #endif
1363 {
1364 	int ret;
1365 	long oldgfx, oldgfy;
1366 
1367 	debugmessage("change_pscf_gfocus","");
1368 
1369 	ret = 0;
1370 	oldgfx = gfocus_x;
1371 	oldgfy = gfocus_y;
1372 	gfocus_x    = gfx;
1373 	gfocus_y    = gfy;
1374 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1375 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1376 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1377 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1378 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1379 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1380 	ret += change_pscf_sfocus();
1381 	if (oldgfx != gfocus_x) return(1);
1382 	if (oldgfy != gfocus_y) return(1);
1383 	return(ret);
1384 }
1385 
1386 
1387 /*  Increment graph focus
1388  *  ---------------------
1389  *  Returns 1, if a redraw is necessary.
1390  */
1391 
1392 #ifdef ANSI_C
incr_pscf_gfocus(long dfx,long dfy)1393 static int incr_pscf_gfocus(long dfx, long dfy)
1394 #else
1395 static int incr_pscf_gfocus(dfx, dfy)
1396 	long dfx;
1397 	long dfy;
1398 #endif
1399 {
1400 	debugmessage("incr_pscf_sfocus","");
1401 
1402 	if ((dfx==0L) && (dfy==0L)) return(0);
1403 	gfocus_x    += dfx;
1404 	gfocus_y    += dfy;
1405 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1406 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1407 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1408 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1409 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1410 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1411 	(void)change_pscf_sfocus();
1412 	return(1);
1413 }
1414 
1415 
1416 /*  Translate a x,y-coordinate of the graph into a x,y-coordinate of the screen
1417  *  ---------------------------------------------------------------------------
1418  */
1419 
1420 #ifdef ANSI_C
pscf_g_to_s(long x,long y,int * resx,int * resy)1421 static void pscf_g_to_s(long x, long y, int *resx, int *resy)
1422 #else
1423 static void pscf_g_to_s(x, y, resx, resy)
1424 	long x, y;
1425 	int *resx, *resy;
1426 #endif
1427 {
1428 	float xdiff, ydiff, dist1, dist2, help;
1429 
1430 	xdiff = (float)(x - gfocus_x);
1431 	ydiff = (float)(y - gfocus_y);
1432 	dist1 = sqrt(xdiff*xdiff + ydiff*ydiff);
1433 
1434 	help = par_p * dist1 + 100.0;
1435 	if (help<=0.0) help = 0.1;
1436 	dist2 = (double)fe_scaling * dist1 / help;
1437 
1438 	*resx = sfocus_x + (int)(xdiff*dist2/dist1);
1439 	*resy = sfocus_y + (int)(ydiff*dist2/dist1);
1440 }
1441 
1442 
1443 
1444 /*  Translate a x,y-coordinate of the screen into a x,y-coordinate of the graph
1445  *  ---------------------------------------------------------------------------
1446  */
1447 
1448 #ifdef ANSI_C
pscf_s_to_g(int x,int y,long * resx,long * resy)1449 static void pscf_s_to_g(int x, int y, long *resx, long *resy)
1450 #else
1451 static void pscf_s_to_g(x, y, resx, resy)
1452 	int x, y;
1453 	long *resx, *resy;
1454 #endif
1455 {
1456 	float xdiff, ydiff, dist1, dist2, help;
1457 
1458 	xdiff = (float)(x - sfocus_x);
1459 	ydiff = (float)(y - sfocus_y);
1460 	dist2 = sqrt(xdiff*xdiff + ydiff*ydiff);
1461 
1462 	help = - par_p * dist2 + fe_scaling;
1463 	if (help<=0.0) help = 0.1;
1464 	dist1 = 100.0 * dist2 / help;
1465 
1466 	*resx = gfocus_x + (long)(xdiff*dist1/dist2);
1467 	*resy = gfocus_y + (long)(ydiff*dist1/dist2);
1468 }
1469 
1470 
1471 
1472 /*--------------------------------------------------------------------*/
1473 /* Polar fixed width continuous fisheye                               */
1474 /*--------------------------------------------------------------------*/
1475 
1476 /* A polar continuos fisheye with a fixed radius of visible range.
1477  * For the formula, see the self adaptable continuous fisheye.
1478  * Now, we fisheye focus is always at the middle of the screen
1479  * and the maximal distance to the focus in the graph is gfishdist.
1480  * In the formula, d_max is now gfishdist.
1481  *
1482  *  with  par2 = k * gfishdist - sd_max
1483  *  and   par1 = gfishdist * sd_max
1484  *
1485  * Implementation detail: we do not transfer straight lines into curves,
1486  * because this would need to much time. As result, the following properties
1487  * hold:
1488  *
1489  *    1) the fisheye preserve bendings
1490  *    2) the fisheye does not preserve crossings
1491  *    3) the fisheye does not preserve angles. However, it preserves
1492  *       angles of rays starting at the focus point, since it is a polar
1493  *       transformation.
1494  */
1495 
1496 
1497 
1498 /*  Calculation of the auxiliary parameters
1499  *  ---------------------------------------
1500  *  A new calculation of the auxiliary parameters is necessary if
1501  *    a) the scaling changes.
1502  *    b) the position of the focus in the graph changes.
1503  *    c) the position of the focus in the window chnages.
1504  *    d) the size of the window changes.
1505  */
1506 
1507 #ifdef ANSI_C
calc_fpscf_parameters(void)1508 static void calc_fpscf_parameters(void)
1509 #else
1510 static void calc_fpscf_parameters()
1511 #endif
1512 {
1513 	long s, t;
1514 
1515 	debugmessage("calc_fpscf_parameters","");
1516 
1517 	xhashmin = 0L;
1518 	xhashmax = -1L;
1519 	yhashmin = 0L;
1520 	yhashmax = -1L;
1521 
1522 	s = (long)(screen_xmax-sfocus_x);
1523 	t = gfishdist;
1524 
1525 	par_xrp1 = s*t;
1526 	par_xrp2 = fe_scaling*t - 100L*s;
1527 
1528 	if (par_xrp1==0L) par_xrp1 = 1L;
1529 	if (par_xrp2<=0L) par_xrp2 = 1L;
1530 	par_p = (double)par_xrp2 / (double)par_xrp1;
1531 
1532 }
1533 
1534 
1535 
1536 /*  Initialization of the fpscf_fisheye
1537  *  -----------------------------------
1538  */
1539 
1540 
1541 #ifdef ANSI_C
init_fpscf(int sxmin,int sxmax,int symin,int symax,long gfx,long gfy)1542 static void init_fpscf(int sxmin, int sxmax, int symin, int symax,
1543 		long gfx, long gfy)
1544 #else
1545 static void init_fpscf(sxmin, sxmax, symin, symax, gfx, gfy)
1546 	int sxmin;
1547 	int sxmax;
1548 	int symin;
1549 	int symax;
1550 	long gfx;
1551 	long gfy;
1552 #endif
1553 {
1554 	debugmessage("init_fpscf","");
1555 
1556 	if ((sxmin!=0) || (sxmax!=0) || (symin!=0) || (symax!=0)) {
1557 		screen_xmin = sxmin;
1558 		screen_xmax = sxmax;
1559 		screen_ymin = symin;
1560 		screen_ymax = symax;
1561 	}
1562 	graph_xmin = 0L;
1563 	graph_xmax = maximal_xpos + (long)G_xbase;
1564 	graph_ymin = 0L;
1565 	graph_ymax = maximal_ypos + (long)G_ybase;
1566 
1567         gfishdist = 2L * (long)(screen_xmax-screen_xmin);
1568         if (gfishdist<30L)  gfishdist = 30;
1569 
1570 	sfocus_x    = (screen_xmax+screen_xmin)/2;
1571         sfocus_y    = (screen_ymax+screen_ymin)/2;
1572 	gfocus_x    = gfx;
1573 	gfocus_y    = gfy;
1574 	if (sfocus_x >= screen_xmax) sfocus_x = screen_xmax-5;
1575 	if (sfocus_x <= screen_xmin) sfocus_x = screen_xmin+5;
1576 	if (screen_xmax == screen_xmin+5) sfocus_x = screen_xmin+2;
1577 	if (sfocus_y >= screen_ymax) sfocus_y = screen_ymax-5;
1578 	if (sfocus_y <= screen_ymin) sfocus_y = screen_ymin+5;
1579 	if (screen_ymax == screen_ymin+5) sfocus_y = screen_ymin+2;
1580 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1581 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1582 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1583 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1584 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1585 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1586 	V_xmin = 0L;
1587 	V_xmax = MAXLONG;
1588 	V_ymin = 0L;
1589 	V_ymax = MAXLONG;
1590 	calc_fpscf_parameters();
1591 }
1592 
1593 
1594 /*  Change scaling
1595  *  --------------
1596  */
1597 
1598 #ifdef ANSI_C
change_fpscf_scaling(void)1599 static void change_fpscf_scaling(void)
1600 #else
1601 static void change_fpscf_scaling()
1602 #endif
1603 {
1604 	debugmessage("change_fpscf_scaling","");
1605 
1606 	calc_fpscf_parameters();
1607 }
1608 
1609 
1610 /*  Change windowsize
1611  *  -----------------
1612  *  Returns 1, if a redraw is necessary.
1613  */
1614 
1615 #ifdef ANSI_C
change_fpscf_winsize(int sxmin,int sxmax,int symin,int symax)1616 static int change_fpscf_winsize(int sxmin, int sxmax, int symin, int symax)
1617 #else
1618 static int change_fpscf_winsize(sxmin, sxmax, symin, symax)
1619 	int sxmin;
1620 	int sxmax;
1621 	int symin;
1622 	int symax;
1623 #endif
1624 {
1625 	int oldsxmin, oldsxmax, oldsymin, oldsymax;
1626 
1627 	debugmessage("change_fpscf_winsize","");
1628 
1629 	oldsxmin = screen_xmin;
1630 	oldsxmax = screen_xmax;
1631 	oldsymin = screen_ymin;
1632 	oldsymax = screen_ymax;
1633 	screen_xmin = sxmin;
1634 	screen_xmax = sxmax;
1635 	screen_ymin = symin;
1636 	screen_ymax = symax;
1637 	calc_fpscf_parameters();
1638 	if (oldsxmin != screen_xmin) return(1);
1639 	if (oldsxmax != screen_xmax) return(1);
1640 	if (oldsymin != screen_ymin) return(1);
1641 	if (oldsymax != screen_ymax) return(1);
1642 	return(0);
1643 }
1644 
1645 
1646 /*  Change graph focus
1647  *  ------------------
1648  *  Returns 1, if a redraw is necessary.
1649  */
1650 
1651 #ifdef ANSI_C
change_fpscf_gfocus(long gfx,long gfy)1652 static int change_fpscf_gfocus(long gfx, long gfy)
1653 #else
1654 static int change_fpscf_gfocus(gfx, gfy)
1655 	long gfx;
1656 	long gfy;
1657 #endif
1658 {
1659 	long oldgfx, oldgfy;
1660 
1661 	debugmessage("change_fpscf_gfocus","");
1662 
1663 	oldgfx = gfocus_x;
1664 	oldgfy = gfocus_y;
1665 	gfocus_x    = gfx;
1666 	gfocus_y    = gfy;
1667 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1668 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1669 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1670 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1671 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1672 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1673 	calc_fpscf_parameters();
1674 	if (oldgfx != gfocus_x) return(1);
1675 	if (oldgfy != gfocus_y) return(1);
1676 	return(0);
1677 }
1678 
1679 
1680 /*  Increment graph focus
1681  *  ---------------------
1682  *  Returns 1, if a redraw is necessary.
1683  */
1684 
1685 #ifdef ANSI_C
incr_fpscf_gfocus(long dfx,long dfy)1686 static int incr_fpscf_gfocus(long dfx, long dfy)
1687 #else
1688 static int incr_fpscf_gfocus(dfx, dfy)
1689 	long dfx;
1690 	long dfy;
1691 #endif
1692 {
1693 	debugmessage("incr_fpscf_sfocus","");
1694 
1695 	if ((dfx==0L) && (dfy==0L)) return(0);
1696 	gfocus_x    += dfx;
1697 	gfocus_y    += dfy;
1698 	if (gfocus_x >= graph_xmax) gfocus_x = graph_xmax-5L;
1699 	if (gfocus_x <= graph_xmin) gfocus_x = graph_xmin+5L;
1700 	if (graph_xmax == graph_xmin+5L) gfocus_x = graph_xmin+2L;
1701 	if (gfocus_y >= graph_ymax) gfocus_y = graph_ymax-5L;
1702 	if (gfocus_y <= graph_ymin) gfocus_y = graph_ymin+5L;
1703 	if (graph_ymax == graph_ymin+5L) gfocus_y = graph_ymin+2L;
1704 	calc_fpscf_parameters(); /* not necessary ? */
1705 	return(1);
1706 }
1707 
1708 
1709 /* Change the fisheye width
1710  * ------------------------
1711  * Returns 1, if a redraw is necessary.
1712  */
1713 
1714 #ifdef ANSI_C
set_fpscf_gfishdist(long gd)1715 static int set_fpscf_gfishdist(long gd)
1716 #else
1717 static int set_fpscf_gfishdist(gd)
1718 long gd;
1719 #endif
1720 {
1721 	int ret;
1722 
1723 	debugmessage("set_fpscf_gfishdist","");
1724 
1725 	if (gd<30L) return(0);
1726 
1727 	ret = (gfishdist != gd);
1728 	gfishdist = gd;
1729 	calc_fpscf_parameters();
1730 	return(ret);
1731 }
1732 
1733 /*--------------------------------------------------------------------*/
1734 /* Entry-Points for the different fisheyes                            */
1735 /*--------------------------------------------------------------------*/
1736 
1737 /*  Initialization of the fisheye
1738  *  -----------------------------
1739  */
1740 
1741 
1742 #ifdef ANSI_C
init_fe(int sxmin,int sxmax,int symin,int symax,int sfx,int sfy)1743 void init_fe(int sxmin, int sxmax, int symin, int symax,
1744 		int sfx, int sfy)
1745 #else
1746 void init_fe(sxmin, sxmax, symin, symax, sfx, sfy)
1747 	int sxmin;
1748 	int sxmax;
1749 	int symin;
1750 	int symax;
1751 	int sfx;
1752 	int sfy;
1753 #endif
1754 {
1755 	long gfx, gfy;
1756 
1757 	debugmessage("init_fe","");
1758 
1759 	fe_scaling = (long)(G_stretch * 100 / G_shrink);
1760 	if (fe_scaling<=0L)    fe_scaling = 1L;
1761 	if (fe_scaling>=5000L) fe_scaling = 5000L;
1762 	gfx = V_xmin + (long)(sxmax-sxmin)/2L;
1763 	gfy = V_ymin + (long)(symax-symin)/2L;
1764 
1765 	if (!xcoord_hash)
1766 		xcoord_hash = (short *)malloc(COORD_HASHSIZE*sizeof(short));
1767 	if (!ycoord_hash)
1768 		ycoord_hash = (short *)malloc(COORD_HASHSIZE*sizeof(short));
1769 
1770 	switch (fisheye_view) {
1771 	case CSCF_VIEW:
1772 			init_cscf(sxmin,sxmax,symin,symax,gfx,gfy);
1773 			G_stretch = G_shrink = 1;
1774 			V_xmin = 0L;
1775 			V_xmax = MAXLONG;
1776 			return;
1777 	case FCSCF_VIEW:
1778 			init_fcscf(sxmin,sxmax,symin,symax,gfx,gfy);
1779 			G_stretch = G_shrink = 1;
1780 			V_xmin = 0L;
1781 			V_xmax = MAXLONG;
1782 			return;
1783 	case PSCF_VIEW:
1784 			init_pscf(sxmin,sxmax,symin,symax,gfx,gfy);
1785 			G_stretch = G_shrink = 1;
1786 			V_xmin = 0L;
1787 			V_xmax = MAXLONG;
1788 			return;
1789 	case FPSCF_VIEW:
1790 			init_fpscf(sxmin,sxmax,symin,symax,gfx,gfy);
1791 			G_stretch = G_shrink = 1;
1792 			V_xmin = 0L;
1793 			V_xmax = MAXLONG;
1794 			return;
1795 	}
1796 	fisheye_view = 0;
1797 
1798 }
1799 
1800 /* Exit a fisheye view
1801  * -------------------
1802  */
1803 
1804 #ifdef ANSI_C
exit_fe(void)1805 void exit_fe(void)
1806 #else
1807 void exit_fe()
1808 #endif
1809 {
1810 	debugmessage("exit_fe","");
1811 
1812 	if (fisheye_view==0) return;
1813 	G_shrink = 100;
1814 	G_stretch = fe_scaling;
1815 	V_xmin = gfocus_x - (long)(screen_xmax-screen_xmin)/2;
1816 	V_ymin = gfocus_y - (long)(screen_ymax-screen_ymin)/2;
1817 	V_xmax = V_xmin + (long)G_xmax;
1818 	V_ymax = V_ymin + (long)(G_ymax + COFFSET);
1819 	fisheye_view = 0;
1820 }
1821 
1822 
1823 
1824 /*  Translate a x,y-coord. of the graph into a x,y-coord. of the screen
1825  *  -------------------------------------------------------------------
1826  */
1827 
1828 
1829 #ifdef ANSI_C
fe_g_to_s(long x,long y,int * resx,int * resy)1830 void fe_g_to_s(long x, long y, int *resx, int *resy)
1831 #else
1832 void fe_g_to_s(x, y, resx, resy)
1833 	long x, y;
1834 	int *resx, *resy;
1835 #endif
1836 {
1837 	int have_x = 0;
1838 
1839 	if ((xcoord_hash) && (x>=xhashmin) && (x<=xhashmax)) {
1840 			*resx = (int)xcoord_hash[x];
1841 			have_x = 1;
1842 	}
1843 	if ((ycoord_hash) && (y>=yhashmin) && (y<=yhashmax)) {
1844 			*resy = (int)ycoord_hash[y];
1845 			if (have_x) return;
1846 	}
1847 
1848 	switch (fisheye_view) {
1849 	case FCSCF_VIEW:
1850 	case CSCF_VIEW:  cscf_g_to_s(x,y,resx,resy); return;
1851 	case FPSCF_VIEW:
1852 	case PSCF_VIEW:  pscf_g_to_s(x,y,resx,resy); return;
1853 	}
1854 	*resx = (int)x;
1855 	*resy = (int)y;
1856 }
1857 
1858 
1859 /*  Translate a x,y-coord. of the screen into a x,y-coord. of the graph
1860  *  -------------------------------------------------------------------
1861  */
1862 
1863 #ifdef ANSI_C
fe_s_to_g(int x,int y,long * resx,long * resy)1864 void fe_s_to_g(int x, int y, long *resx, long *resy)
1865 #else
1866 void fe_s_to_g(x, y, resx, resy)
1867 	int x, y;
1868 	long *resx, *resy;
1869 #endif
1870 {
1871 	switch (fisheye_view) {
1872 	case FCSCF_VIEW:
1873 	case CSCF_VIEW: cscf_s_to_g(x,y,resx,resy); return;
1874 	case FPSCF_VIEW:
1875 	case PSCF_VIEW: pscf_s_to_g(x,y,resx,resy); return;
1876 	}
1877 	*resx = (long)x;
1878 	*resy = (long)y;
1879 }
1880 
1881 
1882 /*  Set scaling
1883  *  -----------
1884  */
1885 
1886 #ifdef ANSI_C
set_fe_scaling(int stretch,int shrink)1887 void set_fe_scaling(int stretch, int shrink)
1888 #else
1889 void set_fe_scaling(stretch, shrink)
1890 	int stretch, shrink;
1891 #endif
1892 {
1893 	long xx, yy;
1894 
1895 	debugmessage("set_fe_scaling","");
1896 
1897 	if (shrink==0) fe_scaling = 100L;
1898 	else fe_scaling = (long)(stretch * 100 / shrink);
1899 	if (fe_scaling<=0L)    fe_scaling = 1L;
1900 	if (fe_scaling>=5000L) fe_scaling = 5000L;
1901 
1902 	switch (fisheye_view) {
1903 	case CSCF_VIEW:  change_cscf_scaling();  return;
1904 	case FCSCF_VIEW: change_fcscf_scaling(); return;
1905 	case PSCF_VIEW:  change_pscf_scaling();  return;
1906 	case FPSCF_VIEW: change_fpscf_scaling();  return;
1907 	}
1908 	xx = V_xmin * (long)G_shrink/(long)G_stretch;
1909         yy = V_ymin * (long)G_shrink/(long)G_stretch;
1910 	G_stretch = stretch;
1911 	G_shrink  = shrink;
1912 	normalize_scaling();
1913         V_xmin = xx * (long)G_stretch/(long)G_shrink;
1914         V_ymin = yy * (long)G_stretch/(long)G_shrink;
1915         V_xmax = V_xmin+(long)G_xmax;
1916         V_ymax = V_ymin+(long)(G_ymax+COFFSET);
1917 }
1918 
1919 
1920 /*  Change scaling relatively
1921  *  -------------------------
1922  */
1923 
1924 #ifdef ANSI_C
change_fe_scaling(int stretch,int shrink)1925 void change_fe_scaling(int stretch, int shrink)
1926 #else
1927 void change_fe_scaling(stretch, shrink)
1928 	int stretch, shrink;
1929 #endif
1930 {
1931 	long xx, yy;
1932 
1933 	debugmessage("change_fe_scaling","");
1934 
1935 	if (shrink==0) fe_scaling = 100L;
1936 	else fe_scaling = fe_scaling * (long)stretch / (long)shrink;
1937 	if (fe_scaling<=0L)    fe_scaling = 1L;
1938 	if (fe_scaling>=5000L) fe_scaling = 5000L;
1939 	switch (fisheye_view) {
1940 	case CSCF_VIEW:  change_cscf_scaling();  return;
1941 	case FCSCF_VIEW: change_fcscf_scaling(); return;
1942 	case PSCF_VIEW:  change_pscf_scaling();  return;
1943 	case FPSCF_VIEW: change_fpscf_scaling();  return;
1944 	}
1945 
1946 	xx = V_xmin * (long)G_shrink/(long)G_stretch;
1947         yy = V_ymin * (long)G_shrink/(long)G_stretch;
1948 	G_stretch = G_stretch * stretch;
1949 	G_shrink  = G_shrink  * shrink;
1950 	normalize_scaling();
1951         V_xmin = xx * (long)G_stretch/(long)G_shrink;
1952         V_ymin = yy * (long)G_stretch/(long)G_shrink;
1953         V_xmax = V_xmin+(long)G_xmax;
1954         V_ymax = V_ymin+(long)(G_ymax+COFFSET);
1955 }
1956 
1957 
1958 
1959 /*  Set graph focus to the normal position
1960  *  --------------------------------------
1961  *  Returns 1, if a redraw is necessary.
1962  */
1963 
1964 #ifdef ANSI_C
normal_fe_focus(void)1965 int normal_fe_focus(void)
1966 #else
1967 int normal_fe_focus()
1968 #endif
1969 {
1970 	int ret;
1971 	long dfx, dfy;
1972 
1973 	debugmessage("normal_fe_focus","");
1974 
1975 	dfx = (graph_xmin + graph_xmax)/2L;
1976 	dfy = (graph_ymin + graph_ymax)/2L;
1977 	switch (fisheye_view) {
1978 	case CSCF_VIEW:  return(change_cscf_gfocus(dfx, dfy));
1979 	case FCSCF_VIEW: return(change_fcscf_gfocus(dfx, dfy));
1980 	case PSCF_VIEW:  return(change_pscf_gfocus(dfx, dfy));
1981 	case FPSCF_VIEW: return(change_fpscf_gfocus(dfx, dfy));
1982 	}
1983 	ret = 0;
1984 	if (V_xmin!=0L) ret = 1;
1985 	if (V_ymin!=0L) ret = 1;
1986         V_xmin = 0L;
1987         V_ymin = 0L;
1988         V_xmax = V_xmin+(long)G_xmax;
1989         V_ymax = V_ymin+(long)(G_ymax+COFFSET);
1990 	return(ret);
1991 }
1992 
1993 
1994 /*  Set graph focus x-coordinate
1995  *  ----------------------------
1996  *  Returns 1, if a redraw is necessary.
1997  */
1998 
1999 #ifdef ANSI_C
set_fe_xfocus(long fx)2000 int set_fe_xfocus(long fx)
2001 #else
2002 int set_fe_xfocus(fx)
2003 	long fx;
2004 #endif
2005 {
2006 	int ret;
2007 
2008 	debugmessage("set_fe_xfocus","");
2009 
2010 	switch (fisheye_view) {
2011 	case CSCF_VIEW:  return(change_cscf_gfocus(fx, gfocus_y));
2012 	case FCSCF_VIEW: return(change_fcscf_gfocus(fx, gfocus_y));
2013 	case PSCF_VIEW:  return(change_pscf_gfocus(fx, gfocus_y));
2014 	case FPSCF_VIEW: return(change_fpscf_gfocus(fx, gfocus_y));
2015 	}
2016 	ret = 0;
2017 	if (V_xmin!=fx) ret = 1;
2018         V_xmin = fx;
2019         V_xmax = V_xmin+(long)G_xmax;
2020 	return(ret);
2021 }
2022 
2023 
2024 /*  Set graph focus y-coordinate
2025  *  ----------------------------
2026  *  Returns 1, if a redraw is necessary.
2027  */
2028 
2029 #ifdef ANSI_C
set_fe_yfocus(long fy)2030 int set_fe_yfocus(long fy)
2031 #else
2032 int set_fe_yfocus(fy)
2033 	long fy;
2034 #endif
2035 {
2036 	int ret;
2037 
2038 	debugmessage("set_fe_yfocus","");
2039 
2040 	switch (fisheye_view) {
2041 	case CSCF_VIEW:  return(change_cscf_gfocus(gfocus_x,fy));
2042 	case FCSCF_VIEW: return(change_fcscf_gfocus(gfocus_x,fy));
2043 	case PSCF_VIEW:  return(change_pscf_gfocus(gfocus_x,fy));
2044 	case FPSCF_VIEW: return(change_fpscf_gfocus(gfocus_x,fy));
2045 	}
2046 	ret = 0;
2047 	if (V_ymin!=fy) ret = 1;
2048         V_ymin = fy;
2049         V_ymax = V_ymin+(long)(G_ymax+COFFSET);
2050 	return(ret);
2051 }
2052 
2053 
2054 
2055 /*  Increment graph focus
2056  *  ---------------------
2057  *  Returns 1, if a redraw is necessary.
2058  */
2059 
2060 #ifdef ANSI_C
incr_fe_focus(long dfx,long dfy)2061 int incr_fe_focus(long dfx, long dfy)
2062 #else
2063 int incr_fe_focus(dfx, dfy)
2064 	long dfx, dfy;
2065 #endif
2066 {
2067 	debugmessage("incr_fe_focus","");
2068 
2069 	switch (fisheye_view) {
2070 	case CSCF_VIEW:  return(incr_cscf_gfocus(dfx, dfy));
2071 	case FCSCF_VIEW: return(incr_fcscf_gfocus(dfx, dfy));
2072 	case PSCF_VIEW:  return(incr_pscf_gfocus(dfx, dfy));
2073 	case FPSCF_VIEW: return(incr_fpscf_gfocus(dfx, dfy));
2074 	}
2075         V_xmin += dfx;
2076         V_ymin += dfy;
2077         V_xmax = V_xmin+(long)G_xmax;
2078         V_ymax = V_ymin+(long)(G_ymax+COFFSET);
2079 	if ((dfx==0L) && (dfy==0L)) return(0);
2080 	return(1);
2081 }
2082 
2083 
2084 
2085 /*  Change windowsize
2086  *  -----------------
2087  *  Returns 1, if a redraw is necessary.
2088  */
2089 
2090 #ifdef ANSI_C
change_fe_winsize(int sxmin,int sxmax,int symin,int symax)2091 int change_fe_winsize(int sxmin, int sxmax, int symin, int symax)
2092 #else
2093 int change_fe_winsize(sxmin, sxmax, symin, symax)
2094 	int sxmin;
2095 	int sxmax;
2096 	int symin;
2097 	int symax;
2098 #endif
2099 {
2100 	switch (fisheye_view) {
2101 	case CSCF_VIEW:  return(change_cscf_winsize(sxmin,sxmax,symin,symax));
2102 	case FCSCF_VIEW: return(change_fcscf_winsize(sxmin,sxmax,symin,symax));
2103 	case PSCF_VIEW:  return(change_pscf_winsize(sxmin,sxmax,symin,symax));
2104 	case FPSCF_VIEW: return(change_fpscf_winsize(sxmin,sxmax,symin,symax));
2105 	}
2106 	return(0);
2107 }
2108 
2109 
2110 /* Change the fisheye width
2111  * ------------------------
2112  * Returns 1, if a redraw is necessary.
2113  */
2114 
2115 #ifdef ANSI_C
set_gfishdist(long gd)2116 int set_gfishdist(long gd)
2117 #else
2118 int set_gfishdist(gd)
2119 long gd;
2120 #endif
2121 {
2122 	switch (fisheye_view) {
2123 	case FCSCF_VIEW: return(set_fcscf_gfishdist(gd));
2124 	case FPSCF_VIEW: return(set_fpscf_gfishdist(gd));
2125 	}
2126 	return(0);
2127 }
2128 
2129 
2130 /*--------------------------------------------------------------------*/
2131 /*  Normalize G_shrink and G_stretch                                  */
2132 /*--------------------------------------------------------------------*/
2133 
2134 /* This is done to minimize rounding errors if to often
2135  * the scaling is changed.
2136  */
2137 
2138 #ifdef ANSI_C
normalize_scaling(void)2139 static void normalize_scaling(void)
2140 #else
2141 static void normalize_scaling()
2142 #endif
2143 {
2144 	if (G_shrink<0) G_shrink   *= -1;
2145 	if (G_stretch<0) G_stretch *= -1;
2146 	if (G_shrink==G_stretch) G_shrink = G_stretch = 1;
2147 	if (G_shrink ==0) G_shrink=1;
2148 	if (G_stretch==0) G_stretch=1;
2149 	if (G_stretch > G_shrink) {
2150 		if (G_shrink * 5000 < G_stretch) {
2151 			G_shrink = 1;
2152 			G_stretch = 5000;
2153 		}
2154 		G_stretch = G_stretch * 60 / G_shrink;
2155 		G_shrink  = 60;
2156 	}
2157 	if (G_stretch < G_shrink) {
2158 		if (G_shrink > G_stretch * 5000) {
2159 			G_shrink =  5000;
2160 			G_stretch = 1;
2161 		}
2162 		G_shrink  = G_shrink * 60 / G_stretch;
2163 		G_stretch = 60;
2164 	}
2165 	while ((G_shrink%2==0) && (G_stretch%2==0)) {
2166 		G_shrink   = G_shrink/2;
2167 		G_stretch  = G_stretch/2;
2168 	}
2169 	while ((G_shrink%3==0) && (G_stretch%3==0)) {
2170 		G_shrink   = G_shrink/3;
2171 		G_stretch  = G_stretch/3;
2172 	}
2173 	while ((G_shrink%5==0) && (G_stretch%5==0)) {
2174 		G_shrink   = G_shrink/5;
2175 		G_stretch  = G_stretch/5;
2176 	}
2177 	while ((G_shrink%7==0) && (G_stretch%7==0)) {
2178 		G_shrink   = G_shrink/7;
2179 		G_stretch  = G_stretch/7;
2180 	}
2181 	if (G_shrink ==0) G_shrink=1;
2182 	if (G_stretch==0) G_stretch=1;
2183 }
2184 
2185 
2186 /*--------------------------------------------------------------------*/
2187 /*  Normalize par_xrp1, ... par_yup2                                  */
2188 /*--------------------------------------------------------------------*/
2189 
2190 /* This is done to minimize rounding errors if the fisheye comes
2191  * too extreme or to near to the normal view.
2192  */
2193 
2194 #ifdef ANSI_C
normalize_fe_parameters(void)2195 static void normalize_fe_parameters(void)
2196 #else
2197 static void normalize_fe_parameters()
2198 #endif
2199 {
2200 	double h;
2201 	long s;
2202 
2203 	assert((par_xrp1>0L));
2204 	if (par_xrp2 < 0L) s = -1L; else s = 1L;
2205 	par_xrp2 = par_xrp2 * s;
2206 	if (par_xrp1 > par_xrp2) {
2207 		h = (double)par_xrp1/(double)par_xrp2;
2208 		if (h<10.0) {
2209 			par_xrp1 = (long)(h*100+0.5);
2210 			par_xrp2 = s * 100L;
2211 		}
2212 		else if (h<100.0) {
2213 			par_xrp1 = (long)(h*10+0.5);
2214 			par_xrp2 = s * 10L;
2215 		}
2216 		else if (h>1000.0) {
2217 			par_xrp1 = 1000L;
2218 			par_xrp2 = s;
2219 		}
2220 		else {  par_xrp1 = (long)(h+0.5);
2221 			par_xrp2 = s;
2222 		}
2223 	}
2224 	else {
2225 		h = (double)par_xrp2/(double)par_xrp1;
2226 		if (h<10.0) {
2227 			par_xrp2 = s * (long)(h*100+0.5);
2228 			par_xrp1 = 100L;
2229 		}
2230 		else if (h<100.0) {
2231 			par_xrp2 = s * (long)(h*10+0.5);
2232 			par_xrp1 = 10L;
2233 		}
2234 		else if (h>1000.0) {
2235 			par_xrp2 = s*1000;
2236 			par_xrp1 = 1L;
2237 		}
2238 		else {  par_xrp2 = s * (long)(h+0.5);
2239 			par_xrp1 = 1L;
2240 		}
2241 	}
2242 	assert((par_xlp1>0L));
2243 	if (par_xlp2 < 0L) s = -1L; else s = 1L;
2244 	par_xlp2 = par_xlp2 * s;
2245 	if (par_xlp1 > par_xlp2) {
2246 		h = (double)par_xlp1/(double)par_xlp2;
2247 		if (h<10.0) {
2248 			par_xlp1 = (long)(h*100+0.5);
2249 			par_xlp2 = s * 100L;
2250 		}
2251 		else if (h<100.0) {
2252 			par_xlp1 = (long)(h*10+0.5);
2253 			par_xlp2 = s * 10L;
2254 		}
2255 		else if (h>1000.0) {
2256 			par_xlp1 = 1000;
2257 			par_xlp2 = s;
2258 		}
2259 		else {  par_xlp1 = (long)(h+0.5);
2260 			par_xlp2 = s;
2261 		}
2262 	}
2263 	else {
2264 		h = (double)par_xlp2/(double)par_xlp1;
2265 		if (h<10.0) {
2266 			par_xlp2 = s * (long)(h*100+0.5);
2267 			par_xlp1 = 100L;
2268 		}
2269 		else if (h<100.0) {
2270 			par_xlp2 = s * (long)(h*10+0.5);
2271 			par_xlp1 = 10L;
2272 		}
2273 		else if (h>1000.0) {
2274 			par_xlp2 = s * 1000;
2275 			par_xlp1 = 1L;
2276 		}
2277 		else {  par_xlp2 = s * (long)(h+0.5);
2278 			par_xlp1 = 1L;
2279 		}
2280 	}
2281 	assert((par_ylp1>0L));
2282 	if (par_ylp2 < 0L) s = -1L; else s = 1L;
2283 	par_ylp2 = par_ylp2 * s;
2284 	if (par_ylp1 > par_ylp2) {
2285 		h = (double)par_ylp1/(double)par_ylp2;
2286 		if (h<10.0) {
2287 			par_ylp1 = (long)(h*100+0.5);
2288 			par_ylp2 = s * 100L;
2289 		}
2290 		else if (h<100.0) {
2291 			par_ylp1 = (long)(h*10+0.5);
2292 			par_ylp2 = s * 10L;
2293 		}
2294 		else if (h>1000.0) {
2295 			par_ylp1 = 1000;
2296 			par_ylp2 = s;
2297 		}
2298 		else {  par_ylp1 = (long)(h+0.5);
2299 			par_ylp2 = s;
2300 		}
2301 	}
2302 	else {
2303 		h = (double)par_ylp2/(double)par_ylp1;
2304 		if (h<10.0) {
2305 			par_ylp2 = s * (long)(h*100+0.5);
2306 			par_ylp1 = 100L;
2307 		}
2308 		else if (h<100.0) {
2309 			par_ylp2 = s * (long)(h*10+0.5);
2310 			par_ylp1 = 10L;
2311 		}
2312 		else if (h>1000.0) {
2313 			par_ylp2 = s * 1000;
2314 			par_ylp1 = 1L;
2315 		}
2316 		else {  par_ylp2 = s * (long)(h+0.5);
2317 			par_ylp1 = 1L;
2318 		}
2319 	}
2320 	assert((par_yup1>0L));
2321 	if (par_yup2 < 0L) s = -1L; else s = 1L;
2322 	par_yup2 = par_yup2 * s;
2323 	if (par_yup1 > par_yup2) {
2324 		h = (double)par_yup1/(double)par_yup2;
2325 		if (h<10.0) {
2326 			par_yup1 = (long)(h*100+0.5);
2327 			par_yup2 = s * 100L;
2328 		}
2329 		else if (h<100.0) {
2330 			par_yup1 = (long)(h*10+0.5);
2331 			par_yup2 = s * 10L;
2332 		}
2333 		else if (h>1000.0) {
2334 			par_yup1 = 1000;
2335 			par_yup2 = s;
2336 		}
2337 		else {  par_yup1 = (long)(h+0.5);
2338 			par_yup2 = s;
2339 		}
2340 	}
2341 	else {
2342 		h = (double)par_yup2/(double)par_yup1;
2343 		if (h<10.0) {
2344 			par_yup2 = s * (long)(h*100+0.5);
2345 			par_yup1 = 100L;
2346 		}
2347 		else if (h<100.0) {
2348 			par_yup2 = s * (long)(h*10+0.5);
2349 			par_yup1 = 10L;
2350 		}
2351 		else if (h>1000.0) {
2352 			par_yup2 = s * 1000;
2353 			par_yup1 = 1L;
2354 		}
2355 		else {  par_yup2 = s * (long)(h+0.5);
2356 			par_yup1 = 1L;
2357 		}
2358 	}
2359 }
2360 
2361