1 /*
2  * FIG : Facility for Interactive Generation of figures
3  * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4  * Parts Copyright (c) 1989-2007 by Brian V. Smith
5  * Parts Copyright (c) 1991 by Paul King
6  *
7  * Any party obtaining a copy of these files is granted, free of charge, a
8  * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9  * nonexclusive right and license to deal in this software and documentation
10  * files (the "Software"), including without limitation the rights to use,
11  * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
12  * the Software, and to permit persons who receive copies from any such
13  * party to do so, with the only requirement being that the above copyright
14  * and this permission notice remain intact.
15  *
16  */
17 
18 #include "e_placelib.h"
19 
20 #include <string.h>
21 #include <X11/Intrinsic.h>	/* includes X11/Xlib.h, which includes X11/X.h */
22 
23 #include "resources.h"
24 #include "mode.h"
25 #include "object.h"
26 #include "paintop.h"
27 
28 #include "e_edit.h"
29 #include "e_flip.h"
30 #include "e_rotate.h"
31 #include "e_scale.h"
32 #include "u_create.h"
33 #include "u_elastic.h"
34 #include "u_list.h"
35 #include "u_redraw.h"
36 #include "u_translate.h"
37 #include "u_undo.h"
38 #include "w_canvas.h"
39 #include "w_cursor.h"
40 #include "w_drawprim.h"		/* for max_char_height */
41 #include "w_library.h"
42 #include "w_modepanel.h"
43 #include "w_mousefun.h"
44 #include "w_msgpanel.h"
45 #include "w_util.h"
46 
47 
48 /* EXPORTS */
49 
50 int	cur_library_object = -1;
51 int	old_library_object = -1;
52 
53 /* LOCAL */
54 
55 static Boolean	draw_box = False;
56 static int	off_library_x;
57 static int	off_library_y;
58 
59 static void	init_move_object(int x, int y);
60 static void	move_object(int x, int y);
61 static void	change_draw_mode(int x, int y);
62 static void	transform_lib_obj(XKeyEvent *kpe, unsigned char c,KeySym keysym);
63 static void	place_lib_object(int x, int y, unsigned int shift);
64 static void	put_draw(int paint_mode);
65 static void	sel_place_lib_obj_proc(int x, int y, int shift);
66 static int	orig_put_x, orig_put_y;
67 
68 
69 void
put_selected(void)70 put_selected(void)
71 {
72 	int	 i, x,y;
73 	char	*com;
74 
75 	set_mousefun("place object","new object","cancel library",
76 			"place and edit","change draw mode", "place at orig posn");
77 	set_action_on();
78 	cur_c = lib_compounds[cur_library_object]->compound;
79 	new_c = copy_compound(cur_c);
80 	/* add it to the depths so it is displayed */
81 	add_compound_depth(new_c);
82 	/* find lower-right corner for draw_box() */
83 	off_library_x = new_c->secorner.x;
84 	off_library_y = new_c->secorner.y;
85 	/* and upper-left in case the user wants to place it at its original position */
86 	/* this is saved here because the compound was shifted to 0,0 when reading in */
87 	orig_put_x = lib_compounds[cur_library_object]->corner.x;
88 	orig_put_y = lib_compounds[cur_library_object]->corner.y;
89 
90 	canvas_locmove_proc = init_move_object;
91 	canvas_ref_proc = null_proc;
92 	canvas_leftbut_proc = place_lib_object;
93 	canvas_middlebut_proc = sel_place_lib_obj_proc;
94 	canvas_rightbut_proc = cancel_place_lib_obj;
95 	set_cursor(null_cursor);
96 
97 	/* get the pointer position */
98 	get_pointer_win_xy(&x, &y);
99 	/* draw the first image */
100 	init_move_object(BACKX(x), BACKY(y));
101 
102 	/* message that we're placing object so and so */
103 	com = strdup(lib_compounds[cur_library_object]->compound->comments);
104 	if (strlen(com)) {
105 	    /* change newlines to blanks */
106 	    for (i=strlen(com); i>=0; i--)
107 		if (com[i] == '\n')
108 		    com[i] = ' ';
109 	    put_msg("Placing library object \"%s\" (%s.fig)",
110 		com, library_objects_texts[cur_library_object]);
111 	} else {
112 	    put_msg("Placing library object %s.fig", library_objects_texts[cur_library_object]);
113 	}
114 }
115 
116 /* allow rotation or flipping of library object before placing on canvas */
117 
118 static void
transform_lib_obj(XKeyEvent * kpe,unsigned char c,KeySym keysym)119 transform_lib_obj(XKeyEvent *kpe, unsigned char c, KeySym keysym)
120 {
121 	(void)kpe;
122 	(void)keysym;
123     int x,y;
124 
125     x = cur_x;
126     y = cur_y;
127 
128     /* first erase the existing image */
129     put_draw(ERASE);
130     if (c == 'r') {
131 	rotn_dirn = 1;
132 	act_rotnangle = 90;
133 	rotate_compound(new_c, x, y);
134     } else if (c == 'l') {
135 	rotn_dirn = -1;
136 	act_rotnangle = 90;
137 	rotate_compound(new_c, x, y);
138     } else if (c == 'h') {
139 	flip_compound(new_c, x, y, LR_FLIP);
140     } else if (c == 'v') {
141 	flip_compound(new_c, x, y, UD_FLIP);
142     } else if (c == 's') {
143 	scale_compound(new_c, 0.9, 0.9, x, y);
144     } else if (c == 'S') {
145 	scale_compound(new_c, 1.1, 1.1, x, y);
146     } /* if not any of the above characters, ignore it */
147     /* and draw the new image */
148     put_draw(PAINT);
149 }
150 
151 static void
sel_place_lib_obj_proc(int x,int y,int shift)152 sel_place_lib_obj_proc(int x, int y, int shift)
153 {
154     /* if shift-left button, change drawing mode */
155     if (shift) {
156 	change_draw_mode(x, y);
157 	return;
158     }
159     /* else popup the library panel again */
160     sel_place_lib_obj();
161 }
162 
163 void
sel_place_lib_obj(void)164 sel_place_lib_obj(void)
165 {
166     canvas_kbd_proc = (void (*)())transform_lib_obj;
167     canvas_locmove_proc = null_proc;
168     canvas_ref_proc = null_proc;
169     canvas_leftbut_proc = null_proc;
170     canvas_middlebut_proc = null_proc;
171     canvas_rightbut_proc = null_proc;
172 
173     /* erase any object currently being dragged around the canvas */
174     if (lib_compounds && action_on && new_c)
175 	put_draw(ERASE);
176     popup_library_panel();
177 }
178 
179 static void
put_draw(int paint_mode)180 put_draw(int paint_mode)
181 {
182   register int    x1, y1, x2, y2;
183 
184   if (draw_box) {
185       x1=cur_x;
186       y1=cur_y;
187       x2=cur_x+off_library_x;
188       y2=cur_y+off_library_y;
189       elastic_box(x1, y1, x2, y2);
190   } else {
191       if (paint_mode==ERASE)
192 	redisplay_compound(new_c);
193       else
194 	redisplay_objects(new_c);
195   }
196 }
197 
198 static void
change_draw_mode(int x,int y)199 change_draw_mode(int x, int y)
200 {
201 	(void)x;
202 	(void)y;
203 
204     put_draw(ERASE);
205     draw_box = !draw_box;
206     translate_compound(new_c,-new_c->nwcorner.x,-new_c->nwcorner.y);
207     if (!draw_box)
208 	translate_compound(new_c,cur_x,cur_y);
209 
210     put_draw(PAINT);
211 }
212 
213 /* place library object at original position in its file */
214 
215 static void
place_lib_object_orig(int x,int y,unsigned int shift)216 place_lib_object_orig(int x, int y, unsigned int shift)
217 {
218 	(void)x;
219 	(void)y;
220 	(void)shift;
221     int dx,dy;
222 
223     canvas_ref_proc = null_proc;
224     put_draw(ERASE);
225     clean_up();
226     /* move back to original position */
227     dx = orig_put_x-x;
228     dy = orig_put_y-y;
229     translate_compound(new_c,dx,dy);
230     /* remove it from the depths because it will be added when it is put in the main list */
231     remove_compound_depth(new_c);
232     add_compound(new_c);
233     set_modifiedflag();
234     redisplay_compound(new_c);
235     put_selected();
236 }
237 
238 static void
place_lib_object(int x,int y,unsigned int shift)239 place_lib_object(int x, int y, unsigned int shift)
240 {
241 	(void)x;
242 	(void)y;
243     F_compound *this_c;
244 
245     canvas_leftbut_proc = null_proc;
246     canvas_middlebut_proc = null_proc;
247     canvas_rightbut_proc = null_proc;
248     canvas_locmove_proc = null_proc;
249     canvas_ref_proc = null_proc;
250     put_draw(ERASE);
251     clean_up();
252     if (draw_box)
253 	translate_compound(new_c,cur_x,cur_y);
254     /* remove it from the depths because it will be added when it is put in the main list */
255     remove_compound_depth(new_c);
256     add_compound(new_c);
257     set_modifiedflag();
258     redisplay_compound(new_c);
259     if (shift) {
260 	/* temporarily turn off library place mode so we can edit the object just placed */
261 	canvas_kbd_proc = null_proc;
262 	clear_mousefun();
263 	set_mousefun("","","", "", "", "");
264 	turn_off_current();
265 	set_cursor(arrow_cursor);
266 	edit_remember_lib_mode = True;
267 	this_c = new_c;
268 	edit_item(this_c, O_COMPOUND, 0, 0);
269     } else {
270 	put_selected();
271     }
272 }
273 
274 
275 static void
move_object(int x,int y)276 move_object(int x, int y)
277 {
278     int dx,dy;
279     void  (*save_canvas_locmove_proc) ();
280     void  (*save_canvas_ref_proc) ();
281 
282     save_canvas_locmove_proc = canvas_locmove_proc;
283     save_canvas_ref_proc = canvas_ref_proc;
284     /* so we don't recurse infinitely */
285     canvas_locmove_proc = null_proc;
286     canvas_ref_proc = null_proc;
287     put_draw(ERASE);
288     if (!draw_box) {
289 	dx=x-cur_x;
290 	dy=y-cur_y;
291 	translate_compound(new_c,dx,dy);
292     }
293     cur_x=x;cur_y=y;
294     put_draw(PAINT);
295     canvas_locmove_proc = save_canvas_locmove_proc;
296     canvas_ref_proc = save_canvas_ref_proc;
297 }
298 
299 static void
init_move_object(int x,int y)300 init_move_object(int x, int y)
301 {
302     cur_x=x;
303     cur_y=y;
304     if (!draw_box)
305 	translate_compound(new_c,x,y);
306 
307     put_draw(PAINT);
308     canvas_locmove_proc = move_object;
309     canvas_ref_proc = move_object;
310 }
311 
312 /* cancel placing a library object */
313 
314 void
cancel_place_lib_obj(int x,int y,int shift)315 cancel_place_lib_obj(int x, int y, int shift)
316 {
317     /* if shift right-button, actually do a place in original position */
318     if (shift) {
319 	place_lib_object_orig(x, y, shift);
320 	return;
321     }
322     reset_action_on();
323     canvas_leftbut_proc = null_proc;
324     canvas_middlebut_proc = null_proc;
325     canvas_rightbut_proc = null_proc;
326     canvas_locmove_proc = null_proc;
327     canvas_ref_proc = null_proc;
328     canvas_kbd_proc = null_proc;
329     clear_mousefun();
330     set_mousefun("","","", "", "", "");
331     turn_off_current();
332     set_cursor(arrow_cursor);
333     put_draw(ERASE);
334     /* remove it from the depths */
335     remove_compound_depth(new_c);
336 }
337 
338