1 /* Copyright (C) 1992-1998 The Geometry Center
2  * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3  *
4  * This file is part of Geomview.
5  *
6  * Geomview is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published
8  * by the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * Geomview is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Geomview; see the file COPYING.  If not, write
18  * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
19  * USA, or visit http://www.gnu.org.
20  */
21 
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25 
26 #if 0
27 static char copyright[] = "Copyright (C) 1992-1998 The Geometry Center\n\
28 Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips";
29 #endif
30 
31 
32 /* Authors: Stuart Levy, Tamara Munzner, Mark Phillips,
33    Celeste Fowler */
34 
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <ctype.h>
40 #include <stdlib.h>
41 #include "lisp.h"
42 #include "lang.h"
43 #include "drawer.h"
44 #include "transform.h"
45 #include "ui.h"
46 #include "motion.h"
47 #include "event.h"
48 #include "comm.h"
49 
50 
51 char *shades[5] = {
52 	"[0as] Constant",	/* APF_CONSTANT */
53 	"[1as] Flat",		/* APF_FLAT */
54 	"[2as] Smooth",		/* APF_SMOOTH */
55 	"[3as] CSmooth",	/* APF_CSMOOTH */
56 	"[4as] VCflat",	        /* APF_VCFLAT */
57 };
58 
59 char *translucencies[3] = {
60   "[0mt] BSP-Tree Alpha Blending",
61   "[1mt] Screen Door",
62   "[2mt] Simple Alpha Blending"
63 };
64 
65 char *norm[4] = {
66 	"[0N] None",		/* NONE */
67 	"[1N] Individual",	/* EACH */
68 	"[2N] Sequence",	/* ALL  */
69 	"[3N] Keep",		/* KEEP */
70 };
71 
72 char *proj[2] = {
73 	"[0vp]  Orthographic",	/* ORTHOGRAPHIC */
74 	"[1vp]  Perspective",	/* PERSPECTIVE */
75 };
76 
77 char *spc[3] = {
78 	"[me] Euclidean",	/* EUCLIDEAN */
79 	"[mh] Hyperbolic",	/* HYPERBOLIC */
80 	"[ms] Spherical",	/* SPHERICAL */
81 };
82 
83 char *mdl[3] = {
84 	"[mv] Virtual",		/* VIRTUAL */
85 	"[mp] Projective",	/* PROJECTIVE */
86 	"[mc] Conformal", 	/* CONFORMALBALL */
87 };
88 
89 
90 char OBJROTATE[]	=	"[r] Rotate";
91 char OBJTRANSLATE[]	=	"[t] Translate";
92 char OBJZOOM[]		=	"[z] Cam Zoom";
93 char OBJSCALE[]		=	"[s] Geom Scale";
94 char OBJFLY[]		=	"[f] Cam Fly";
95 char OBJORBIT[]		=	"[o] Cam Orbit";
96 char LIGHTEDIT[] 	=	"[le] Edit Lights";
97 
98 /* in ui.c */
99 
cui_init()100 void cui_init()
101 {
102 
103   uistate.targetid = WORLDGEOM;
104   uistate.centerid = TARGETID;
105   uistate.bbox_center = 0;
106   uistate.targetgeom = 0; /* World geom is index 0 */
107   uistate.targetcam = INDEXOF(FOCUSID);
108   uistate.cam_wm_focus = 0; /* bad idea */
109   uistate.mode_count = 0;
110   uistate.emod_dir = NULL;
111   uistate.apoverride = ~0;	/* Enable override by default */
112   uistate.inertia = 1;		/* Enable inertia by default */
113   uistate.pick_invisible = 1;	/* Pick invisible as well as visible objects? */
114 
115   /*
116    * The order of these calls must be the same as the declared integers
117    * in ui.h!!
118    */
119   ui_install_mode(OBJROTATE,	minterp_rotate,		T_NONE);
120   ui_install_mode(OBJZOOM,	minterp_zoom, 		T_CAM);
121   ui_install_mode(OBJTRANSLATE,	minterp_translate,	T_NONE);
122   ui_install_mode(OBJFLY,	minterp_fly,		T_CAM);
123   ui_install_mode(OBJORBIT,	minterp_orbit,		T_CAM);
124   ui_install_mode(OBJSCALE,	minterp_scale, 		T_GEOM);
125   VVINIT(uistate.emod, emodule, 10);
126   vvzero(&uistate.emod);
127   uistate.savewhat = NOID;
128   uistate.cursor_still = UI_CURSOR_STILL;
129   uistate.cursor_twitch = UI_CURSOR_TWITCH;
130   uistate.longwhile = 2.5;		/* Max credible inter-redraw interval */
131   uistate.backface = 0;
132   return;
133 }
134 
ui_reinstall_mode(char * name,PFI proc,int type,int index)135 void ui_reinstall_mode(char *name, PFI proc, int type, int index)
136 {
137   uistate.modenames[index] = name;
138   uistate.modes[index] = proc;
139   uistate.modetype[index] = type;
140 }
141 
ui_install_mode(char * name,PFI proc,int type)142 void ui_install_mode(char *name, PFI proc, int type)
143 {
144   if(uistate.mode_count >= MAXMODES) {
145     OOGLError(1, "Motion-mode table full (max %d entries)", MAXMODES);
146     uistate.mode_count = MAXMODES-1;
147   }
148   uistate.modenames[uistate.mode_count] = name;
149   uistate.modes[uistate.mode_count] = proc;
150   uistate.modetype[uistate.mode_count] = type;
151   ++uistate.mode_count;
152 
153 D1PRINT(("ui_install_mode: name=%s, proc=%x\n", name, proc));
154 
155 }
156 
ui_uninstall_mode(char * name)157 void ui_uninstall_mode(char *name)
158 {
159   int i = ui_mode_index(name);
160 
161   if (i<0) return;
162   --uistate.mode_count;
163   while (i<uistate.mode_count) {
164     uistate.modenames[i] = uistate.modenames[i+1];
165     uistate.modes[i] = uistate.modes[i+1];
166     uistate.modetype[i] = uistate.modetype[i+1];
167     i++;
168   }
169 }
170 
171 /*
172  * Match names
173  */
ui_mode_index(char * name)174 int ui_mode_index(char *name)
175 {
176   int i;
177 
178   for (i=0; i<uistate.mode_count; ++i) {
179     if(!strcasecmp(name, uistate.modenames[i]))
180 	return i;
181   }
182   OOGLError(0, "ui_mode_index: unknown mode \"%s\"", name);
183   return 0;
184 }
185 
ui_emodule_uninstall(int k)186 void ui_emodule_uninstall(int k)
187 {
188   emodule *em;
189   int i;
190   if(k < 0 || k >= VVCOUNT(uistate.emod))
191     return;
192   em = &VVEC(uistate.emod, emodule)[k];
193   for(i = k+1; i < VVCOUNT(uistate.emod); i++, em++)
194     *em = *(em+1);
195   VVCOUNT(uistate.emod)--;
196   uistate.emod_changed = k+1;
197 }
198 
199 emodule *
ui_emodule_install(int before,char * ename,PFI func)200 ui_emodule_install(int before, char *ename, PFI func)
201 {
202   int i,k;
203   emodule *em, *emp;
204 
205   if((k = ui_emodule_index(ename,NULL)) >= 0)
206     ui_emodule_uninstall(k);
207   k = VVCOUNT(uistate.emod)++;
208   vvneeds(&uistate.emod, VVCOUNT(uistate.emod));
209   if(before > k) before = k; else if(before < 0) before = 0;
210 
211   /* Shift the part of emodule table below the insertion point down
212      one unit.  Don't use bcopy() for this because it does not
213      correctly handle overlapping src and dst.
214      mbp Wed Sep  9 19:07:39 1992 */
215   em = VVEC(uistate.emod, emodule);
216   for (i=VVCOUNT(uistate.emod)-1, emp = &em[i]; i>before; i--, emp--)
217     *emp = *(emp-1);
218 
219   em = &VVEC(uistate.emod, emodule)[before];
220   em->name = strdup(ename);
221   em->func = (PFV)func;
222   em->dir =  uistate.emod_dir;
223   /* Other emodule fields zeroed */
224   uistate.emod_changed = before+1;
225   return em;
226 }
227 
228 LDEFINE(emodule_clear, LVOID,
229 	"(emodule-clear)\n\
230 	Clears the geomview application (external module) browser.")
231 {
232   LDECLARE(("emodule-clear", LBEGIN,
233 	    LEND));
234 
235   while (VVCOUNT(uistate.emod))
236     ui_emodule_uninstall(0);
237   return Lt;
238 }
239 
240 int
ui_emodule_index(char * ename,emodule ** emp)241 ui_emodule_index(char *ename, emodule **emp)
242 {
243   int i;
244   emodule *em;
245   if(!emp) emp = &em;
246   for (i=0, em=VVEC(uistate.emod, emodule); i<VVCOUNT(uistate.emod); i++, em++)
247 	if (strcasecmp(em->name, ename)==0) {
248 	    *emp = em;
249 	    return i;
250 	}
251   *emp = NULL;
252   return -1;
253 }
254 
255 /*-----------------------------------------------------------------------
256  * Function:	set_ui_target
257  * Description:	set the target of user actions
258  * Args:	type: T_GEOM or T_CAM
259  *		index: index of current geom or current cam
260  * Returns:
261  * Author:	mbp
262  * Date:	Thu Nov 21 14:04:28 1991
263  * Notes:	equivalent to set_ui_target_id( ID(type, index) )
264  */
265 void
set_ui_target(int type,int index)266 set_ui_target(int type, int index)
267 {
268   uistate.targetid = ID(type, index);
269   switch (uistate.targettype = type) {
270   case T_GEOM:
271     uistate.targetgeom = index;
272     if (uistate.bbox_center && uistate.targetid != WORLDGEOM) {
273       make_center_from_bbox("CENTER", uistate.targetid);
274     }
275     break;
276   case T_CAM:
277     uistate.targetcam = index;
278     break;
279   }
280 }
281 
282 void
set_ui_center(int id)283 set_ui_center(int id)
284 {
285   uistate.centerid = id;
286 }
287 
288 void
set_ui_center_origin(int use_bbox_center)289 set_ui_center_origin(int use_bbox_center)
290 {
291   uistate.bbox_center = use_bbox_center != 0; /* boolean value */
292   if (uistate.bbox_center && uistate.targetid != WORLDGEOM) {
293     make_center_from_bbox("CENTER", uistate.targetid);
294   } else {
295     gv_ui_center(TARGETID);
296   }
297 }
298 
299 void
set_ui_wm_focus(int cam_wm_focus)300 set_ui_wm_focus(int cam_wm_focus)
301 {
302   uistate.cam_wm_focus = cam_wm_focus != 0;
303 }
304 
305 /*-----------------------------------------------------------------------
306  * Function:	set_ui_target_id
307  * Description:	set the target id of user actions
308  * Args:	id: id to target
309  * Returns:
310  * Author:	mbp
311  * Date:	Thu Nov 21 14:05:33 1991
312  * Notes:	equivalent to set_ui_target( TYPEOF(id), INDEXOF(id) )
313  */
314 void
set_ui_target_id(int id)315 set_ui_target_id(int id)
316 {
317   set_ui_target( TYPEOF(id), INDEXOF(id) );
318 }
319 
320 
ui_cleanup()321 void ui_cleanup()
322 {
323   int i;
324   for(i = VVCOUNT(uistate.emod); --i >= 0; ) {
325     if(VVEC(uistate.emod, emodule)[i].pid > 0) {
326 	emodule_kill(&VVEC(uistate.emod, emodule)[i]);
327     }
328   }
329   gv_delete(ALLCAMS);
330 }
331 
332 /* maybe replace this later with something more useful: */
ui_targeting()333 void ui_targeting()
334 {}
335 
336 
337 /**********************************************************************/
338 
339 /* for debugging */
print_emodtable()340 void print_emodtable()
341 {
342   emodule *em;
343   int i;
344 
345   for(i=0, em=VVEC(uistate.emod,emodule); i<VVCOUNT(uistate.emod); i++, em++) {
346     fprintf(stderr, "em[%2d] = %s\n", i, em->name);
347   }
348   return;
349 }
350 
351 LDEFINE(cursor_still, LVOID,
352 	"(cursor-still [INT])\n\
353 	Sets the number of microseconds for which the cursor must not\n\
354 	move to as holding still.  If INT is not specified,\n\
355 	the value will be reset to the default.")
356 {
357   uistate.cursor_still = UI_CURSOR_STILL;
358   LDECLARE(("cursor-still", LBEGIN,
359 	    LOPTIONAL,
360 	    LINT, &uistate.cursor_still,
361 	    LEND));
362   return Lt;
363 }
364 
365 LDEFINE(cursor_twitch, LVOID,
366 	"(cursor-twitch	[INT])\n\
367 	Sets the distance which the cursor must not move (in x or\n\
368 	y) to as holding still.  If INT is not specified,\n\
369 	the value will be reset to the default.")
370 {
371   uistate.cursor_twitch = UI_CURSOR_TWITCH;
372   LDECLARE(("cursor-twitch", LBEGIN,
373 	    LOPTIONAL,
374 	    LINT, &uistate.cursor_twitch,
375 	    LEND));
376   return Lt;
377 }
378 
379 LDEFINE(ap_override, LVOID,
380 	"(ap-override [on|off])\n\
381 	Selects whether appearance controls should override objects' own\n\
382 	settings.  On by default.  With no arguments, returns current setting.")
383 {
384   Keyword kw = NOT_A_KEYWORD;
385 
386   LDECLARE(("ap-override", LBEGIN,
387 	LOPTIONAL,
388 	LKEYWORD, &kw,
389 	LEND));
390 
391   if (kw == NOT_A_KEYWORD) {
392     Keyword on = uistate.apoverride ? ON_KEYWORD : OFF_KEYWORD;
393     return LNew(LKEYWORD, &on);
394   }
395   drawer_int(WORLDGEOM, DRAWER_APOVERRIDE, boolval("ap-override", kw));
396   return Lt;
397 }
398 
399 
400 int
uispace(int space)401 uispace(int space)
402 {
403   switch (space) {
404   case TM_EUCLIDEAN:  return EUCLIDEAN;
405   case TM_HYPERBOLIC: return HYPERBOLIC;
406   case TM_SPHERICAL: return SPHERICAL;
407   }
408   return -1;
409 }
410 
411 /*
412  * Local Variables: ***
413  * c-basic-offset: 2 ***
414  * End: ***
415  */
416