1 /*
2 * This file is part of XForms.
3 *
4 * XForms is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1, or
7 * (at your option) any later version.
8 *
9 * XForms is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with XForms. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19 /**
20 * \file fd_select.c
21 *
22 * This file is part of XForms package
23 * Copyright (c) 1996-2002 T.C. Zhao and Mark Overmars
24 * All rights reserved.
25 *
26 * Part of the Form Designer.
27 *
28 * This file contains all routines and data types to maintain the current
29 * selection and manipulate (move, scale) and draw it.
30 */
31
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <ctype.h>
38 #include <float.h>
39
40 #include "fd_main.h"
41 #include "fd_spec.h"
42 #include "fd_iconinfo.h"
43
44 #define MAXSEL 2048
45
46 #define BackOBJ( ) cur_form->first->next
47
48 static FL_OBJECT *selobj[ MAXSEL ]; /* list of selected objects */
49 static int selnumb = 0; /* and their number */
50 static int backf = FL_FALSE; /* whether the selection is the backface */
51
52
53 static FL_OBJECT * copy_object( FL_OBJECT * obj,
54 int exact );
55 static void set_attribs( FL_OBJECT * obj,
56 FL_OBJECT * src );
57
58
59 /***************************************
60 * Returns the index of a particular object. -1 if it is not selected
61 ***************************************/
62
63 static int
find_selobject(FL_OBJECT * obj)64 find_selobject( FL_OBJECT * obj )
65 {
66 int i;
67
68 for ( i = 0; i < selnumb; i++ )
69 if ( selobj[ i ] == obj )
70 return i;
71
72 return -1;
73 }
74
75
76 /***************************************
77 * Make a new, properly ordered list of selected objects, removing
78 * duplicates and objects set to NULL
79 ***************************************/
80
81 static void
cleanup_selection_list(void)82 cleanup_selection_list( void )
83 {
84 FL_OBJECT **tmpobj = fl_malloc( selnumb * sizeof *tmpobj ),
85 *obj;
86 int tmpnumb = 0;
87
88 for ( obj = cur_form->first; obj != NULL; obj = obj->next )
89 if ( find_selobject( obj ) != -1 )
90 tmpobj[ tmpnumb++ ] = obj;
91
92 memcpy( selobj, tmpobj, tmpnumb * sizeof *tmpobj );
93 fl_free( tmpobj );
94 selnumb = tmpnumb;
95 }
96
97
98 /***************************************
99 * Cleans up the selection, ordering the objects and creating
100 * groups if all elements are in there
101 ***************************************/
102
103 static void
cleanup_selection(void)104 cleanup_selection( void )
105 {
106 FL_OBJECT *obj,
107 *begobj = NULL;
108 int tt,
109 sel = -1;
110
111 if ( cur_form == NULL )
112 {
113 selnumb = 0;
114 backf = FL_FALSE;
115 return;
116 }
117
118 /* Figure out whether whole groups are selected */
119
120 for ( obj = cur_form->first; obj != NULL; obj = obj->next )
121 {
122 if ( obj->objclass == FL_BEGIN_GROUP )
123 {
124 sel = 1;
125 begobj = obj;
126 }
127 else if ( obj->objclass == FL_END_GROUP )
128 {
129 if ( sel )
130 {
131 selobj[ selnumb++ ] = begobj;
132 selobj[ selnumb++ ] = obj;
133 sel = 0;
134 }
135 else
136 {
137 if ( ( tt = find_selobject( begobj ) ) != -1 )
138 selobj[ tt ] = NULL;
139 if ( ( tt = find_selobject( obj ) ) != -1 )
140 selobj[ tt ] = NULL;
141 }
142 }
143 else if ( ! obj->parent && find_selobject( obj ) == -1 )
144 sel = 0;
145 }
146
147 cleanup_selection_list( );
148 fillin_groups( );
149 }
150
151
152 /***************************************
153 * Returns whether object is selected
154 ***************************************/
155
156 int
is_selected(FL_OBJECT * obj)157 is_selected( FL_OBJECT * obj )
158 {
159 return find_selobject( obj ) != -1;
160 }
161
162
163 /***************************************
164 * Adds an object to the current selection
165 ***************************************/
166
167 void
addto_selection(FL_OBJECT * obj)168 addto_selection( FL_OBJECT * obj )
169 {
170 /* Find the real parent */
171
172 while ( obj->parent )
173 obj = obj->parent;
174
175 /* Don't add objects with backface */
176
177 if ( backf )
178 clear_selection( );
179
180 if ( selnumb >= MAXSEL )
181 {
182 fprintf( stderr, "Exceeding selection limits\n" );
183 return;
184 }
185
186 selobj[ selnumb++ ] = obj;
187 cleanup_selection( );
188 }
189
190
191 /***************************************
192 * Adds a group to the current selection
193 ***************************************/
194
195 void
addgroupto_selection(FL_OBJECT * obj)196 addgroupto_selection( FL_OBJECT * obj )
197 {
198 FL_OBJECT *ob;
199
200 if ( obj->objclass != FL_BEGIN_GROUP )
201 return;
202
203 /* If the currently selected object is the backface then deselect it */
204
205 if ( backf )
206 clear_selection( );
207
208 for ( ob = obj; ob && ob->objclass != FL_END_GROUP; ob = ob->next )
209 {
210 if ( ob->parent )
211 continue;
212
213 if ( selnumb >= MAXSEL - 1 )
214 {
215 fprintf( stderr, "Exceeding selection limits\n" );
216 while ( selobj[ --selnumb ]->objclass != FL_BEGIN_GROUP )
217 /* empty */ ;
218 return;
219 }
220
221 selobj[ selnumb++ ] = ob;
222 }
223
224 if ( ob != NULL )
225 selobj[ selnumb++ ] = ob;
226
227 cleanup_selection( );
228 }
229
230
231 /***************************************
232 * Removes an object from the selection (if present)
233 ***************************************/
234
235 void
deletefrom_selection(FL_OBJECT * obj)236 deletefrom_selection( FL_OBJECT * obj )
237 {
238 int ind = find_selobject( obj );
239
240 if ( ind != -1 )
241 selobj[ ind ] = NULL;
242 cleanup_selection( );
243 }
244
245
246 /***************************************
247 * Removes a group to the current selection
248 ***************************************/
249
250 void
deletegroupfrom_selection(FL_OBJECT * obj)251 deletegroupfrom_selection( FL_OBJECT * obj )
252 {
253 FL_OBJECT *ob;
254 int ind;
255
256 if ( backf )
257 return; /* Don't remove objects with backface */
258
259 if ( obj->objclass != FL_BEGIN_GROUP )
260 return;
261
262 for ( ob = obj; ob != NULL && ob->objclass != FL_END_GROUP; ob = ob->next )
263 if ( ( ind = find_selobject( ob ) ) != -1 )
264 selobj[ ind ] = NULL;
265
266 cleanup_selection( );
267 }
268
269
270 /***************************************
271 * Clears the complete selection
272 ***************************************/
273
274 void
clear_selection(void)275 clear_selection( void )
276 {
277 backf = FL_FALSE;
278 selnumb = 0;
279 cleanup_selection( );
280 }
281
282
283 /****
284 Helper procedures
285 ****/
286
287 /***************************************
288 * Compute the bounding box of the selection
289 ***************************************/
290
291 static void
compute_selbox(double * x,double * y,double * w,double * h)292 compute_selbox( double * x,
293 double * y,
294 double * w,
295 double * h )
296 {
297 int i;
298 double x1 = DBL_MAX,
299 y1 = DBL_MAX,
300 x2 = - DBL_MAX,
301 y2 = - DBL_MAX;
302
303 for ( i = 0; i < selnumb; i++ )
304 if ( selobj[ i ]->objclass != FL_BEGIN_GROUP
305 && selobj[ i ]->objclass != FL_END_GROUP )
306 {
307 if ( selobj[ i ]->fl1 < x1 )
308 x1 = selobj[ i ]->fl1;
309 if ( selobj[ i ]->ft1 < y1 )
310 y1 = selobj[ i ]->ft1;
311 if ( selobj[ i ]->fl2 > x2 )
312 x2 = selobj[ i ]->fl2;
313 if ( selobj[ i ]->ft2 > y2 )
314 y2 = selobj[ i ]->ft2;
315 }
316
317 *x = x1;
318 *y = y1;
319 *w = x2 - x1;
320 *h = y2 - y1;
321 }
322
323
324 /***************************************
325 * Find position of the mouse mouse
326 ***************************************/
327
328 static void
find_mousepos(double * mx,double * my)329 find_mousepos( double * mx,
330 double * my )
331 {
332 if ( cur_form == NULL )
333 return;
334
335 fl_winset( main_window );
336 get_mouse_pos( mx, my );
337 }
338
339
340 /***************************************
341 * Returns the object under the mouse.
342 ***************************************/
343
344 static FL_OBJECT *
find_mouseobj(void)345 find_mouseobj( void )
346 {
347 double xx,
348 yy;
349
350 if ( cur_form == NULL )
351 return NULL;
352
353 find_mousepos( &xx, &yy );
354
355 return fli_find_last( cur_form, FLI_FIND_MOUSE, xx, yy );
356 }
357
358
359 /****
360 Drawing routines
361 ****/
362
363 #define HS 8
364
365 int hidden = FL_FALSE;
366
367
368 /***************************************
369 * Draw the selection box
370 ***************************************/
371
372 void
draw_selbox(void)373 draw_selbox( void )
374 {
375 double x,
376 y,
377 w,
378 h;
379 int i;
380 FL_OBJECT *ob;
381
382 if ( selnumb == 0 )
383 return;
384
385 /* Draw object boxes */
386
387 color( fd_red );
388 for ( i = 0; i < selnumb; i++ )
389 {
390 ob = selobj[ i ];
391 if ( ob->objclass != FL_BEGIN_GROUP && ob->objclass != FL_END_GROUP )
392 rect( ob->x, ob->y, ob->x + ob->w - 1.0, ob->y + ob->h - 1.0 );
393 }
394
395 if ( hidden )
396 return;
397
398 /* Draw the total box */
399
400 compute_selbox( &x, &y, &w, &h );
401
402 show_geometry( x, y, w, h );
403
404 if ( ! backf )
405 {
406 x -= 1.0;
407 y -= 1.0;
408 w += 2.0;
409 h += 2.0;
410 }
411 color( fd_red );
412
413 rect( x, y, x + w - 1.0, y + h - 1.0 );
414 rectf( x, y, x + HS - 1.0, y + HS - 1.0 );
415 rectf( x + w - HS, y, x + w - 1.0, y + HS - 1.0 );
416 rectf( x + w - HS, y + h - HS, x + w - 1.0, y + h - 1.0 );
417 rectf( x, y + h - HS, x + HS - 1.0, y + h - 1.0 );
418
419 show_selmessage( selobj, selnumb );
420 }
421
422
423 /****
424 Interaction handling
425 ****/
426
427 /***************************************
428 * Handles the moving of the selection (by mouse)
429 ***************************************/
430
431 int
within_selection(double mx,double my)432 within_selection( double mx,
433 double my )
434 {
435 double x,
436 y,
437 w = 0.0,
438 h = 0.0;
439
440 if ( ! selnumb || ! cur_form || ! cur_form->first )
441 return 0;
442
443 compute_selbox( &x, &y, &w, &h );
444
445 /* If backface, only within scale knob is considered within */
446
447 if ( selobj[ selnumb - 1 ] == BackOBJ( ) )
448 return mx >= x + w - HS
449 && mx < x + w
450 && my >= y + h - HS
451 && my < y + h;
452
453 return mx > x && mx < x + w && my > y && my < y + h;
454 }
455
456
457 /***************************************
458 ***************************************/
459
460 void
handle_move(const XEvent * xev)461 handle_move( const XEvent * xev )
462 {
463 double mx,
464 my;
465 double x,
466 y,
467 w,
468 h;
469 int s;
470
471 if ( cur_form == NULL || backf )
472 return;
473
474 fl_winset( main_window );
475
476 s = ShiftIsDown( xev->xbutton.state );
477
478 find_mousepos( &mx, &my );
479 compute_selbox( &x, &y, &w, &h );
480
481 if ( mx < x || mx > x + w || my < y || my > y + h )
482 return; /* not in box */
483
484 hidden = FL_TRUE;
485 redraw_the_form( 0 );
486
487 if ( s )
488 {
489 copy_selection( );
490 paste_selection( );
491 }
492 else
493 {
494 int i;
495 double ox = x;
496 double oy = y;
497 double ow = w;
498 double oh = h;
499
500 /* Show the rubberband box */
501
502 if ( mx <= x + HS && my <= y + HS )
503 {
504 x += w;
505 y += h;
506 w = -w;
507 h = -h;
508 scale_box( &x, &y, &w, &h );
509 }
510 else if ( mx <= x + HS && my >= y + h - HS )
511 {
512 x += w;
513 w = -w;
514 scale_box( &x, &y, &w, &h );
515 }
516 else if ( mx >= x + w - HS && my <= y + HS )
517 {
518 y += h;
519 h = -h;
520 scale_box( &x, &y, &w, &h );
521 }
522 else if ( mx >= x + w - HS && my >= y + h - HS )
523 scale_box( &x, &y, &w, &h );
524 else
525 move_box( &x, &y, &w, &h, FL_TRUE );
526
527 /* Recompute object sizes */
528
529 for ( i = 0; i < selnumb; i++ )
530 {
531 if ( selobj[ i ]->objclass != FL_BEGIN_GROUP
532 && selobj[ i ]->objclass != FL_END_GROUP )
533 {
534 selobj[ i ]->fl1 -= ox;
535 selobj[ i ]->fl2 -= ox;
536 selobj[ i ]->fr1 += ox;
537 selobj[ i ]->fr2 += ox;
538
539 selobj[ i ]->ft1 -= oy;
540 selobj[ i ]->ft2 -= oy;
541 selobj[ i ]->fb1 += oy;
542 selobj[ i ]->fb2 += oy;
543
544 fli_scale_object( selobj[ i ], w / ow, h / oh);
545
546 selobj[ i ]->x = selobj[ i ]->fl1 += x;
547 selobj[ i ]->fl2 += x;
548 selobj[ i ]->fr1 -= x;
549 selobj[ i ]->fr2 -= x;
550
551 selobj[ i ]->y = selobj[ i ]->ft1 += y;
552 selobj[ i ]->ft2 += y;
553 selobj[ i ]->fb1 -= y;
554 selobj[ i ]->fb2 -= y;
555
556 fli_notify_object( selobj[ i ], FL_RESIZED );
557 }
558 }
559 }
560
561 fli_recalc_intersections( cur_form );
562
563 hidden = FL_FALSE;
564 redraw_the_form( backf );
565 changed = FL_TRUE;
566 }
567
568
569 /***************************************
570 * We know how many pixels to move
571 ***************************************/
572
573 void
move_selection(FL_Coord dx,FL_Coord dy)574 move_selection( FL_Coord dx,
575 FL_Coord dy )
576 {
577 int i;
578 double x,
579 y,
580 w,
581 h;
582 double ox,
583 oy;
584 FL_OBJECT *ob;
585
586 if ( ! cur_form || backf || selnumb == 0 )
587 return;
588
589 compute_selbox( &x, &y, &w, &h );
590
591 ox = x;
592 oy = y;
593
594 if ( ( x += dx ) < 0 )
595 x = 0.0;
596 else if ( x + w > winw )
597 x = winw - w;
598
599 if ( ( y += dy ) < 0 )
600 y = 0.0;
601 else if ( y + h > winh )
602 y = winh - h;
603
604 if ( ( dx = x - ox ) == 0 && ( dy = y - oy ) == 0 )
605 return;
606
607 for ( i = 0; i < selnumb; i++ )
608 {
609 ob = selobj[ i ];
610 if ( ob->objclass != FL_BEGIN_GROUP && ob->objclass != FL_END_GROUP )
611 {
612 ob->x += dx;
613 ob->fl1 += dx;
614 ob->fl2 += dx;
615 ob->fr1 -= dx;
616 ob->fr2 -= dx;
617
618 ob->y += dy;
619 ob->ft1 += dy;
620 ob->ft2 += dy;
621 ob->fb1 -= dy;
622 ob->fb2 -= dy;
623
624 fli_notify_object( ob, FL_RESIZED );
625 }
626 }
627
628 redraw_the_form( 1 );
629 changed = FL_TRUE;
630 }
631
632
633 /***************************************
634 * Change the selection size
635 ***************************************/
636
637 #define MINSIZE 5
638 #define DELTA 0.2
639
640 void
resize_selection(FL_Coord dx,FL_Coord dy)641 resize_selection( FL_Coord dx,
642 FL_Coord dy )
643 {
644 double x,
645 y,
646 w,
647 h,
648 ox,
649 oy,
650 ow,
651 oh;
652 double yscale,
653 xscale;
654 int i;
655
656 if ( ! cur_form || selnumb == 0 )
657 return;
658
659 compute_selbox( &x, &y, &w, &h );
660
661 ox = x;
662 oy = y;
663 ow = w;
664 oh = h;
665
666 if ( backf )
667 {
668 winw = fl_scrw;
669 winh = fl_scrh;
670 }
671
672 if ( ( w += dx ) > winw)
673 w = winw;
674 else if ( w < MINSIZE )
675 w = MINSIZE;
676
677 if ( ( h += dy ) > winh )
678 h = winh;
679 else if ( h < MINSIZE )
680 h = MINSIZE;
681
682 if ( w == ow && oh == h )
683 return;
684
685 xscale = w / ow;
686 yscale = h / oh;
687
688 /* Recompute object sizes */
689
690 for ( i = 0; i < selnumb; i++ )
691 if ( selobj[ i ]->objclass != FL_BEGIN_GROUP
692 && selobj[ i ]->objclass != FL_END_GROUP )
693 {
694 selobj[ i ]->fl1 -= ox;
695 selobj[ i ]->fl2 -= ox;
696 selobj[ i ]->fr1 += ox;
697 selobj[ i ]->fr2 += ox;
698
699 selobj[ i ]->ft1 -= oy;
700 selobj[ i ]->ft2 -= oy;
701 selobj[ i ]->fb1 += oy;
702 selobj[ i ]->fb2 += oy;
703
704 fli_scale_object( selobj[ i ], xscale, yscale );
705
706 selobj[ i ]->x = selobj[ i ]->fl1 += x;
707 selobj[ i ]->fl2 += x;
708 selobj[ i ]->fr1 -= x;
709 selobj[ i ]->fr2 -= x;
710
711 selobj[ i ]->y = selobj[ i ]->ft1 += y;
712 selobj[ i ]->ft2 += y;
713 selobj[ i ]->fb1 -= y;
714 selobj[ i ]->fb2 -= y;
715
716 fli_notify_object( selobj[ i ], FL_RESIZED );
717 }
718
719 fli_recalc_intersections( cur_form );
720
721 if ( backf )
722 {
723 cur_form->w_hr = cur_form->w = selobj[ 0 ]->w;
724 cur_form->h_hr = cur_form->h = selobj[ 0 ]->h;
725 fl_winresize( main_window, cur_form->w, cur_form->h );
726 }
727
728 redraw_the_form( 1 );
729 changed = FL_TRUE;
730 }
731
732
733 /***************************************
734 * Handles the selection of objects
735 ***************************************/
736
737 void
handle_select(const XEvent * xev)738 handle_select( const XEvent * xev )
739 {
740 int s;
741 FL_OBJECT * obj,
742 * mouseobj;
743 double x,
744 y,
745 w,
746 h;
747 double stepsize;
748
749 if ( ! ( mouseobj = find_mouseobj( ) ) )
750 return;
751
752 if ( ( s = ShiftIsDown( xev->xbutton.state ) ) ) /* Shift Push */
753 {
754 if ( ! cur_form->first )
755 {
756 fprintf( stderr, "something is wrong, form has No objects\n" );
757 return;
758 }
759
760 if ( mouseobj == BackOBJ( ) )
761 return;
762
763 if ( find_selobject( mouseobj ) == -1 )
764 addto_selection( mouseobj );
765 else
766 deletefrom_selection( mouseobj );
767
768 return;
769 }
770
771 clear_selection( );
772
773 find_mousepos( &x, &y );
774 w = 0.0;
775 h = 0.0;
776
777 stepsize = get_step_size( );
778 set_step_size( 0.0 );
779 if ( xev->type != ButtonRelease )
780 scale_box( &x, &y, &w, &h );
781 set_step_size( stepsize );
782 obj = BackOBJ( )->next;
783
784 while ( obj != NULL )
785 {
786 if ( obj->objclass != FL_BEGIN_GROUP
787 && obj->objclass != FL_END_GROUP
788 && obj->x >= x
789 && obj->y >= y
790 && obj->x + obj->w <= x + w
791 && obj->y + obj->h <= y + h )
792 addto_selection( obj );
793
794 obj = obj->next;
795 }
796
797 if ( selnumb == 0 )
798 {
799 if ( mouseobj == NULL )
800 return;
801 else if ( mouseobj == BackOBJ( ) )
802 {
803 addto_selection( mouseobj );
804 backf = FL_TRUE;
805 }
806 else
807 addto_selection( mouseobj );
808 }
809 }
810
811
812 /***************************************
813 * Selects all objects in the form.
814 ***************************************/
815
816 void
select_all(void)817 select_all( void )
818 {
819 FL_OBJECT *obj;
820
821 if ( ! cur_form )
822 return;
823
824 clear_selection( );
825
826 for ( obj = BackOBJ( )->next; obj != NULL; obj = obj->next )
827 if ( ! obj->parent )
828 selobj[ selnumb++ ] = obj;
829
830 cleanup_selection( );
831 }
832
833
834 /****
835 Operations on the selection
836 ****/
837
838 /***************************************
839 * Clone curobj's attributes to the currently selected objects
840 ***************************************/
841
842 static void
change_selected_objects(FL_OBJECT * curobj)843 change_selected_objects( FL_OBJECT * curobj )
844 {
845 int i;
846 FL_OBJECT *ob;
847
848 for ( i = 0; i < selnumb; i++ )
849 {
850 ob = selobj[ i ];
851
852 if ( ob == curobj )
853 continue;
854
855 if ( ob->objclass != FL_BEGIN_GROUP && ob->objclass != FL_END_GROUP )
856 {
857 spec_change_type( ob, curobj->type );
858 set_attribs( ob, curobj );
859 }
860 }
861 }
862
863
864 /***************************************
865 * Interactively change the attributes of the selection
866 ***************************************/
867
868 void
change_selection(void)869 change_selection( void )
870 {
871 FL_OBJECT *firstobj = NULL;
872 int objclass = -1,
873 i;
874 FL_OBJECT *ob;
875
876 if ( ! cur_form )
877 return;
878
879 if ( selnumb == 0 )
880 {
881 fl_show_alert( "", "Please select object to edit",
882 "by single-clicking on it", 0 );
883 return;
884 }
885
886 if ( selnumb == 1 )
887 {
888 if ( change_object( selobj[ 0 ], FL_TRUE ) )
889 changed = 1;
890 return;
891 }
892
893 for ( i = 0; i < selnumb; i++ )
894 {
895 ob = selobj[ i ];
896 if ( ob->objclass != FL_BEGIN_GROUP
897 && ob->objclass != FL_END_GROUP )
898 {
899 if ( firstobj == NULL )
900 {
901 firstobj = ob;
902 objclass = ob->objclass;
903 }
904 else if ( objclass != ob->objclass )
905 {
906 fl_show_messages( "Selected objects have different "
907 "classes" );
908 return;
909 }
910 }
911 }
912
913 if ( firstobj == NULL )
914 return;
915
916 if ( ! change_object( firstobj, FL_FALSE ) )
917 return;
918
919 change_selected_objects( firstobj );
920 changed = 1;
921 }
922
923
924 /***************************************
925 * Aligns the objects in the selection
926 ***************************************/
927
928 void
align_selection(int dir)929 align_selection( int dir )
930 {
931 double x,
932 y,
933 w,
934 h,
935 gap,
936 shift;
937 int used[ MAXSEL ],
938 current;
939 int i,
940 j;
941
942 if ( backf || ! cur_form )
943 return; /* Cannot align the backface */
944
945 if ( selnumb <= 1 )
946 return; /* Nothing to align */
947
948 compute_selbox( &x, &y, &w, &h );
949
950 if ( dir == FD_HEQUAL ) /* Horizontal equal distance */
951 {
952 gap = 0.0;
953
954 for ( i = 0; i < selnumb; i++ )
955 gap += selobj[ i ]->w;
956
957 gap = ( w - gap ) / ( selnumb - 1 );
958
959 for ( i = 0; i < selnumb; i++ )
960 used[ i ] = 0;
961
962 for ( j = 0; j < selnumb; j++ )
963 {
964 current = -1;
965 for ( i = 0; i < selnumb; i++ )
966 if ( ! used[ i ] )
967 if ( current == -1
968 || selobj[ i ]->x < selobj[ current ]->x )
969 current = i;
970 used[ current ] = 1;
971 shift = x - selobj[ current ]->x;
972 selobj[ current ]->x += shift;
973 selobj[ current ]->fl1 += shift;
974 selobj[ current ]->fl2 += shift;
975 selobj[ current ]->fr1 -= shift;
976 selobj[ current ]->fr2 -= shift;
977 x += selobj[ current ]->w + gap;
978 }
979 }
980 else if ( dir == FD_VEQUAL ) /* Vertical equal distance */
981 {
982 gap = 0.0;
983
984 for ( i = 0; i < selnumb; i++ )
985 gap += selobj[ i ]->h;
986
987 gap = ( h - gap ) / ( selnumb - 1 );
988
989 for ( i = 0; i < selnumb; i++ )
990 used[ i ] = 0;
991
992 for ( j = 0; j < selnumb; j++ )
993 {
994 current = -1;
995 for ( i = 0; i < selnumb; i++ )
996 if ( ! used[ i ] )
997 if ( current == -1
998 || selobj[ i ]->y < selobj[ current ]->y )
999 current = i;
1000 used[ current ] = 1;
1001 shift = y - selobj[ current ]->y;
1002 selobj[ current ]->y += shift;
1003 selobj[ current ]->ft1 += shift;
1004 selobj[ current ]->ft2 += shift;
1005 selobj[ current ]->fb1 -= shift;
1006 selobj[ current ]->fb2 -= shift;
1007 y += selobj[ current ]->h + gap;
1008 }
1009 }
1010 else
1011 for ( i = 0; i < selnumb; i++ )
1012 {
1013 switch ( dir )
1014 {
1015 case FD_LEFT: /* Left */
1016 shift = x - selobj[ i ]->x;
1017 selobj[ i ]->x += shift;
1018 selobj[ i ]->fl1 += shift;
1019 selobj[ i ]->fl2 += shift;
1020 selobj[ i ]->fr1 -= shift;
1021 selobj[ i ]->fr2 -= shift;
1022 break;
1023
1024 case FD_HCENTER: /* Center */
1025 shift = x + w / 2.0 - selobj[ i ]->w / 2.0 - selobj[ i ]->x;
1026 selobj[ i ]->x += shift;
1027 selobj[ i ]->fl1 += shift;
1028 selobj[ i ]->fl2 += shift;
1029 selobj[ i ]->fr1 -= shift;
1030 selobj[ i ]->fr2 -= shift;
1031 break;
1032
1033 case FD_RIGHT: /* Right */
1034 shift = x + w - selobj[ i ]->w - selobj[ i ]->x;
1035 selobj[ i ]->x += shift;
1036 selobj[ i ]->fl1 += shift;
1037 selobj[ i ]->fl2 += shift;
1038 selobj[ i ]->fr1 -= shift;
1039 selobj[ i ]->fr2 -= shift;
1040 break;
1041
1042 case FD_TOP:
1043 shift = y - selobj[ i ]->y;
1044 selobj[ i ]->y += shift;
1045 selobj[ i ]->ft1 += shift;
1046 selobj[ i ]->ft2 += shift;
1047 selobj[ i ]->fb1 -= shift;
1048 selobj[ i ]->fb2 -= shift;
1049 break;
1050
1051 case FD_VCENTER: /* Center */
1052 shift = y + h / 2.0 - selobj[ i ]->h / 2.0 - selobj[ i ]->y;
1053 selobj[ i ]->y += shift;
1054 selobj[ i ]->ft1 += shift;
1055 selobj[ i ]->ft2 += shift;
1056 selobj[ i ]->fb1 -= shift;
1057 selobj[ i ]->fb2 -= shift;
1058 break;
1059
1060 case FD_BOTTOM:
1061 shift = y + h - selobj[ i ]->h - selobj[ i ]->y;
1062 selobj[ i ]->y += shift;
1063 selobj[ i ]->ft1 += shift;
1064 selobj[ i ]->ft2 += shift;
1065 selobj[ i ]->fb1 -= shift;
1066 selobj[ i ]->fb2 -= shift;
1067 break;
1068 }
1069 }
1070
1071 redraw_the_form( 0 );
1072 changed = 1;
1073 }
1074
1075
1076 /***************************************
1077 * Shows all objects in the selection.
1078 ***************************************/
1079
1080 void
show_selection(void)1081 show_selection( void )
1082 {
1083 int i;
1084
1085 if ( backf )
1086 return; /* Cannot show the backface */
1087
1088 if ( ! cur_form )
1089 return;
1090
1091 for ( i = 0; i < selnumb; i++ )
1092 fl_show_object( selobj[ i ] );
1093 }
1094
1095
1096 /***************************************
1097 * Hides all objects in the selection.
1098 ***************************************/
1099
1100 void
hide_selection(void)1101 hide_selection( void )
1102 {
1103 int i;
1104
1105 if ( backf )
1106 return; /* Cannot hide the backface */
1107
1108 if ( ! cur_form )
1109 return;
1110
1111 for ( i = 0; i < selnumb; i++ )
1112 fl_hide_object( selobj[ i ] );
1113 }
1114
1115
1116 /***************************************
1117 * Raises the selected objects
1118 ***************************************/
1119
1120 void
raise_selection(void)1121 raise_selection( void )
1122 {
1123 int i;
1124 FL_OBJECT **tmpobj;
1125
1126 if ( backf )
1127 return; /* Cannot raise the backface */
1128
1129 if ( ! cur_form )
1130 return;
1131
1132 tmpobj = fl_malloc( selnumb * sizeof *tmpobj );
1133 memcpy( tmpobj, selobj, selnumb * sizeof *selobj );
1134
1135 for ( i = 0; i < selnumb; i++ )
1136 {
1137 FL_OBJECT *first,
1138 *last;
1139
1140 first = last = selobj[ i ];
1141
1142 if ( ! first )
1143 continue;
1144
1145 if ( first->objclass == FL_BEGIN_GROUP )
1146 {
1147 int idx;
1148
1149 /* If a whole group is selected we move it all at once,
1150 including the objects marking the groups begin and end */
1151
1152 do
1153 {
1154 last = last->next;
1155 if ( ( idx = find_selobject( last ) ) != -1 )
1156 selobj[ idx ] = NULL;
1157 } while ( last->objclass != FL_END_GROUP );
1158
1159 /* If the group is already at the end of the forms objects
1160 there's nothing to raise */
1161
1162 if ( ! last->next )
1163 continue;
1164 }
1165 else
1166 {
1167 /* If the object has children they also need raising, set last
1168 to the last child belonging to the object */
1169
1170 if ( last->child )
1171 while ( last->next && last->next->parent )
1172 last = last->next;
1173
1174 /* Nothing to raise if we're already at the end of the list of
1175 objects of the form */
1176
1177 if ( ! last->next )
1178 continue;
1179
1180 /* If the object we raise belongs to a group remove it (and all
1181 it's chilren) from the
1182 group */
1183
1184 if ( first->group_id )
1185 {
1186 FL_OBJECT *o;
1187
1188 for ( o = first; o != last; o = o->next )
1189 o->group_id = 0;
1190 last->group_id = 0;
1191 }
1192 }
1193
1194 changed = 1;
1195
1196 first->prev->next = last->next;
1197 last->next->prev = first->prev;
1198
1199 first->prev = cur_form->last;
1200 cur_form->last->next = first;
1201 last->next = NULL;
1202
1203 cur_form->last = last;
1204 }
1205
1206 memcpy( selobj, tmpobj, selnumb * sizeof *selobj );
1207 fl_free( tmpobj );
1208 cleanup_selection( );
1209 }
1210
1211
1212 /***************************************
1213 * Lowers the selection
1214 ***************************************/
1215
1216 void
lower_selection(void)1217 lower_selection( void )
1218 {
1219 int i;
1220 FL_OBJECT **tmpobj;
1221
1222 if ( backf )
1223 return; /* Cannot lower the backface. */
1224
1225 if ( ! cur_form )
1226 return;
1227
1228 tmpobj = fl_malloc( selnumb * sizeof *tmpobj );
1229 memcpy( tmpobj, selobj, selnumb * sizeof *selobj );
1230
1231 for ( i = selnumb - 1; i >= 0; i-- )
1232 {
1233 FL_OBJECT *first,
1234 *last;
1235
1236 first = last = selobj[ i ];
1237
1238 if ( ! first || first->prev == BackOBJ( ) )
1239 continue;
1240
1241 if ( first->objclass == FL_END_GROUP )
1242 {
1243 int idx;
1244
1245 do
1246 {
1247 first = first->prev;
1248 if ( ( idx = find_selobject( first ) ) != -1 )
1249 selobj[ idx ] = NULL;
1250 } while ( first->objclass != FL_BEGIN_GROUP );
1251
1252 /* If the group is already at the start of the forms objects
1253 (except the backface object) there's nothing to raise */
1254
1255 if ( first->prev == BackOBJ( ) )
1256 continue;
1257 }
1258 else
1259 {
1260 /* If the object has children they also need lowering, set last
1261 to the last child belonging to the object */
1262
1263 if ( last->child )
1264 while ( last->next && last->next->parent )
1265 last = last->next;
1266
1267 /* Nothing to lower if we're already at the start of the list of
1268 objects of the form (module the backface object) */
1269
1270 if ( first->prev == BackOBJ( ) )
1271 continue;
1272 /* If the object we raise belongs to a group remove it (and all
1273 it's chilren) from the
1274 group */
1275
1276 if ( first->group_id )
1277 {
1278 FL_OBJECT *o;
1279
1280 for ( o = first; o != last; o = o->next )
1281 o->group_id = 0;
1282 last->group_id = 0;
1283 }
1284 }
1285
1286 changed = 1;
1287
1288 first->prev->next = last->next;
1289 if ( last->next )
1290 last->next->prev = first->prev;
1291 else
1292 cur_form->last = first->prev;
1293
1294 BackOBJ( )->next->prev = last;
1295 last->next = BackOBJ( )->next;
1296 BackOBJ( )->next = first;
1297 first->prev = BackOBJ( );
1298 }
1299
1300 memcpy( selobj, tmpobj, selnumb * sizeof *selobj );
1301 fl_free( tmpobj );
1302 cleanup_selection( );
1303 }
1304
1305
1306 static FL_OBJECT *cutbuf[ MAXSEL ]; /* Buffered objects */
1307 static int ncut = 0; /* and their number */
1308
1309
1310 /***************************************
1311 ***************************************/
1312
1313 static void
clear_cutbuffer(void)1314 clear_cutbuffer( void )
1315 {
1316 while ( ncut > 0 )
1317 {
1318 ncut--;
1319
1320 if ( cutbuf[ ncut ]->u_vdata )
1321 fl_free( cutbuf[ ncut ]->u_vdata );
1322 fl_free_object( cutbuf[ ncut ] );
1323 }
1324 }
1325
1326
1327 /***************************************
1328 * Removes all elements in the selection
1329 ***************************************/
1330
1331 void
cut_selection(void)1332 cut_selection( void )
1333 {
1334 int i;
1335
1336 if ( backf )
1337 return; /* Cannot cut the backface. */
1338
1339 if ( ! cur_form )
1340 {
1341 addform_cb( NULL, 0 );
1342 if ( ! cur_form )
1343 return;
1344 }
1345
1346 if ( selnumb == 0 )
1347 return;
1348
1349 clear_cutbuffer( );
1350
1351 /* Make new deletion and save it */
1352
1353 for ( i = 0; i < selnumb; i++ )
1354 if ( selobj[ i ]->objclass != FL_BEGIN_GROUP
1355 && selobj[ i ]->objclass != FL_END_GROUP )
1356 {
1357 fl_delete_object( selobj[ i ] );
1358 cutbuf[ ncut++ ] = copy_object( selobj[ i ], 1 );
1359 }
1360
1361 selnumb = 0;
1362 clear_selection( );
1363
1364 changed = 1;
1365 }
1366
1367
1368 /***************************************
1369 * Pastes elements from buffer into form
1370 ***************************************/
1371
1372 void
paste_selection(void)1373 paste_selection( void )
1374 {
1375 FL_OBJECT *obj;
1376 double x,
1377 y,
1378 w,
1379 h,
1380 ox,
1381 oy,
1382 shift;
1383 int i;
1384
1385 if ( ! cur_form || ! ncut )
1386 return;
1387
1388 is_pasting = 1; /* horrible hack */
1389
1390 /* Copy selection from buffer */
1391
1392 clear_selection( );
1393 redraw_the_form( 0 );
1394
1395 for ( i = 0; i < ncut; i++ )
1396 {
1397 obj = copy_object( cutbuf[ i ], 1 );
1398
1399 /* Fix label: if underlining caused by cutbuf shortcut, remove it.
1400 Note can't use cutbuf as cutbuf does not contain shortcut info */
1401
1402 if ( obj->label
1403 && strchr( obj->label, *fl_ul_magic_char )
1404 && selobj[ i ]->shortcut[ 0 ] )
1405 {
1406 char *t, *b;
1407
1408 b = t = fl_strdup( obj->label );
1409 while ( ( b = strchr( b, *fl_ul_magic_char ) ) )
1410 memmove( b, b + 1, strlen( b ) );
1411 fl_set_object_label( obj, t );
1412 fl_free( t );
1413 }
1414
1415 fl_add_object( cur_form, obj );
1416 selobj[ selnumb++ ] = obj;
1417 }
1418
1419 /* Move the selection to the correct place */
1420
1421 compute_selbox( &x, &y, &w, &h );
1422 ox = x;
1423 oy = y;
1424 move_box( &x, &y, &w, &h, FL_FALSE );
1425
1426 /* Recompute object position */
1427
1428 for ( i = 0; i < selnumb; i++ )
1429 if ( selobj[ i ]->objclass != FL_BEGIN_GROUP
1430 && selobj[ i ]->objclass != FL_END_GROUP)
1431 {
1432 shift = x - ox;
1433 selobj[ i ]->x += shift;
1434 selobj[ i ]->fl1 += shift;
1435 selobj[ i ]->fl2 += shift;
1436 selobj[ i ]->fr1 -= shift;
1437 selobj[ i ]->fr2 -= shift;
1438
1439 shift = y - oy;
1440 selobj[ i ]->y += shift;
1441 selobj[ i ]->ft1 += shift;
1442 selobj[ i ]->ft2 += shift;
1443 selobj[ i ]->fb1 -= shift;
1444 selobj[ i ]->fb2 -= shift;
1445
1446 fli_notify_object( selobj[ i ], FL_RESIZED );
1447 }
1448
1449 cleanup_selection( );
1450 redraw_the_form( 0 );
1451 changed = 1;
1452 is_pasting = 0;
1453 }
1454
1455
1456 /***************************************
1457 * Copies all elements in the selection to the buffer
1458 ***************************************/
1459
1460 void
copy_selection(void)1461 copy_selection( void )
1462
1463 {
1464 int i;
1465
1466 if ( backf || selnumb == 0 || ! cur_form )
1467 return;
1468
1469 clear_cutbuffer( );
1470
1471 /* Copy the objects */
1472
1473 for ( i = 0; i < selnumb; i++ )
1474 if ( selobj[ i ]->objclass != FL_BEGIN_GROUP
1475 && selobj[ i ]->objclass != FL_END_GROUP )
1476 cutbuf[ ncut++ ] = copy_object( selobj[ i ], 0 );
1477 }
1478
1479
1480 /***************************************
1481 * Makes a copy of the current selection
1482 ***************************************/
1483
1484 FL_OBJECT **
dup_selection(void)1485 dup_selection( void )
1486 {
1487 FL_OBJECT **ob;
1488 int i;
1489
1490 if ( ! selnumb )
1491 return NULL;
1492
1493 ob = fl_malloc( ( selnumb + 1 ) * sizeof *ob );
1494
1495 for ( i = 0; i < selnumb; i++ )
1496 ob[ i ] = copy_object( selobj[ i ], 1 );
1497
1498 ob[ selnumb ] = NULL;
1499
1500 return ob;
1501 }
1502
1503
1504 /***************************************
1505 ***************************************/
1506
1507 void
free_dupped_selection(FL_OBJECT ** ob)1508 free_dupped_selection( FL_OBJECT ** ob )
1509 {
1510 int i;
1511
1512 for ( i = 0; ob[ i ]; i++ )
1513 fl_free_object( ob[ i ] );
1514
1515 fl_free( ob );
1516 }
1517
1518
1519 /***************************************
1520 * Changes the selection to a new list of objects and show it.
1521 * The pointer received must be an array of object pointers
1522 * with the last element being set to NULL.
1523 ***************************************/
1524
1525 void
set_selection(FL_OBJECT ** ob)1526 set_selection( FL_OBJECT ** ob )
1527 {
1528 FL_OBJECT *obj;
1529 int i;
1530
1531 for ( i = 0; i < selnumb; i++ )
1532 fl_delete_object( selobj[ i ] );
1533
1534 clear_selection( );
1535 redraw_the_form( 0 );
1536
1537 for ( selnumb = 0; selnumb < MAXSEL && ob[ selnumb ]; selnumb++ )
1538 {
1539 obj = copy_object( ob[ selnumb ], 1 );
1540 if ( selobj[ selnumb ]->objclass != FL_BEGIN_GROUP
1541 && selobj[ selnumb ]->objclass != FL_END_GROUP )
1542 fl_add_object( cur_form, obj );
1543 selobj[ selnumb ] = obj;
1544 }
1545
1546 redraw_the_form( 0 );
1547 }
1548
1549
1550 /***************************************
1551 ***************************************/
1552
1553 void
next_selection(void)1554 next_selection( void )
1555 {
1556 if ( ! cur_form || ! BackOBJ( ) )
1557 return;
1558
1559 do
1560 {
1561 if ( ! selnumb || ! selobj[ 0 ]->next )
1562 selobj[ 0 ] = BackOBJ( )->next ? BackOBJ( )->next : BackOBJ( );
1563 else if ( selnumb && selobj[ 0 ]->next )
1564 selobj[ 0 ] = selobj[ 0 ]->next;
1565 selnumb = 1;
1566 } while ( selobj[ 0 ]->parent
1567 || selobj[ 0 ]->objclass == FL_BEGIN_GROUP
1568 || selobj[ 0 ]->objclass == FL_END_GROUP );
1569
1570 redraw_the_form( 0 );
1571 }
1572
1573
1574 /***************************************
1575 ***************************************/
1576
1577 void
prev_selection(void)1578 prev_selection( void )
1579 {
1580 if ( ! cur_form || ! BackOBJ( ) )
1581 return;
1582
1583 do
1584 {
1585 if ( ! selnumb || ! selobj[ 0 ]->prev )
1586 selobj[ 0 ] = BackOBJ( )->prev ? BackOBJ( )->prev : BackOBJ( );
1587 else if ( selnumb && selobj[ 0 ]->prev )
1588 selobj[ 0 ] = selobj[ 0 ]->prev;
1589 } while ( selobj[ 0 ]->parent );
1590
1591 selnumb = 1;
1592 redraw_the_form( 0 );
1593 }
1594
1595
1596 /***************************************
1597 * Groups all elements in the selection into a group
1598 ***************************************/
1599
1600 void
group_selection(void)1601 group_selection( void )
1602 {
1603 int i;
1604 FL_OBJECT *obj;
1605 const char *s;
1606
1607 if ( backf )
1608 return; /* Cannot group the backface */
1609
1610 if ( ! cur_form || selnumb == 0 )
1611 return;
1612
1613 get_new_group_name:
1614
1615 if ( ! ( s = fl_show_input( "Group name (must be usable as "
1616 "a C variable or empty):", "" ) ) )
1617 return;
1618
1619 if ( *s && ! is_valid_c_name( s ) )
1620 {
1621 fl_show_alert( "Error", "Invalid C identifier for group "
1622 "name:", s, 0 );
1623 goto get_new_group_name;
1624 }
1625
1626 obj = add_an_object( FL_BEGIN_GROUP, -1, 0, 0, 0, 0 );
1627
1628 for ( i = 0; i < selnumb; i++ )
1629 {
1630 if ( selobj[ i ]->form )
1631 fl_delete_object( selobj[ i ] );
1632
1633 if ( selobj[ i ]->objclass != FL_BEGIN_GROUP
1634 && selobj[ i ]->objclass != FL_END_GROUP )
1635 fl_add_object( cur_form, selobj[ i ] );
1636 }
1637
1638 add_an_object( FL_END_GROUP, -1, 0, 0, 0, 0 );
1639 clear_selection( );
1640 set_object_name( obj, s, "", "" );
1641 addgroupto_selection( obj );
1642 changed = 1;
1643 }
1644
1645
1646 /***************************************
1647 * Removes begin and endgroups from the selection
1648 ***************************************/
1649
1650 void
flatten_selection(void)1651 flatten_selection( void )
1652 {
1653 int i, j;
1654
1655 /* Cannot flatten the backface */
1656
1657 if ( backf )
1658 return;
1659
1660 if ( ! cur_form )
1661 return;
1662
1663 for ( i = 0; i < selnumb; i++ )
1664 {
1665 /* Bothig to be done for selected object that aren't part of a group */
1666
1667 if ( selobj[ i ]->objclass != FL_BEGIN_GROUP )
1668 continue;
1669
1670 /* Unset the group ID of all the objects that rae part of the group
1671 (unless. of course, the object for the start and the end of the
1672 group. that will keep them from getting deleted when the object
1673 for the start of thegroup is deleted. */
1674
1675 for ( j = i + 1; j < selnumb; j++ )
1676 if ( selobj[ j ]->objclass == FL_END_GROUP )
1677 break;
1678 else
1679 selobj[ j ]->group_id = 0;
1680
1681 /* Delete the obkect for the start of the group - this will also
1682 delete the object for teh end of the group (but ot the actual
1683 members of the group since we just reset theirgroup ID) */
1684
1685 fl_delete_object( selobj[ i ] );
1686
1687 /* Mark start and end object in the list of selected objects as
1688 deleted */
1689
1690 selobj[ i ] = NULL;
1691 if ( j < selnumb )
1692 selobj[ j ] = NULL;
1693
1694 /* Look for more grouped objects in the list of selected objects */
1695
1696 i = j;
1697 }
1698
1699 cleanup_selection( );
1700 changed = 1;
1701 }
1702
1703
1704 /***************************************
1705 * Makes a copy of the object. Only if 'exact' is set
1706 * the objects name is copied.
1707 ***************************************/
1708
1709 static FL_OBJECT *
copy_object(FL_OBJECT * obj,int exact)1710 copy_object( FL_OBJECT * obj,
1711 int exact )
1712 {
1713 char name[ MAX_VAR_LEN ],
1714 cbname[ MAX_VAR_LEN ],
1715 argname[ MAX_VAR_LEN ];
1716 FL_OBJECT *obj2;
1717 char *label;
1718 char *s;
1719
1720 obj2 = add_an_object( obj->objclass, obj->type, obj->x, obj->y,
1721 obj->w, obj->h );
1722
1723 get_object_name( obj, name, cbname, argname );
1724 set_object_name( obj2, exact ? name : "", cbname, argname );
1725 set_attribs( obj2, obj );
1726
1727 s = label = fl_strdup( obj->label );
1728 while ( ( s = strchr( s, '\010' ) ) )
1729 memmove( s, s + 1, strlen( s ) + 1 );
1730
1731 fl_set_object_label( obj2, label );
1732 fl_free( label );
1733
1734 /* Also copy the object specific info */
1735
1736 copy_superspec( obj2, obj );
1737 superspec_to_spec( obj2 );
1738
1739 copy_iconinfo( obj2, obj );
1740 restore_spec( obj2 );
1741
1742 fl_delete_object( obj2 );
1743
1744 return obj2;
1745 }
1746
1747
1748 /***************************************
1749 * Sets the attributes of an object
1750 ***************************************/
1751
1752 static void
set_attribs(FL_OBJECT * obj,FL_OBJECT * src)1753 set_attribs( FL_OBJECT * obj,
1754 FL_OBJECT * src )
1755 {
1756 obj->boxtype = src->boxtype;
1757 obj->col1 = src->col1;
1758 obj->col2 = src->col2;
1759 obj->lcol = src->lcol;
1760 obj->lsize = src->lsize;
1761 obj->lstyle = src->lstyle;
1762
1763 if ( obj->objclass == FL_SLIDER
1764 && ! ( obj->type & FL_VERT_PROGRESS_BAR ) )
1765 {
1766 obj->align = fl_to_outside_lalign( obj->align );
1767 if ( fl_is_center_lalign( obj->align ) )
1768 obj->align = FL_SLIDER_ALIGN;
1769 }
1770 else
1771 obj->align = src->align;
1772
1773 obj->nwgravity = src->nwgravity;
1774 obj->segravity = src->segravity;
1775 obj->resize = src->resize;
1776 obj->how_return = src->how_return;
1777
1778 fli_handle_object( obj, FL_ATTRIB, 0, 0, 0, NULL, 0 );
1779
1780 /* Some extra adjustments for spinner objects (this is a hack but
1781 avoiding it would require a complete change of how fdesign works) */
1782
1783 if ( obj->objclass == FL_SPINNER )
1784 {
1785 FL_OBJECT *subobj = fl_get_spinner_input( obj );
1786
1787 subobj->col1 = src->col1;
1788 subobj->col2 = src->col2;
1789
1790 subobj->lstyle = src->lstyle;
1791 subobj->lsize = src->lsize;
1792
1793 fli_handle_object( subobj, FL_ATTRIB, 0, 0, 0, NULL, 0 );
1794 }
1795 }
1796
1797
1798 /*
1799 * Local variables:
1800 * tab-width: 4
1801 * indent-tabs-mode: nil
1802 * End:
1803 */
1804