1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11 
12 
13 
14 #include <stdio.h>
15 
16 #include <math.h>
17 #include "ColorMapEditor.h"
18 #include "ColorMapEditorP.h"
19 
20 #ifndef MIN
21 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
22 #endif
23 #ifndef MAX
24 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
25 #endif
26 
27 
28 
29 #define HALF_LEVEL (1/(NUM_LEVELS*2))
30 /*
31  *  Declare templates for locally defined and used subroutines
32  */
33 void PrintAllControlPoints(XmColorMapEditorWidget cmew);
34 void PrintControlPoint(ControlMap *map, int point_num);
35 void AddControlPoint(ControlMap* map, double level, double value,
36 		     Boolean above);
37 void CallActivateCallback(XmColorMapEditorWidget cmew, int reason);
38 void RemoveSelectedControlPoints(XmColorMapEditorWidget cmew);
39 static void DeselectAllPoints(ControlMap *map);
40 static Boolean PointExists(ControlMap *map, double level, double value);
41 static void InsertControlPoint( ControlMap* map, int i,
42 			        double level, double value );
43 static void SetControlBoxXY( ControlMap* map, XRectangle* box,
44 			     double level, double value );
45 static void GetControlValues( ControlMap* map, int x, int y,
46 			      double* level, double* value );
47 static int RemoveControlPoint( ControlMap* map, int index );
48 static int MoveControlPoint( ControlMap* map, int index, int x, int y );
49 static int RepositionControlPoint( ControlMap* map, int index,
50 				   double level, double value );
51 static int GetControlPoint( ControlMap* map, int x, int y, int grab_mode );
52 static void DrawRubberband(XmDrawingAreaWidget w, ControlMap* map);
53 static void StretchRubberband(XmDrawingAreaWidget w, ControlMap* map);
54 static void DrawMultiPointGrabBoxes( Widget w, ControlMap* map);
55 static void ClearMultiPointGrabs( ControlMap* map);
56 void LoadColormapFromFile(char *filename, XmColorMapEditorWidget cmew,
57 	Boolean init);
58 void RecalculateControlPointLevels(XmColorMapEditorWidget cmew);
59 
60 
61 /*  Subroutine:	CreateControlMap
62  *  Purpose:	Create a ControlMap structure and partially initialize it.
63  *  Note:	Some things, such as the GC, must be initialized at expose time
64  */
CreateControlMap(ControlField * field,ControlLine * line,Pixel color,Boolean clip_value)65 ControlMap* CreateControlMap( ControlField* field, ControlLine* line,
66 			      Pixel color, Boolean clip_value )
67 {
68     ControlMap* map;
69 
70     map = (ControlMap *)XtMalloc(sizeof(struct ControlMapRec));
71     map->rubber_banding = False;
72     map->points = NULL;
73     map->undo_top = -1;
74     map->num_undoable = 0;
75     map->boxes = NULL;
76     map->num_points = 0;
77     map->size_buf = 0;
78     /* map->grabbed is the 'current' control point.  The grabbed point is black,
79        the rest are hollow.  Button 1 need not be kept depressed for a control
80        point to be grabbed */
81     map->grabbed = -1;
82     map->clip_value = clip_value;
83     map->double_click_interval = 350;
84     map->field = field;
85     map->line = line;
86     map->gc = NULL;
87     map->erase_gc = NULL;
88     map->color = color;
89     map->end_policy = FILL_LEVEL;
90     map->multi_point_grab = False;
91     map->toggle_on = False;
92     return map;
93 }
94 
95 
96 /*  Subroutine:	CMEAddControlPoint
97  *  Purpose:	External interface to add a control point
98  */
CMEAddControlPoint(Widget w,double level,double value,Boolean above)99 void CMEAddControlPoint(Widget w, double level, double value, Boolean above )
100 {
101 XmColorMapEditorWidget cmew = (XmColorMapEditorWidget)w;
102 ControlField *field;
103 int i;
104 
105     PushUndoPoints(cmew);
106     /*
107      * Normalize the level to 0.0 - 1.0
108      */
109     level = (level - cmew->color_map_editor.value_minimum)/
110 		(cmew->color_map_editor.value_maximum -
111 		cmew->color_map_editor.value_minimum);
112     for(i = 0; i < 4; i++)
113 	{
114 	field = cmew->color_map_editor.g.field[i];
115 	if(!field->map[0]->toggle_on) continue;
116 
117 	DrawControlBoxes(field->map[0], field->map[0]->erase_gc);
118 	DrawLine(field->map[0]->line, field->map[0]->line->erase_gc);
119 	AddControlPoint(field->map[0], level, value, True);
120 	SetArrayValues(field->map[0], field->line[0]);
121 	SetLineCoords(field->line[0]);
122 	DeselectAllPoints(field->map[0]);
123 	DrawControlBoxes(field->map[0], field->map[0]->gc);
124 	DrawLine(field->map[0]->line, field->map[0]->line->gc);
125 	field->user_callback(field);
126 	}
127     PrintAllControlPoints(cmew);
128     if(cmew->color_map_editor.g.field[0]->map[0]->toggle_on ||
129        cmew->color_map_editor.g.field[1]->map[0]->toggle_on ||
130        cmew->color_map_editor.g.field[2]->map[0]->toggle_on ||
131        cmew->color_map_editor.g.field[3]->map[0]->toggle_on)
132 	CallActivateCallback(cmew, XmCR_MODIFIED);
133 }
134 /*  Subroutine:	AddControlPoint
135  *  Purpose:	Put a new control point in the control point list
136  */
AddControlPoint(ControlMap * map,double level,double value,Boolean above)137 void AddControlPoint(ControlMap* map, double level, double value,
138 		     Boolean above)
139 {
140     register int i;
141 
142     if(PointExists(map, level, value)) return;
143     if (level > 1.0 )
144 	{
145 	level = 1.0;
146 	}
147     if (level < 0.0)
148 	{
149 	level = 0.0;
150 	}
151     /*  Position i at the index we want to use  */
152     if(above)
153 	for(i = 0;
154 	    (i < map->num_points) && (level >= map->points[i].level);
155 	    i++ );
156     else
157 	for(i = 0;
158 	    (i < map->num_points) && (level > map->points[i].level);
159 	    i++ );
160     InsertControlPoint(map, i, level, value);
161 }
162 
163 
164 /*  Subroutine:	InsertControlPoint
165  *  Purpose:	Knowing where the new point is to go, insert it
166  */
InsertControlPoint(ControlMap * map,int index,double level,double value)167 static void InsertControlPoint( ControlMap* map, int index,
168 			        double level, double value )
169 {
170     register int i;
171 
172     if( map->num_points == map->size_buf )
173     {
174 	map->size_buf += ADDITION;
175 	if( map->points )
176 	    map->points =
177 		(ControlPoint *)XtRealloc((char*)map->points,
178 				map->size_buf * sizeof(ControlPoint));
179 	else
180 	    map->points =
181 		(ControlPoint *)XtMalloc(map->size_buf * sizeof(ControlPoint));
182 	if( map->boxes )
183 	    map->boxes =
184 		(XRectangle *)XtRealloc((char*)map->boxes,
185 				map->size_buf * sizeof(XRectangle));
186 	else
187 	    map->boxes =
188 		(XRectangle *)XtMalloc(map->size_buf * sizeof(XRectangle));
189 	/*  Set general stuff that is unchanged by other activity  */
190 	for( i=map->num_points; i<map->size_buf; i++ )
191 	{
192 	    map->boxes[i].width = HASH_SIZE;
193 	    map->boxes[i].height = HASH_SIZE;
194 	}
195     }
196     /*  Move everything above that index up  */
197     for( i=map->num_points; i>index; i-- )
198     {
199 	(void)memcpy((char *)&map->points[i], (char *)&map->points[i-1],
200 			sizeof(ControlPoint));
201 	(void)memcpy((char *)&map->boxes[i], (char *)&map->boxes[i-1],
202 			sizeof(XRectangle));
203     }
204     ++map->num_points;
205     map->points[index].level = level;
206     map->points[index].value = value;
207     map->points[index].wrap_around = 0;
208     map->points[index].multi_point_grab = False;
209     SetControlBoxXY(map, &map->boxes[index], level, value);
210     map->points[index].x = map->boxes[index].x + HASH_OFFSET;
211     map->points[index].y = map->boxes[index].y + HASH_OFFSET;
212     map->points[index].old_print_x = -999;
213 }
214 
215 
216 /*  Subroutine:	SetControlBoxXY
217  *  Purpose:	Given level and value, set the drawing x and y for the hash box
218  */
SetControlBoxXY(ControlMap * map,XRectangle * box,double level,double value)219 static void SetControlBoxXY( ControlMap* map, XRectangle* box,
220 			     double level, double value )
221 {
222     /*  Roll value over into the range of 0.0 to 1.0  */
223     if( value > 1.0 )
224 	value -= (double)((int)value);
225     else if( value < 0.0 )
226 	value += 1.0 - (double)((int)value);
227     if( map->field->vertical )
228     {
229 	/*  Level is on vertical axis from bottom, value on horizontal  */
230 	box->x = (value * (map->field->width - 1))
231 	  + map->field->left_margin - HASH_OFFSET;
232 	box->y = ((1.0 - level) * (map->field->height - 1))
233 	  + map->field->top_margin - HASH_OFFSET;
234     }
235     else
236     {
237 	box->x = (level * (map->field->width - 1))
238 	  + map->field->left_margin - HASH_OFFSET;
239 	box->y = (value * (map->field->height - 1))
240 	  + map->field->top_margin - HASH_OFFSET;
241     }
242 }
243 
244 
245 /*  Subroutine:	GetControlValues
246  *  Purpose:	Given window x and y, set correspondong level and value.
247  *		Clip value to range of 0-1.
248  */
GetControlValues(ControlMap * map,int x,int y,double * level,double * value)249 static void GetControlValues( ControlMap* map, int x, int y,
250 			      double* level, double* value )
251 {
252 double max_level;
253 
254 
255     if( map->field->vertical )
256     {
257 	/*  Level is on vertical axis (from bottom), value on horizontal  */
258 	*level = (double)(1 - ((double)(y - map->field->top_margin)/
259 			  (double)(map->field->height - 1)));
260 	*value = (double)((double)(x - map->field->left_margin)/
261 			  (double)(map->field->width - 1));
262     }
263     else
264     {
265 	/*  Level is on horizontal axis (from left), value on vertical  */
266 	*level = (double)(x - map->field->left_margin)
267 	  / (double)(map->field->width - 1);
268 	*value = (double)(y - map->field->top_margin)
269 	  / (double)(map->field->height - 1);
270     }
271     /*  If value is a min-max between 0 and 1, restrict it  */
272     if( map->clip_value )
273     {
274 	/*  Clip value to range of 0-1  */
275 	if( *value > 1.0 )
276 	    *value = 1.0;
277 	else if( *value < 0.0 )
278 	    *value = 0.0;
279     }
280     max_level = 1.0;
281     if( *level > max_level )
282         *level = max_level;
283     else if( *level < 0.0 )
284         *level = 0.0;
285 }
286 
287 
288 /*  Subroutine: RemoveSelectedControlPoints
289  *  Purpose:	Take all selected control points out of the field
290  */
RemoveSelectedControlPoints(XmColorMapEditorWidget cmew)291 void RemoveSelectedControlPoints(XmColorMapEditorWidget cmew)
292 {
293 int i,j;
294 ControlField *field;
295 ControlMap *map;
296 
297     for(i = 0; i < 4; i++)
298     {
299 	field = cmew->color_map_editor.g.field[i];
300 	map = field->map[0];
301 	if(!map->toggle_on) continue;
302 
303 	DrawControlBoxes(field->map[0], field->map[0]->erase_gc);
304 	DrawLine(field->map[0]->line, field->map[0]->line->erase_gc);
305 	if (map->grabbed >= 0)
306 	    {
307 	    RemoveControlPoint(map,map->grabbed);
308 	    map->grabbed = -1;
309 	    }
310 	for (j = map->num_points - 1; j >= 0; j--)
311 	    {
312 	    if (map->points[j].multi_point_grab)
313 		{
314 		RemoveControlPoint(map,j);
315 		}
316 	    }
317 	SetArrayValues(field->map[0], field->line[0]);
318 	SetLineCoords(field->line[0]);
319 	DrawControlBoxes(field->map[0], field->map[0]->gc);
320 	DrawLine(field->line[0], field->map[0]->line->gc);
321     }
322     field->user_callback(field);
323     PrintAllControlPoints(cmew);
324 }
325 /*  Subroutine: RemoveAllControlPoints
326  *  Purpose:	Take all control points out of the field
327  */
RemoveAllControlPoints(ControlField * field)328 void RemoveAllControlPoints( ControlField *field)
329 {
330 int i, num_pts;
331 
332     num_pts = field->map[0]->num_points;
333     for (i=0; i < num_pts; i++)
334 	{
335 	RemoveControlPoint(field->map[0],0);
336 	}
337     PrintAllControlPoints(field->cmew);
338 }
339 /*  Subroutine: RemoveControlPoint
340  *  Purpose:	Take a control point out of the list
341  */
RemoveControlPoint(ControlMap * map,int index)342 static int RemoveControlPoint( ControlMap* map, int index )
343 {
344     int i;
345 
346     if( (index < 0) || (index >= map->num_points) )
347 	return 0;
348     /*  Move everything between there and index down  */
349     for( i=index+1; i<map->num_points; i++ )
350     {
351 	(void)memcpy((char *)&map->points[i-1], (char *)&map->points[i],
352 			sizeof(ControlPoint));
353 	(void)memcpy((char *)&map->boxes[i-1], (char *)&map->boxes[i],
354 			sizeof(XRectangle));
355     }
356     --map->num_points;
357     return 0;
358 }
359 
360 
361 /*  Subroutine:	MoveControlPoint
362  *  Purpose:	Given window x and y, Reposition the Control Point
363  */
MoveControlPoint(ControlMap * map,int index,int x,int y)364 static int MoveControlPoint( ControlMap* map, int index, int x, int y )
365 {
366     double level, value;
367 
368     x = MAX(map->field->left_margin ,x);
369     y = MAX(map->field->top_margin  ,y);
370     x = MIN(map->field->width + map->field->left_margin - 1, x);
371     y = MIN(map->field->height+ map->field->top_margin - 1, y);
372     GetControlValues(map, x, y, &level, &value);
373     map->points[index].x = x;
374     map->points[index].y = y;
375     /*  Include wrap-around offset if point has a prior wrap-around  */
376     if( map->points[index].wrap_around != 0 )
377 	value += (double)map->points[index].wrap_around;
378     return RepositionControlPoint(map, index, level, value);
379 }
380 
381 
382 /*  Subroutine:	RepositionControlPoint
383  *  Purpose:	Shift a control point to a new location (maintain good order)
384  *  Args:	Index of point being moved and its new level and value
385  */
RepositionControlPoint(ControlMap * map,int index,double level,double value)386 static int RepositionControlPoint( ControlMap* map, int index,
387 				   double level, double value )
388 {
389 Boolean get_new_vals;
390 Boolean use_adjacent_level;
391 double adjacent_level=0;
392 int min_y, max_y;
393 
394     /*
395      * use_adjacent_level and adjacent_level were implemented for the case
396      * where a control point "bumps" into another.  Since a use can place
397      * a control point at an arbitrary (non-pixel aligned) level, when another
398      * point "bumps" into it, it should get the level of the non-pixel aligned
399      * point.
400      */
401     get_new_vals = False;
402     use_adjacent_level = False;
403     max_y = (map->field->height - 1)
404 	  + map->field->top_margin;
405     min_y = map->field->top_margin;
406     if (index == 0)
407 	{
408 	if (map->points[index].y >= max_y)
409 	    {
410 	    map->points[index].y = max_y;
411 	    get_new_vals = True;
412 	    }
413 	if (map->num_points > 1)
414 	    {
415 	    if (map->points[index].y <= map->points[index+1].y )
416 		{
417 		map->points[index].y = map->points[index+1].y;
418 	    	get_new_vals = True;
419 		use_adjacent_level = True;
420 		adjacent_level = map->points[index+1].level;
421 		}
422 	    }
423 	}
424     if (index == map->num_points - 1)
425 	{
426 	if (map->points[index].y <= min_y)
427 	    {
428 	    map->points[index].y = min_y;
429 	    get_new_vals = True;
430 	    }
431 	if (map->num_points > 1)
432 	    {
433 	    if (map->points[index].y >= map->points[index-1].y )
434 		{
435 		map->points[index].y = map->points[index-1].y;
436 	    	get_new_vals = True;
437 		use_adjacent_level = True;
438 		adjacent_level = map->points[index-1].level;
439 		}
440 	    }
441 	}
442     if ( (index > 0) && (index < map->num_points-1) )
443 	{
444 	if ( map->points[index].y <= map->points[index+1].y )
445 	    {
446 	    map->points[index].y = map->points[index+1].y;
447 	    get_new_vals = True;
448 	    use_adjacent_level = True;
449 	    adjacent_level = map->points[index+1].level;
450 	    }
451 	if ( map->points[index].y >= map->points[index-1].y )
452 	    {
453 	    map->points[index].y = map->points[index-1].y;
454 	    get_new_vals = True;
455 	    use_adjacent_level = True;
456 	    adjacent_level = map->points[index-1].level;
457 	    }
458 	}
459     if (get_new_vals)
460 	{
461 	GetControlValues(map, map->points[index].x, map->points[index].y,
462 			&level, &value);
463 	}
464     if(use_adjacent_level)
465 	map->points[index].level = adjacent_level;
466     else
467 	map->points[index].level = level;
468     map->points[index].value = value;
469     SetControlBoxXY(map, &map->boxes[index], level, value);
470     return index;
471 }
472 
473 
474 /*  Subroutine:	GetControlPoint
475  *  Purpose:	Return the index of the point indicated (if the radial
476  *		distance is within GRAB_RANGE) or a new point
477  *  Note:	grab_mode: <0:new | ==0:grab,else new | >0:grab, else nothing
478  */
GetControlPoint(ControlMap * map,int x,int y,int grab_mode)479 static int GetControlPoint( ControlMap* map, int x, int y, int grab_mode )
480 {
481     double value, level;
482     int i;
483     int save_error;
484     int save_i;
485     register int error_i, error_y;
486 
487     GetControlValues(map, x, y, &level, &value);
488     /*  Position i at the index we want to use  */
489     for( i = 0; i < map->num_points; i++ )
490 	{
491 	if (level < (map->points[i].level -
492 			(double)HASH_OFFSET/(double)NUM_LEVELS)) break;
493 	}
494     /* If there are two points on the same level, select the one whose x value
495        comes the closest to the x of the button press. Note that GRAB_RANGE
496        is normally compared with the square of the error, so I simply
497        check that the y values are w/in 3 pixels of an existing
498        control point, rather than do the square root computation. */
499     if (i < (map->num_points - 1))
500 	{
501 	    if ( (map->points[i].level == map->points[i+1].level) &&
502 	     (abs(y - map->points[i].y) < 3) )
503 	    {
504 	    if (abs(x - map->points[i+1].x) < abs(x - map->points[i].x) )
505 		    {
506 		    i++;
507 		    }
508 	    }
509 	}
510     if( grab_mode >= 0 )
511     {
512 	save_error = GRAB_RANGE + GRAB_RANGE;
513 	save_i = -1;
514 	for(i = 0; i < map->num_points; i++)
515 	{
516 	    error_i = x - (map->points[i].x);
517 	    error_i *= error_i;
518 	    if( error_i <= GRAB_RANGE )
519 	    {
520 		error_y = y - (map->points[i].y);
521 		error_y *= error_y;
522 		error_i += error_y;
523 		if (error_i < save_error)
524 		{
525 		    save_error = error_i;
526 		    save_i = i;
527 		}
528 	    }
529 	}
530 	if (save_i >= 0)
531 	{
532 	    return save_i;
533 	}
534 	else
535 	{
536 	    return -1;
537 	}
538     }
539     InsertControlPoint(map, i, level, value);
540     return i;
541 }
542 
543 
544 /*  Subroutine:	RedrawControlBoxes
545  *  Purpose:	Clear the window and draw the control points anew
546  */
RedrawControlBoxes(ControlMap * map)547 void RedrawControlBoxes( ControlMap* map )
548 {
549     XClearWindow(XtDisplay(map->field->w), XtWindow(map->field->w));
550     DrawControlBoxes(map, map->gc);
551 }
552 
553 
554 /*  Subroutine:	DrawControlBoxes
555  *  Purpose:	Draw the visible control point hash boxes in the window
556  */
DrawControlBoxes(ControlMap * map,GC gc)557 void DrawControlBoxes( ControlMap* map, GC gc )
558 {
559     int start, finish, index;
560     int low, high;
561 
562     if (gc == NULL) return;
563 
564     if( map->field->vertical )
565     {
566 	low = map->field->top_margin - HASH_SIZE;
567 	high = map->field->top_margin + map->field->height - 1;
568 	/*  Points are ordered highest y to lowest  */
569 	for( start=0;
570 	     (start<map->num_points) && (map->boxes[start].y>=high);
571 	     start++ );
572 	for( finish=start;
573 	     (finish<map->num_points) && (map->boxes[finish].y>=low);
574 	     finish++ );
575     }
576     else
577     {
578 	low = map->field->left_margin - HASH_SIZE;
579 	high = map->field->left_margin + map->field->width - 1;
580 	/*  Points are ordered lowest x to highest  */
581 	for( start=0;
582 	     (start<map->num_points) && (map->boxes[start].x<low);
583 	     start++ );
584 	for( finish=start;
585 	     (finish<map->num_points) && (map->boxes[finish].x<high);
586 	     finish++ );
587     }
588     if( finish > start )
589     {
590 	XDrawRectangles(XtDisplay(map->field->w), XtWindow(map->field->w),
591 			gc, &map->boxes[start], finish - start);
592 	if(   (map->grabbed >= 0)
593 	   && (map->grabbed >= start)
594 	   && (map->grabbed < finish) )
595 	{
596 	    XRectangle* box = &map->boxes[map->grabbed];
597 	    /*  Fill region inside box (fill size is 1 smaller than box)  */
598 	    ++box->x;
599 	    ++box->y;
600 	    --box->width;
601 	    --box->height;
602 	    XFillRectangles(XtDisplay(map->field->w), XtWindow(map->field->w),
603 			    gc, box, 1);
604 	    --box->x;
605 	    --box->y;
606 	    ++box->width;
607 	    ++box->height;
608 	}
609 	for(index=0; index < map->num_points; index++)
610 	    {
611 	    if (map->points[index].multi_point_grab)
612 		{
613 	        XRectangle* box = &map->boxes[index];
614 	        /*  Fill region inside box (fill size is 1 smaller than box)  */
615 	        ++box->x;
616 	        ++box->y;
617 	        --box->width;
618 	        --box->height;
619 	        XFillRectangles(XtDisplay(map->field->w),
620 				XtWindow(map->field->w), gc, box, 1);
621 	        --box->x;
622 	        --box->y;
623 	        ++box->width;
624 	        ++box->height;
625 		}
626 	    }
627     }
628     XSync(XtDisplay(map->field->w), FALSE);
629 }
630 
631 
632 /*  Subroutine:	ResizeControlBoxes
633  *  Purpose:	Update all box drawing params for the current sizes of things
634  */
ResizeControlBoxes(ControlMap * map)635 void ResizeControlBoxes( ControlMap* map )
636 {
637     int i;
638     for( i = 0; i < map->num_points; i++ )
639 	{
640 	SetControlBoxXY(map, &map->boxes[i],
641 			map->points[i].level, map->points[i].value);
642 	map->points[i].x = map->boxes[i].x + HASH_OFFSET;
643 	map->points[i].y = map->boxes[i].y + HASH_OFFSET;
644 	}
645 }
646 
647 
648 /*  Subroutine:	MapInput
649  *  Purpose:	Handle input of button events
650  *  Returns:	True if values have been changed
651  */
MapInput(Widget w,ControlMap * map,XmDrawingAreaCallbackStruct * call_data)652 Boolean MapInput( Widget w, ControlMap* map,
653 		  XmDrawingAreaCallbackStruct* call_data )
654 {
655 ControlField    *field;
656 static Time time = 0;	/* Time of last button1 press event */
657 int index, dummy_index;
658 int delta_y, delta_x;
659 int old_x=0;
660 int xmax;
661 int xmin;
662 int point;
663 Boolean constrain_horizontal;
664 Boolean constrain_vertical;
665 int i;
666 Boolean set;
667 
668     if ( ((call_data->event->type == ButtonPress) ||
669 	  (call_data->event->type == ButtonRelease)) &&
670          (call_data->event->xbutton.button != Button1) )
671 	{
672 	return FALSE;
673 	}
674 
675     if ( (call_data->event->type == MotionNotify) &&
676 	!(call_data->event->xmotion.state & Button1Mask) )
677 	{
678 	return FALSE;
679 	}
680     constrain_vertical = map->field->cmew->color_map_editor.constrain_vert &&
681 			 map->toggle_on;
682     constrain_horizontal = map->field->cmew->color_map_editor.constrain_hor &&
683 			 map->toggle_on;
684     if( call_data->event->type == ButtonPress )
685         {
686 	if( call_data->event->xbutton.button == Button1 )
687 	    {
688 	    XtVaGetValues( map->field->toggle_b,
689 		XmNset, &set, NULL);
690 	    if(!set)
691 		{
692 		for(i = 0; i < 4; i++)
693 		    {
694 		    field = map->field->cmew->color_map_editor.g.field[i];
695 		    XtVaGetValues(field->toggle_b,
696 			XmNset, &set, NULL);
697 		    if((XmDrawingAreaWidget)w == field->w)
698 			{
699 			XtVaSetValues( field->toggle_b,
700 			    XmNset, True, NULL);
701 			map->toggle_on = True;
702 			}
703 		    else
704 			{
705 			if(set)
706 			    {
707 			    XtVaSetValues( field->toggle_b,
708 				XmNset, False, NULL);
709 			    field->map[0]->toggle_on = False;
710 			    }
711 			}
712 		    }
713 		}
714 
715 	    if(ShiftMask & call_data->event->xbutton.state)
716 		{
717 		point = GetControlPoint(map, call_data->event->xbutton.x,
718 					call_data->event->xbutton.y, 1);
719 		if(point >= 0)
720 		    {
721 		    DrawControlBoxes(map, map->erase_gc);
722 		    if(map->grabbed == point)
723 			{
724 			map->grabbed = -1;
725 			}
726 		    else
727 			{
728 			map->points[point].multi_point_grab =
729 				!map->points[point].multi_point_grab;
730 			if(map->grabbed != -1)
731 			    {
732 			    map->points[map->grabbed].multi_point_grab = True;
733 			    map->grabbed = -1;
734 			    }
735 			}
736 		    DrawControlBoxes(map, map->gc);
737 		    PrintAllControlPoints(map->field->cmew);
738 		    }
739 		return False;
740 		}
741 	    DrawControlBoxes(map, map->erase_gc);
742 	    DrawLine(map->line, map->line->erase_gc);
743 	    if(  (call_data->event->xbutton.time - time)
744 	       < map->double_click_interval )
745 	        {
746 		PushUndoPoints(map->field->cmew);
747 		ClearMultiPointGrabs(map);
748 		if( map->grabbed >= 0 )
749 		    {
750 		    RemoveControlPoint(map, map->grabbed);
751 		    map->grabbed = -1;
752 		    SetArrayValues(map, map->line);
753 		    SetLineCoords(map->line);
754 		    CallActivateCallback(map->field->cmew, XmCR_MODIFIED);
755 		    }
756 		else
757 		    {
758 		    map->grabbed =
759 		      GetControlPoint(map, call_data->event->xbutton.x,
760 				      call_data->event->xbutton.y, -1);
761 		    map->points[map->grabbed].wrap_around = 0;
762 		    }
763 		time = 0;
764 	        }
765 	    else	/* Not a double click */
766 	        {
767 		map->grabbed =
768 		    GetControlPoint(map, call_data->event->xbutton.x,
769 				    call_data->event->xbutton.y, 1);
770 		time = call_data->event->xbutton.time;
771 		/* Btn not pressed on a control point */
772 		if (map->grabbed == -1)
773 		    {
774 		    ClearMultiPointGrabs(map);
775 		    map->multi_point_grab = True;
776 		    map->rubber_banding = True;
777 		    map->first_rubber_band = True;
778 		    map->rubber_band_base_y = call_data->event->xbutton.y;
779 		    map->rubber_band_current_y = call_data->event->xbutton.y;
780 		    }
781 		else
782 		    {
783 		    /* Btn pressed on a control point that is part of a multi
784 			point grab */
785 		    PushUndoPoints(map->field->cmew);
786 		    if (map->points[map->grabbed].multi_point_grab)
787 			{
788 			/* set grabbed to -1 so we can distinguish this mode
789 			   while doing the motion processing */
790 			map->grabbed = -1;
791 		        map->multi_move_base_y = call_data->event->xbutton.y;
792 		        map->multi_move_base_x = call_data->event->xbutton.x;
793 			map->multi_point_move = True;
794 			}
795 		    else
796 			{
797 			ClearMultiPointGrabs(map);
798 			}
799 		    }
800 	        }
801 	    DrawControlBoxes(map, map->gc);
802 	    DrawLine(map->line, map->line->gc);
803 	    PrintAllControlPoints(map->field->cmew);
804 	    if( time == 0 )
805 		return TRUE;
806 	    }
807         }
808     else if( call_data->event->type == MotionNotify )
809         {
810 	/*
811 	 * Shift/Button events are processed in the button press.
812 	 */
813 	if(ShiftMask & call_data->event->xmotion.state) return FALSE;
814 
815 	if( map->grabbed >= 0 )
816 	    {
817 	    DrawControlBoxes(map, map->erase_gc);/* Erase the old boxes */
818 	    DrawLine(map->line, map->line->erase_gc);/* Erase the old lines */
819 	    if (constrain_vertical)
820 		{
821 		call_data->event->xmotion.x = map->points[map->grabbed].x;
822 		old_x = call_data->event->xmotion.x;
823 		}
824 	    if (constrain_horizontal)
825 		{
826 		call_data->event->xmotion.y = map->points[map->grabbed].y;
827 		}
828 	    map->grabbed =
829 	      MoveControlPoint(map, map->grabbed, call_data->event->xmotion.x,
830 			       call_data->event->xmotion.y);
831 	    if (constrain_vertical)
832 		{
833 		map->points[map->grabbed].x = old_x;
834 		}
835 	    SetArrayValues(map, map->line);
836 	    SetLineCoords(map->line);
837 	    DrawControlBoxes(map, map->gc);
838 	    DrawLine(map->line, map->line->gc);
839 	    PrintAllControlPoints(map->field->cmew);
840 	    return TRUE;
841 	    }
842 	else if(map->rubber_banding)
843 	    {
844 	    map->rubber_band_current_y = call_data->event->xmotion.y;
845 	    StretchRubberband((XmDrawingAreaWidget)w, map);
846 	    DrawMultiPointGrabBoxes(w, map);
847 	    }
848 	else if( map->multi_point_move )
849 	    {
850 	    DrawControlBoxes(map, map->erase_gc);     /* Erase the old boxes */
851 	    DrawLine(map->line, map->line->erase_gc); /* Erase the old lines */
852 	    delta_y = call_data->event->xmotion.y - map->multi_move_base_y;
853 	    delta_x = call_data->event->xmotion.x - map->multi_move_base_x;
854 	    if (constrain_vertical)
855 		{
856 		delta_x = 0;
857 		}
858 	    if (constrain_horizontal)
859 		{
860 		delta_y = 0;
861 		}
862 	    /* Calculate the y limits of movement for the group */
863 	    xmax = (map->field->width-1) +
864 		 map->field->right_margin - HASH_OFFSET;
865 	    xmin = map->field->left_margin;
866 	    if (delta_x != 0)
867 		{
868 		for(index = 0; index < map->num_points; index++)
869 		    {
870 		    if (map->points[index].multi_point_grab)
871 			{
872 			if (delta_x + map->points[index].x < xmin)
873 			    {
874 			    delta_x = -(map->points[index].x - xmin);
875 			    }
876 			if ((delta_x + map->points[index].x) > xmax)
877 			    {
878 			    delta_x = ((map->field->width-1) +
879 				map->field->left_margin) -
880 				map->points[index].x;
881 			    }
882 			}
883 		    }
884 		}
885 	    if (delta_y > 0)
886 		{
887 	        for(index = 0; index < map->num_points; index++)
888 	            {
889 	            if (map->points[index].multi_point_grab)
890 		        {
891 		        if (index != 0)
892 			    {
893 		    	    if (delta_y > (map->points[index-1].y -
894 						map->points[index].y) )
895 			        {
896 			        delta_y = map->points[index-1].y -
897 						map->points[index].y;
898 			        }
899 			    }
900 		        else
901 			    {
902 			    delta_y = MIN(delta_y, (((map->field->height - 1) +
903 					map->field->top_margin - HASH_OFFSET) -
904 					map->points[0].y));
905 			    }
906 		        break;
907 		        }
908 	            }
909 		}
910 	    if (delta_y < 0)
911 		{
912 	        for(index = map->num_points - 1; index >= 0;  index--)
913 	            {
914 	            if (map->points[index].multi_point_grab)
915 		        {
916 		        if ((index + 1) != map->num_points)
917 			    {
918 		    	    if (abs(delta_y) > abs(map->points[index+1].y -
919 						map->points[index].y))
920 			        {
921 			        delta_y = map->points[index+1].y -
922 						map->points[index].y;
923 			        }
924 			    }
925 		        else
926 			    {
927 		    	    if  ( (map->points[index].y + delta_y) <
928 				 (HASH_SIZE - 1)  )
929 				{
930 			        delta_y = -(map->points[index].y - HASH_SIZE+1);
931 			        }
932 			    }
933 		        break;
934 		        }
935 	            }
936 		}
937 	    if (delta_y >= 0)
938 		{
939 	        for (index = 0; index < map->num_points; index++)
940 		    {
941 		    if (map->points[index].multi_point_grab)
942 		        {
943 	    	        dummy_index = MoveControlPoint(map, index,
944 			    	map->points[index].x + delta_x,
945 				map->points[index].y + delta_y);
946 		        }
947 		    }
948 		}
949 	    else
950 		{
951 	        for (index = map->num_points - 1; index >= 0; index--)
952 		    {
953 		    if (map->points[index].multi_point_grab)
954 		        {
955 	    	        dummy_index = MoveControlPoint(map, index,
956 			    	map->points[index].x + delta_x,
957 				map->points[index].y + delta_y);
958 			if (index != dummy_index)
959 			    {
960 			    map->points[index].multi_point_grab = True;
961 			    map->points[index+1].multi_point_grab = False;
962 			    }
963 		        }
964 		    }
965 		}
966 	    map->multi_move_base_y = call_data->event->xmotion.y;
967 	    map->multi_move_base_x = call_data->event->xmotion.x;
968 	    SetArrayValues(map, map->line);
969 	    SetLineCoords(map->line);
970 	    DrawControlBoxes(map, map->gc);
971 	    DrawLine(map->line, map->line->gc);
972 	    PrintAllControlPoints(map->field->cmew);
973 	    return TRUE;
974 	    }
975         }
976     else if(call_data->event->type == ButtonRelease)
977         {
978 	/*
979 	 * Shift/Button events are processed in the button press.
980 	 */
981 	if(ShiftMask & call_data->event->xbutton.state)
982 	    {
983 	    CallActivateCallback(map->field->cmew, XmCR_SELECT);
984 	    return FALSE;
985 	    }
986 
987 	if (map->rubber_banding)
988 	    {
989 	    map->rubber_banding = False;
990 	    map->multi_point_grab = False;
991 	    map->rubber_band_current_y = call_data->event->xbutton.y;
992 	    if(!map->first_rubber_band)
993 		{
994 		DrawRubberband((XmDrawingAreaWidget)w, map);
995 		}
996 	    DrawMultiPointGrabBoxes(w, map);
997 	    CallActivateCallback(map->field->cmew, XmCR_SELECT);
998 	    }
999 	else if(map->grabbed >= 0)
1000 	    {
1001 	    DrawControlBoxes(map, map->erase_gc);
1002 	    DrawLine(map->line, map->line->erase_gc);
1003 	    if (constrain_vertical)
1004 		{
1005 		call_data->event->xbutton.x = map->points[map->grabbed].x;
1006 		}
1007 	    if (constrain_horizontal)
1008 		{
1009 		call_data->event->xbutton.y = map->points[map->grabbed].y;
1010 		}
1011 	    map->grabbed =
1012 	      MoveControlPoint(map, map->grabbed, call_data->event->xbutton.x,
1013 			       call_data->event->xbutton.y);
1014 	    if( map->clip_value == FALSE )
1015 		/*  Record the degree of wrap-around  */
1016 		map->points[map->grabbed].wrap_around =
1017 		  (short)floor(map->points[map->grabbed].value);
1018 	    SetArrayValues(map, map->line);
1019 	    SetLineCoords(map->line);
1020 	    CallActivateCallback(map->field->cmew, XmCR_MODIFIED);
1021 	    DrawControlBoxes(map, map->gc);
1022 	    DrawLine(map->line, map->line->gc);
1023 	    return TRUE;
1024 	    }
1025 	else if (map->multi_point_move)
1026 	    {
1027 	    map->multi_point_move = False;
1028 	    CallActivateCallback(map->field->cmew, XmCR_MODIFIED);
1029 	    }
1030 	else
1031 	    {
1032 	    CallActivateCallback(map->field->cmew, XmCR_SELECT);
1033 	    }
1034 	PrintAllControlPoints(map->field->cmew);
1035         }
1036     return FALSE;
1037 }
DrawRubberband(XmDrawingAreaWidget w,ControlMap * map)1038 static void DrawRubberband(XmDrawingAreaWidget w, ControlMap* map)
1039 {
1040 	XDrawRectangle(XtDisplay(w), XtWindow(w), map->field->rubber_band_gc,
1041 		w->manager.shadow_thickness,
1042 		MIN(map->rubber_band_base_y, map->rubber_band_current_y),
1043 		w->core.width-2*(w->manager.shadow_thickness)-1,
1044 		abs(map->rubber_band_base_y - map->rubber_band_current_y));
1045 
1046 	map->rubber_band_old_y = map->rubber_band_current_y;
1047 }
StretchRubberband(XmDrawingAreaWidget w,ControlMap * map)1048 static void StretchRubberband(XmDrawingAreaWidget w, ControlMap* map)
1049 {
1050     if (!map->first_rubber_band)
1051     XDrawRectangle(XtDisplay(w), XtWindow(w), map->field->rubber_band_gc,
1052 	w->manager.shadow_thickness,
1053 	MIN(map->rubber_band_base_y, map->rubber_band_old_y),
1054 	w->core.width-2*(w->manager.shadow_thickness)-1,
1055 	abs(map->rubber_band_base_y - map->rubber_band_old_y));
1056 
1057     XDrawRectangle(XtDisplay(w), XtWindow(w), map->field->rubber_band_gc,
1058 	w->manager.shadow_thickness,
1059 	MIN(map->rubber_band_base_y, map->rubber_band_current_y),
1060 	w->core.width-2*(w->manager.shadow_thickness)-1,
1061 	abs(map->rubber_band_base_y - map->rubber_band_current_y));
1062 
1063     map->first_rubber_band = False;
1064     map->rubber_band_old_y = map->rubber_band_current_y;
1065 }
1066 /*  Subroutine:	DrawControlBoxes
1067  *  Purpose:	Draw the visible control point hash boxes in the window
1068  */
DrawMultiPointGrabBoxes(Widget w,ControlMap * map)1069 static void DrawMultiPointGrabBoxes( Widget w, ControlMap* map)
1070 {
1071 int start, finish;
1072 int low, high;
1073 int yupper, ylower, index;
1074 
1075     if( map->field->vertical )
1076         {
1077 	low = map->field->top_margin - HASH_SIZE;
1078 	high = map->field->top_margin + map->field->height - 1;
1079 	/*  Points are ordered highest y to lowest  */
1080 	for( start=0;
1081 	     (start<map->num_points) && (map->boxes[start].y>high);
1082 	     start++ );
1083 	for( finish=start;
1084 	     (finish<map->num_points) && (map->boxes[finish].y>low);
1085 	     finish++ );
1086         }
1087     else
1088         {
1089 	low = map->field->left_margin - HASH_SIZE;
1090 	high = map->field->left_margin + map->field->width - 1;
1091 	/*  Points are ordered lowest x to highest  */
1092 	for( start=0;
1093 	     (start<map->num_points) && (map->boxes[start].x<low);
1094 	     start++ );
1095 	for( finish=start;
1096 	     (finish<map->num_points) && (map->boxes[finish].x<high);
1097 	     finish++ );
1098         }
1099     if( finish > start )
1100         {
1101 	ylower = MIN(map->rubber_band_current_y,
1102 			map->rubber_band_base_y) - 2*HASH_OFFSET;
1103 	yupper = MAX(map->rubber_band_current_y,
1104 			map->rubber_band_base_y) + HASH_OFFSET;
1105         for( index=0; (index < map->num_points); index++ )
1106 	    {
1107 	    /* Is the point between the grab range ? */
1108 	    if ( (map->boxes[index].y > ylower) &&
1109 		 (map->boxes[index].y < yupper) )
1110 	        {
1111 		/* If the point is currently not grabbed, fill it in */
1112 		if (!map->points[index].multi_point_grab)
1113 		    {
1114 	            XRectangle* box = &map->boxes[index];
1115 		    map->points[index].multi_point_grab = True;
1116 	        /*  Fill region inside box (fill size is 1 smaller than box)  */
1117 	            ++box->x;
1118 	            ++box->y;
1119 	            --box->width;
1120 	            --box->height;
1121 	            XFillRectangles(XtDisplay(map->field->w),
1122 				XtWindow(map->field->w), map->gc, box, 1);
1123 	            --box->x;
1124 	            --box->y;
1125 	            ++box->width;
1126 	            ++box->height;
1127 		    }
1128 	        }
1129 	    else
1130 	        {
1131 	        /* The point is out of the grab range. If it was grabbed,
1132 		   unfill the rectangle  */
1133 		if (map->points[index].multi_point_grab)
1134 		    {
1135 	            XRectangle* box = &map->boxes[index];
1136 		    map->points[index].multi_point_grab = False;
1137 	        /*  Fill region inside box (fill size is 1 smaller than box)  */
1138 	            ++box->x;
1139 	            ++box->y;
1140 	            --box->width;
1141 	            --box->height;
1142 	            XFillRectangles(XtDisplay(map->field->w),
1143 				XtWindow(map->field->w), map->erase_gc, box, 1);
1144 	            --box->x;
1145 	            --box->y;
1146 	            ++box->width;
1147 	            ++box->height;
1148 		    }
1149 	        }
1150 	    }
1151         }
1152     XSync(XtDisplay(map->field->w), FALSE);
1153 }
1154 /*  Subroutine:	DrawControlBoxes
1155  *  Purpose:	Draw the visible control point hash boxes in the window
1156  */
ClearMultiPointGrabs(ControlMap * map)1157 static void ClearMultiPointGrabs( ControlMap* map)
1158 {
1159 int index;
1160 
1161     for (index = 0; index < map->num_points; index ++)
1162 	{
1163 	map->points[index].multi_point_grab = False;
1164 	}
1165 }
1166 /*  Subroutine:	CallActivateCallback
1167  *  Purpose:	Call registered callbacks to report value change
1168  */
CallActivateCallback(XmColorMapEditorWidget cmew,int reason)1169 void CallActivateCallback( XmColorMapEditorWidget cmew, int reason)
1170 {
1171 XmColorMapEditorCallbackStruct call_value;
1172 int 		i;
1173 ControlField 	*field;
1174 ControlMap 	*map;
1175 int		index;
1176 
1177     call_value.reason = reason;
1178     call_value.op_values = NULL;
1179     call_value.val_values = NULL;
1180     call_value.sat_values = NULL;
1181     call_value.hue_values = NULL;
1182 
1183     for(i = 0; i < 4; i++)
1184 	{
1185 	if (cmew->color_map_editor.g.field[i]->map[0]->toggle_on)
1186 	    {
1187 	    /*
1188 	     * The value MUST match the #defines in ColorMapEditor.h
1189 	     */
1190 	    call_value.selected_area = i;
1191 	    break;
1192 	    }
1193 	}
1194     call_value.min_value = cmew->color_map_editor.value_minimum;
1195     call_value.max_value = cmew->color_map_editor.value_maximum;
1196     field = cmew->color_map_editor.g.field[0];
1197 
1198     /*
1199      * Note: If the field toggle is not on, set the number of selected control
1200      * points to zero, so the application can set menu sensitivity correctly.
1201      */
1202     call_value.hue_selected = 0;
1203     call_value.sat_selected = 0;
1204     call_value.val_selected = 0;
1205     call_value.op_selected = 0;
1206     if(!field->map[0]->toggle_on)
1207 	{
1208 	call_value.hue_selected = 0;
1209 	}
1210     else if (field->map[0]->grabbed >=0 )
1211 	{
1212 	call_value.hue_selected = 1;
1213 	}
1214     else
1215 	{
1216 	for(i = 0; i < field->map[0]->num_points;
1217 						i++)
1218 	    {
1219 	    if (field->map[0]->points[i].multi_point_grab)
1220 		{
1221 		call_value.hue_selected++;
1222 		}
1223 	    }
1224 	}
1225     field = cmew->color_map_editor.g.field[1];
1226     if(!field->map[0]->toggle_on)
1227 	{
1228 	call_value.sat_selected = 0;
1229 	}
1230     else if (field->map[0]->grabbed >=0 )
1231 	{
1232 	call_value.sat_selected = 1;
1233 	}
1234     else
1235 	{
1236 	for(i = 0; i < field->map[0]->num_points; i++)
1237 	    {
1238 	    if (field->map[0]->points[i].multi_point_grab)
1239 		{
1240 		call_value.sat_selected++;
1241 		}
1242 	    }
1243 	}
1244     field = cmew->color_map_editor.g.field[2];
1245     if(!field->map[0]->toggle_on)
1246 	{
1247 	call_value.val_selected = 0;
1248 	}
1249     else if (field->map[0]->grabbed >=0 )
1250 	{
1251 	call_value.val_selected = 1;
1252 	}
1253     else
1254 	{
1255 	for(i = 0; i < field->map[0]->num_points;
1256 						i++)
1257 	    {
1258 	    if (field->map[0]->points[i].multi_point_grab)
1259 		{
1260 		call_value.val_selected++;
1261 		}
1262 	    }
1263 	}
1264     field = cmew->color_map_editor.g.field[3];
1265     if(!field->map[0]->toggle_on)
1266 	{
1267 	call_value.op_selected = 0;
1268 	}
1269     else if (field->map[0]->grabbed >=0 )
1270 	{
1271 	call_value.op_selected = 1;
1272 	}
1273     else
1274 	{
1275 	for(i = 0; i < field->map[0]->num_points;
1276 						i++)
1277 	    {
1278 	    if (field->map[0]->points[i].multi_point_grab)
1279 		{
1280 		call_value.op_selected++;
1281 		}
1282 	    }
1283 	}
1284 #ifdef Comment
1285 {
1286     struct
1287     {
1288     Boolean	occupied;
1289     int		num_hues;
1290     int		num_sats;
1291     int		num_vals;
1292     int		hue_index[2];
1293     int		sat_index[2];
1294     int		val_index[2];
1295     int		wrap_around;
1296     double	level;
1297     } flags[NUM_LEVELS];
1298 
1299     int		num_alloced_pts;
1300 
1301     /* Initialize the flags array */
1302     for (i = 0; i < NUM_LEVELS; i++)
1303 	{
1304 	flags[i].occupied = False;
1305 	flags[i].num_hues = 0;
1306 	flags[i].num_sats = 0;
1307 	flags[i].num_vals = 0;
1308 	flags[i].wrap_around = 0;
1309 	}
1310 	/* Find all the control points and set the corresponding flag in the
1311 	   flags array. */
1312 	for (i = 0; i < 3; i ++)
1313 	    {
1314 	    field = cmew->color_map_editor.g.field[i];
1315 	    for (j = 0; j < field->map[0]->num_points; j++)
1316 		{
1317 		level = field->map[0]->points[j].level;
1318 		index = level*(NUM_LEVELS-1) + 0.5;
1319 		flags[index].occupied = True;
1320 		flags[index].level = field->map[0]->points[j].level;
1321 		switch(i)
1322 		    {
1323 		    case 0:
1324 			if(flags[index].num_hues == 0)
1325 			    {
1326 			    flags[index].num_hues = 1;
1327 			    flags[index].hue_index[0] = j;
1328 			    }
1329 			else
1330 			    {
1331 			    flags[index].num_hues = 2;
1332 			    flags[index].hue_index[1] = j;
1333 			    }
1334 			break;
1335 		    case 1:
1336 			if(flags[index].num_sats == 0)
1337 			    {
1338 			    flags[index].num_sats = 1;
1339 			    flags[index].sat_index[0] = j;
1340 			    }
1341 			else
1342 			    {
1343 			    flags[index].num_sats = 2;
1344 			    flags[index].sat_index[1] = j;
1345 			    }
1346 			break;
1347 		    case 2:
1348 			if(flags[index].num_vals == 0)
1349 			    {
1350 			    flags[index].num_vals = 1;
1351 			    flags[index].val_index[0] = j;
1352 			    }
1353 			else
1354 			    {
1355 			    flags[index].num_vals = 2;
1356 			    flags[index].val_index[1] = j;
1357 			    }
1358 			break;
1359 		    }
1360 		/* Record hue wrap arounds */
1361 		if (i == 0)
1362 		    {
1363 		    flags[index].wrap_around =
1364 				field->map[0]->points[j].wrap_around;
1365 		    }
1366 		}
1367 	    }
1368 	if (!flags[0].occupied)
1369 	    {
1370 	    flags[0].occupied = True;
1371 	    flags[0].level = 0.0;
1372 	    }
1373 	if (!flags[NUM_LEVELS-1].occupied)
1374 	    {
1375 	    flags[NUM_LEVELS-1].occupied = True;
1376 	    flags[NUM_LEVELS-1].level = 1.0;
1377 	    }
1378 	/* Count the number of control points we have to send */
1379 	call_value.num_points = 0;
1380 	for (i = 0; i < NUM_LEVELS; i++)
1381 	    {
1382 	    if ( flags[i].occupied )
1383 		{
1384 	        call_value.num_points++;
1385 		if ( (flags[i].num_hues == 2) ||
1386 		     (flags[i].num_sats == 2) ||
1387 		     (flags[i].num_vals == 2) )
1388 		    {
1389 	            call_value.num_points++;
1390 		    }
1391 		}
1392 	    }
1393 	call_value.reason = reason;
1394 	call_value.data =
1395 		(double *)XtMalloc(call_value.num_points*sizeof(double));
1396 	call_value.hue_values =
1397 		(double *)XtMalloc(call_value.num_points*sizeof(double));
1398 	call_value.sat_values =
1399 		(double *)XtMalloc(call_value.num_points*sizeof(double));
1400 	call_value.val_values =
1401 		(double *)XtMalloc(call_value.num_points*sizeof(double));
1402 
1403 	j = 0;
1404 	for (i = 0; i < NUM_LEVELS; i++)
1405 	    {
1406 	    if ( flags[i].occupied )
1407 		{
1408 		if ( (flags[i].num_hues < 2) &&
1409 		     (flags[i].num_sats < 2) &&
1410 		     (flags[i].num_vals < 2) )
1411 		    {
1412 		    call_value.data[j] = cmew->color_map_editor.value_minimum +
1413 			flags[i].level*(cmew->color_map_editor.value_maximum -
1414 			cmew->color_map_editor.value_minimum);
1415 	     	    call_value.hue_values[j] = flags[i].wrap_around +
1416 			cmew->color_map_editor.g.field[0]->line[0]->values[i];
1417 	     	    call_value.sat_values[j] =
1418 			cmew->color_map_editor.g.field[1]->line[0]->values[i];
1419 	     	    call_value.val_values[j] =
1420 			cmew->color_map_editor.g.field[2]->line[0]->values[i];
1421 			j++;
1422 		    }
1423 		else
1424 		    {
1425 		    call_value.data[j] = cmew->color_map_editor.value_minimum +
1426 			flags[i].level*(cmew->color_map_editor.value_maximum -
1427 			cmew->color_map_editor.value_minimum);
1428 		    field = cmew->color_map_editor.g.field[0];
1429 		    if(flags[i].num_hues == 2)
1430 			{
1431 			call_value.hue_values[j] =
1432 			    field->map[0]->points[flags[i].hue_index[0]].value;
1433 			}
1434 		    else
1435 			{
1436 	     	        call_value.hue_values[j] = flags[i].wrap_around +
1437 			field->line[0]->values[i];
1438 			}
1439 
1440 		    field = cmew->color_map_editor.g.field[1];
1441 		    if(flags[i].num_sats == 2)
1442 			{
1443 			call_value.sat_values[j] =
1444 			    field->map[0]->points[flags[i].sat_index[0]].value;
1445 			}
1446 		    else
1447 			{
1448 	     	        call_value.sat_values[j] = field->line[0]->values[i];
1449 			}
1450 
1451 		    field = cmew->color_map_editor.g.field[2];
1452 		    if(flags[i].num_vals == 2)
1453 			{
1454 			call_value.val_values[j] =
1455 			    field->map[0]->points[flags[i].val_index[0]].value;
1456 			}
1457 		    else
1458 			{
1459 	     	        call_value.val_values[j] = field->line[0]->values[i];
1460 			}
1461 		    j++;
1462 
1463 		    call_value.data[j] = cmew->color_map_editor.value_minimum +
1464 			flags[i].level*(cmew->color_map_editor.value_maximum -
1465 			cmew->color_map_editor.value_minimum);
1466 		    field = cmew->color_map_editor.g.field[0];
1467 		    if(flags[i].num_hues == 2)
1468 			{
1469 			call_value.hue_values[j] =
1470 			    field->map[0]->points[flags[i].hue_index[1]].value;
1471 			}
1472 		    else
1473 			{
1474 	     	        call_value.hue_values[j] = flags[i].wrap_around +
1475 			field->line[0]->values[i];
1476 			}
1477 
1478 		    field = cmew->color_map_editor.g.field[1];
1479 		    if(flags[i].num_sats == 2)
1480 			{
1481 			call_value.sat_values[j] =
1482 			    field->map[0]->points[flags[i].sat_index[1]].value;
1483 			}
1484 		    else
1485 			{
1486 	     	        call_value.sat_values[j] = field->line[0]->values[i];
1487 			}
1488 
1489 		    field = cmew->color_map_editor.g.field[2];
1490 		    if(flags[i].num_vals == 2)
1491 			{
1492 			call_value.val_values[j] =
1493 			    field->map[0]->points[flags[i].val_index[1]].value;
1494 			}
1495 		    else
1496 			{
1497 	     	        call_value.val_values[j] = field->line[0]->values[i];
1498 			}
1499 		    j++;
1500 		    }
1501 		}
1502 	    }
1503 
1504 	/* Opacity field */
1505 	field = cmew->color_map_editor.g.field[3];
1506 	call_value.num_op_points = field->map[0]->num_points;
1507 	num_alloced_pts = call_value.num_op_points;
1508 	if (field->map[0]->points[0].level != 0.0)
1509 	    {
1510 	    num_alloced_pts++;
1511 	    }
1512 	if (field->map[0]->points[call_value.num_op_points-1].level < 1.0)
1513 	     {
1514 	    num_alloced_pts++;
1515 	    }
1516 	call_value.op_data =
1517 		(double *)XtMalloc(num_alloced_pts*sizeof(double));
1518 	call_value.op_values =
1519 		(double *)XtMalloc(num_alloced_pts*sizeof(double));
1520 	if (field->map[0]->points[0].level != 0.0)
1521 	    {
1522 	    call_value.op_data[0] = cmew->color_map_editor.value_minimum;
1523 	    call_value.op_values[0] = field->map[0]->line[0].values[0];
1524 	    index = 1;
1525 	    }
1526 	else
1527 	    {
1528 	    index = 0;
1529 	    }
1530 	for (i = 0; i < call_value.num_op_points; i++)
1531 	    {
1532 	    call_value.op_data[index] = cmew->color_map_editor.value_minimum +
1533 		field->map[0]->points[i].level*
1534 		(cmew->color_map_editor.value_maximum -
1535 		 cmew->color_map_editor.value_minimum);
1536 	    call_value.op_values[index] =
1537 		 cmew->color_map_editor.g.field[3]->map[0]->points[i].value;
1538 	    index++;
1539 	    }
1540 	if (field->map[0]->points[call_value.num_op_points-1].level < 1.0)
1541 	    {
1542 	    call_value.op_data[index] = cmew->color_map_editor.value_maximum;
1543 	    call_value.op_values[index] =
1544 		 field->map[0]->line[0].values[(int)(NUM_LEVELS-1)];
1545 	    }
1546 	call_value.num_op_points = num_alloced_pts;
1547  }
1548 #endif
1549 	/*minimum = cmew->color_map_editor.value_minimum;*/
1550 	/*range = (cmew->color_map_editor.value_maximum -*/
1551         /*	   cmew->color_map_editor.value_minimum);*/
1552 
1553 	/* Hue field */
1554 	map = cmew->color_map_editor.g.field[HUE]->map[0];
1555 	index = map->num_points;
1556 	call_value.num_hue_points = index;
1557 	call_value.hue_values = (double *)XtMalloc(2*index*sizeof(double));
1558 
1559 	for (i = 0; i < index ; i++)
1560 	{
1561 #ifdef Comment
1562 	    call_value.hue_values[i] =  minimum + map->points[i].level*range;
1563 #else
1564 	    call_value.hue_values[i] =  map->points[i].level;
1565 #endif
1566 	    call_value.hue_values[i + index] = map->points[i].value;
1567 	}
1568 
1569 	/* Saturation field */
1570 	map = cmew->color_map_editor.g.field[SATURATION]->map[0];
1571 	index = map->num_points;
1572 	call_value.num_sat_points = index;
1573 	call_value.sat_values = (double *)XtMalloc(2*index*sizeof(double));
1574 	for (i = 0; i < index ; i++)
1575 	{
1576 #ifdef Comment
1577 	    call_value.sat_values[i] =  minimum + map->points[i].level*range;
1578 #else
1579 	    call_value.sat_values[i] =  map->points[i].level;
1580 #endif
1581 	    call_value.sat_values[index +i] = map->points[i].value;
1582 	}
1583 
1584 	/* Value field */
1585 	map = cmew->color_map_editor.g.field[VALUE]->map[0];
1586 	index = map->num_points;
1587 	call_value.num_val_points = index;
1588 	call_value.val_values = (double *)XtMalloc(2*index*sizeof(double));
1589 	for (i = 0; i < index ; i++)
1590 	{
1591 #ifdef Comment
1592 	    call_value.val_values[i] =  minimum + map->points[i].level*range;
1593 #else
1594 	    call_value.val_values[i] =  map->points[i].level;
1595 #endif
1596 	    call_value.val_values[index +i] = map->points[i].value;
1597 	}
1598 
1599 	/* Opacity field */
1600 	map = cmew->color_map_editor.g.field[OPACITY]->map[0];
1601 	index = map->num_points;
1602 	call_value.num_op_points = index;
1603 	call_value.op_values = (double *)XtMalloc(2*index*sizeof(double));
1604 	for (i = 0; i < index ; i++)
1605 	{
1606 #ifdef Comment
1607 	    call_value.op_values[i] = minimum + map->points[i].level*range;
1608 #else
1609 	    call_value.op_values[i] =  map->points[i].level;
1610 #endif
1611 	    call_value.op_values[i + index ] = map->points[i].value;
1612 	}
1613 
1614 	XtCallCallbacks((Widget)cmew, XmNactivateCallback, &call_value);
1615 
1616 	if (call_value.op_values)
1617 		XtFree((char*)call_value.op_values);
1618 	if (call_value.val_values)
1619 		XtFree((char*)call_value.val_values);
1620 	if (call_value.sat_values)
1621 		XtFree((char*)call_value.sat_values);
1622 	if (call_value.hue_values)
1623 		XtFree((char*)call_value.hue_values);
1624 }
LoadHardCodeDefaults(XmColorMapEditorWidget cmew,Boolean init)1625 void LoadHardCodeDefaults(XmColorMapEditorWidget cmew, Boolean init)
1626 {
1627 int i;
1628 ControlPoint cp_ptr;
1629 int n;
1630 Arg wargs[12];
1631 
1632   if (!init)
1633     {
1634     for (i=0; i<4; i++)
1635 	{
1636 	DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1637 		cmew->color_map_editor.g.field[i]->map[0]->erase_gc);
1638 	DrawLine(cmew->color_map_editor.g.field[i]->map[0]->line,
1639 		cmew->color_map_editor.g.field[i]->map[0]->line->erase_gc);
1640 	RemoveAllControlPoints(cmew->color_map_editor.g.field[i]);
1641 	}
1642     }
1643   cmew->color_map_editor.value_minimum = 0.0;
1644   cmew->color_map_editor.value_maximum = 100.0;
1645   if (!init)
1646     {
1647     n=0;
1648     DoubleSetArg(wargs[n], XmNdValue, cmew->color_map_editor.value_minimum);n++;
1649     XtSetValues((Widget)cmew->color_map_editor.min_num, wargs, n);
1650     n=0;
1651     DoubleSetArg(wargs[n], XmNdValue, cmew->color_map_editor.value_maximum);n++;
1652     XtSetValues((Widget)cmew->color_map_editor.max_num, wargs, n);
1653     }
1654 
1655   /* Add the 2 Hue Control Points */
1656   cp_ptr.level = 0.0;
1657   cp_ptr.value = 0.6666667;
1658   cp_ptr.wrap_around = 0;
1659   cp_ptr.x = 0;
1660   cp_ptr.y = 0;
1661   AddControlPoint( cmew->color_map_editor.g.field[0]->map[0],
1662             cp_ptr.level, cp_ptr.value, True );
1663 
1664   cp_ptr.level = 1.0;
1665   cp_ptr.value = 0.0;
1666   cp_ptr.wrap_around = 0;
1667   cp_ptr.x = 0;
1668   cp_ptr.y = 0;
1669   AddControlPoint( cmew->color_map_editor.g.field[0]->map[0],
1670             cp_ptr.level, cp_ptr.value, True );
1671 
1672   SetArrayValues(cmew->color_map_editor.g.field[0]->map[0],
1673    cmew->color_map_editor.g.field[0]->line[0]);
1674   SetLineCoords(cmew->color_map_editor.g.field[0]->line[0]);
1675 
1676   /* Add the Saturation ControlPoints */
1677   cp_ptr.level = 0.0;
1678   cp_ptr.value = 1.0;
1679   cp_ptr.wrap_around = 0;
1680   cp_ptr.x = 0;
1681   cp_ptr.y = 0;
1682   AddControlPoint( cmew->color_map_editor.g.field[1]->map[0],
1683             cp_ptr.level, cp_ptr.value, True );
1684 
1685   cp_ptr.level = 1.0;
1686   cp_ptr.value = 1.0;
1687   cp_ptr.wrap_around = 0;
1688   cp_ptr.x = 0;
1689   cp_ptr.y = 0;
1690   AddControlPoint( cmew->color_map_editor.g.field[1]->map[0],
1691             cp_ptr.level, cp_ptr.value, True );
1692 
1693   SetArrayValues(cmew->color_map_editor.g.field[1]->map[0],
1694 	    cmew->color_map_editor.g.field[1]->line[0]);
1695   SetLineCoords(cmew->color_map_editor.g.field[1]->line[0]);
1696 
1697   /* Add the Value ControlPoints */
1698   cp_ptr.level = 0.0;
1699   cp_ptr.value = 1.0;
1700   cp_ptr.wrap_around = 0;
1701   cp_ptr.x = 0;
1702   cp_ptr.y = 0;
1703   AddControlPoint( cmew->color_map_editor.g.field[2]->map[0],
1704             cp_ptr.level, cp_ptr.value, True );
1705 
1706   cp_ptr.level = 1.0;
1707   cp_ptr.value = 1.0;
1708   cp_ptr.wrap_around = 0;
1709   cp_ptr.x = 0;
1710   cp_ptr.y = 0;
1711   AddControlPoint( cmew->color_map_editor.g.field[2]->map[0],
1712             cp_ptr.level, cp_ptr.value, True );
1713 
1714   SetArrayValues(cmew->color_map_editor.g.field[2]->map[0],
1715 	    cmew->color_map_editor.g.field[2]->line[0]);
1716   SetLineCoords(cmew->color_map_editor.g.field[2]->line[0]);
1717 
1718 
1719   /* Add the Opacity ControlPoints */
1720   cp_ptr.level = 1.0;
1721   cp_ptr.value = 1.0;
1722   cp_ptr.wrap_around = 0;
1723   cp_ptr.x = 0;
1724   cp_ptr.y = 0;
1725   AddControlPoint( cmew->color_map_editor.g.field[3]->map[0],
1726             cp_ptr.level, cp_ptr.value, True );
1727 
1728   cp_ptr.level = 0.0;
1729   cp_ptr.value = 1.0;
1730   cp_ptr.wrap_around = 0;
1731   cp_ptr.x = 0;
1732   cp_ptr.y = 0;
1733   AddControlPoint( cmew->color_map_editor.g.field[3]->map[0],
1734             cp_ptr.level, cp_ptr.value, True );
1735 
1736   SetArrayValues(cmew->color_map_editor.g.field[3]->map[0],
1737 	    cmew->color_map_editor.g.field[3]->line[0]);
1738   SetLineCoords(cmew->color_map_editor.g.field[3]->line[0]);
1739 
1740   for (i = 0; i < 4; i++)
1741     {
1742     if (!init)
1743       {
1744       DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1745 		cmew->color_map_editor.g.field[i]->map[0]->gc);
1746       DrawLine(cmew->color_map_editor.g.field[i]->line[0],
1747 		cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1748       cmew->color_map_editor.g.field[i]->user_callback(cmew->color_map_editor.g.field[i]);
1749       }
1750     }
1751 }
1752 
LoadColormapFromFile(char * filename,XmColorMapEditorWidget cmew,Boolean init)1753 void LoadColormapFromFile(char *filename, XmColorMapEditorWidget cmew,
1754 	Boolean init)
1755 {
1756 int i,j;
1757 ControlPoint cp_ptr;
1758 FILE *fp;
1759 int num_points, n;
1760 char *message;
1761 Arg wargs[12];
1762 double min, max;
1763 
1764   if ( (fp = fopen(filename, "r")) == NULL)
1765     {
1766     message = XtMalloc(strlen(filename) + 64);
1767     strcpy(message, "Cannot open color map file \"");
1768     strcat(message, filename);
1769     strcat(message, "\".");
1770     XtWarning(message);
1771     XtFree(message);
1772 
1773     LoadHardCodeDefaults(cmew, init);
1774     return;
1775     }
1776 
1777   if (!init)
1778     {
1779     for (i=0; i<4; i++)
1780       {
1781       DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1782 		cmew->color_map_editor.g.field[i]->map[0]->erase_gc);
1783       DrawLine(cmew->color_map_editor.g.field[i]->map[0]->line,
1784 		cmew->color_map_editor.g.field[i]->map[0]->line->erase_gc);
1785       RemoveAllControlPoints(cmew->color_map_editor.g.field[i]);
1786       SetArrayValues(cmew->color_map_editor.g.field[i]->map[0],
1787           cmew->color_map_editor.g.field[i]->line[0]);
1788       SetLineCoords(cmew->color_map_editor.g.field[i]->line[0]);
1789       DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1790 		cmew->color_map_editor.g.field[i]->map[0]->gc);
1791       DrawLine(cmew->color_map_editor.g.field[i]->line[0],
1792 		cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1793       }
1794     }
1795   if ( fscanf(fp,"%lg",&min) < 0 )
1796     {
1797     message = XtMalloc(strlen(filename) + 64);
1798     strcpy(message, "Error occurred while reading color map file \"");
1799     strcat(message, filename);
1800     strcat(message, "\".");
1801     XtWarning(message);
1802     XtFree(message);
1803 
1804     LoadHardCodeDefaults(cmew, init);
1805     return;
1806     }
1807   if ( fscanf(fp,"%lg",&max) < 0 )
1808     {
1809     message = XtMalloc(strlen(filename) + 64);
1810     strcpy(message, "Error occurred while reading color map file \"");
1811     strcat(message, filename);
1812     strcat(message, "\".");
1813     XtWarning(message);
1814     XtFree(message);
1815 
1816     LoadHardCodeDefaults(cmew, init);
1817     return;
1818     }
1819   if (!init)
1820     {
1821     if(cmew->color_map_editor.min_editable)
1822 	{
1823 	cmew->color_map_editor.value_minimum = min;
1824 	n=0;
1825 	DoubleSetArg(wargs[n], XmNdValue, min);n++;
1826 	XtSetValues((Widget)cmew->color_map_editor.min_num, wargs, n);
1827 	}
1828     if(cmew->color_map_editor.max_editable)
1829 	{
1830 	cmew->color_map_editor.value_maximum = max;
1831 	n=0;
1832 	DoubleSetArg(wargs[n], XmNdValue, max);n++;
1833 	XtSetValues((Widget)cmew->color_map_editor.max_num, wargs, n);
1834 	}
1835     }
1836 
1837   for (i=0; i<3; i++)				/* for all three fields */
1838     {
1839     if(!init)
1840       {
1841           DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1842 		cmew->color_map_editor.g.field[i]->map[0]->gc);
1843           DrawLine(cmew->color_map_editor.g.field[i]->map[0]->line,
1844 		cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1845       }
1846 
1847     if ( fscanf(fp,"%d",&num_points) < 0 )
1848 	{
1849 	message = XtMalloc(strlen(filename) + 64);
1850 	strcpy(message, "Error occurred while reading color map file \"");
1851 	strcat(message, filename);
1852 	strcat(message, "\".");
1853 	XtWarning(message);
1854 	XtFree(message);
1855 
1856 	LoadHardCodeDefaults(cmew, init);
1857 	return;
1858 	}
1859     for (j=0;j < num_points; j++)
1860   	{
1861 	if ( fscanf(fp,"%lg",&(cp_ptr.level)) < 0 )
1862 	    {
1863 	    message = XtMalloc(strlen(filename) + 64);
1864 	    strcpy(message, "Error occurred while reading color map file \"");
1865 	    strcat(message, filename);
1866 	    strcat(message, "\".");
1867 	    XtWarning(message);
1868 	    XtFree(message);
1869 
1870 	    LoadHardCodeDefaults(cmew, init);
1871 	    return;
1872 	    }
1873 	if ( fscanf(fp,"%lg",&(cp_ptr.value)) < 0 )
1874 	    {
1875 	    message = XtMalloc(strlen(filename) + 64);
1876 	    strcpy(message, "Error occurred while reading color map file \"");
1877 	    strcat(message, filename);
1878 	    strcat(message, "\".");
1879 	    XtWarning(message);
1880 	    XtFree(message);
1881 
1882 	    LoadHardCodeDefaults(cmew, init);
1883 	    return;
1884 	    }
1885 	if ( fscanf(fp,"%d",&(cp_ptr.wrap_around)) < 0 )
1886 	    {
1887 	    message = XtMalloc(strlen(filename) + 64);
1888 	    strcpy(message, "Error occurred while reading color map file \"");
1889 	    strcat(message, filename);
1890 	    strcat(message, "\".");
1891 	    XtWarning(message);
1892 	    XtFree(message);
1893 
1894 	    LoadHardCodeDefaults(cmew, init);
1895 	    return;
1896 	    }
1897 	if ( fscanf(fp,"%d",&(cp_ptr.x)) < 0 )
1898 	    {
1899 	    message = XtMalloc(strlen(filename) + 64);
1900 	    strcpy(message, "Error occurred while reading color map file \"");
1901 	    strcat(message, filename);
1902 	    strcat(message, "\".");
1903 	    XtWarning(message);
1904 	    XtFree(message);
1905 
1906 	    LoadHardCodeDefaults(cmew, init);
1907 	    return;
1908 	    }
1909 	if ( fscanf(fp,"%d",&(cp_ptr.y)) < 0 )
1910 	    {
1911 	    message = XtMalloc(strlen(filename) + 64);
1912 	    strcpy(message, "Error occurred while reading color map file \"");
1913 	    strcat(message, filename);
1914 	    strcat(message, "\".");
1915 	    XtWarning(message);
1916 	    XtFree(message);
1917 
1918 	    LoadHardCodeDefaults(cmew, init);
1919 	    return;
1920 	    }
1921         AddControlPoint( cmew->color_map_editor.g.field[i]->map[0],
1922             cp_ptr.level, cp_ptr.value, True );
1923 	SetArrayValues(cmew->color_map_editor.g.field[i]->map[0],
1924 	    cmew->color_map_editor.g.field[i]->line[0]);
1925 	SetLineCoords(cmew->color_map_editor.g.field[i]->line[0]);
1926         }
1927       if (!init)
1928 	{
1929         DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1930 		cmew->color_map_editor.g.field[i]->map[0]->gc);
1931         DrawLine(cmew->color_map_editor.g.field[i]->line[0],
1932 		cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1933         cmew->color_map_editor.g.field[i]->user_callback(cmew->color_map_editor.g.field[i]);
1934 	}
1935     }
1936 
1937     /* Handle Opacity separately for backwards comaptabilty with old
1938        colormap files */
1939     i = 3;
1940     if(!init)
1941       {
1942           DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1943 		cmew->color_map_editor.g.field[i]->map[0]->gc);
1944           DrawLine(cmew->color_map_editor.g.field[i]->map[0]->line,
1945 		cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1946       }
1947 
1948     if ( fscanf(fp,"%d",&num_points) < 0 )
1949 	{
1950  	num_points = 1;
1951 	cp_ptr.level = 1.0;
1952 	cp_ptr.value = 1.0;
1953 	AddControlPoint( cmew->color_map_editor.g.field[i]->map[0],
1954             	cp_ptr.level, cp_ptr.value, True );
1955 	SetArrayValues(cmew->color_map_editor.g.field[i]->map[0],
1956 	   	cmew->color_map_editor.g.field[i]->line[0]);
1957 	SetLineCoords(cmew->color_map_editor.g.field[i]->line[0]);
1958 	}
1959     else
1960 	{
1961 	for (j=0;j < num_points; j++)
1962   	    {
1963 	    if ( fscanf(fp,"%lg",&(cp_ptr.level)) < 0 )
1964 		{
1965 		message = XtMalloc(strlen(filename) + 64);
1966 		strcpy(message,
1967 		       "Error occurred while reading color map file \"");
1968 		strcat(message, filename);
1969 		strcat(message, "\".");
1970 		XtWarning(message);
1971 		XtFree(message);
1972 
1973 		LoadHardCodeDefaults(cmew, init);
1974 		return;
1975 		}
1976 	    if ( fscanf(fp,"%lg",&(cp_ptr.value)) < 0 )
1977 		{
1978 		message = XtMalloc(strlen(filename) + 64);
1979 		strcpy(message,
1980 		       "Error occurred while reading color map file \"");
1981 		strcat(message, filename);
1982 		strcat(message, "\".");
1983 		XtWarning(message);
1984 		XtFree(message);
1985 
1986 		LoadHardCodeDefaults(cmew, init);
1987 		return;
1988 		}
1989 	    if ( fscanf(fp,"%d",&(cp_ptr.wrap_around)) < 0 )
1990 		{
1991 		message = XtMalloc(strlen(filename) + 64);
1992 		strcpy(message,
1993 		       "Error occurred while reading color map file \"");
1994 		strcat(message, filename);
1995 		strcat(message, "\".");
1996 		XtWarning(message);
1997 		XtFree(message);
1998 
1999 		LoadHardCodeDefaults(cmew, init);
2000 		return;
2001 		}
2002 	    if ( fscanf(fp,"%d",&(cp_ptr.x)) < 0 )
2003 		{
2004 		message = XtMalloc(strlen(filename) + 64);
2005 		strcpy(message,
2006 		       "Error occurred while reading color map file \"");
2007 		strcat(message, filename);
2008 		strcat(message, "\".");
2009 		XtWarning(message);
2010 		XtFree(message);
2011 
2012 		LoadHardCodeDefaults(cmew, init);
2013 		return;
2014 		}
2015 	    if ( fscanf(fp,"%d",&(cp_ptr.y)) < 0 )
2016 		{
2017 		message = XtMalloc(strlen(filename) + 64);
2018 		strcpy(message,
2019 		       "Error occurred while reading color map file \"");
2020 		strcat(message, filename);
2021 		strcat(message, "\".");
2022 		XtWarning(message);
2023 		XtFree(message);
2024 
2025 		LoadHardCodeDefaults(cmew, init);
2026 		return;
2027 		}
2028 	    AddControlPoint( cmew->color_map_editor.g.field[i]->map[0],
2029             	cp_ptr.level, cp_ptr.value, True );
2030 	    SetArrayValues(cmew->color_map_editor.g.field[i]->map[0],
2031 	   	cmew->color_map_editor.g.field[i]->line[0]);
2032 	    SetLineCoords(cmew->color_map_editor.g.field[i]->line[0]);
2033             }
2034 	}
2035       if (!init)
2036 	{
2037         DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
2038 		cmew->color_map_editor.g.field[i]->map[0]->gc);
2039         DrawLine(cmew->color_map_editor.g.field[i]->line[0],
2040 		cmew->color_map_editor.g.field[i]->map[0]->line->gc);
2041         cmew->color_map_editor.g.field[i]->user_callback(cmew->color_map_editor.g.field[i]);
2042 	}
2043   if (fclose(fp) != 0)
2044       {
2045       message = XtMalloc(strlen(filename) + 64);
2046       strcpy(message,
2047 	     "Cannot close color map file \"");
2048       strcat(message, filename);
2049       strcat(message, "\".");
2050       XtWarning(message);
2051       XtFree(message);
2052 
2053       LoadHardCodeDefaults(cmew, init);
2054       return;
2055       }
2056 }
XmColorMapEditorLoad(Widget cmew,double min,double max,int nhues,double * hues,int nsats,double * sats,int nvals,double * vals,int nopat,double * opat)2057 void XmColorMapEditorLoad(Widget cmew, double min, double max,
2058 			  int nhues, double *hues,
2059 			  int nsats, double *sats,
2060 			  int nvals, double *vals,
2061 			  int nopat, double *opat)
2062 {
2063 int i;
2064 double norm, range=0;
2065 Boolean skip_normalize;
2066 #ifdef PASSDOUBLEVALUE
2067 XtArgVal dx_l;
2068 #endif
2069 
2070     XmColorMapEditorWidget w = (XmColorMapEditorWidget)cmew;
2071 
2072     /* Erase the old Control points */
2073     if (XtIsRealized((Widget)w))
2074     {
2075 	for (i=0; i<4; i++)
2076 	{
2077 	    DrawControlBoxes(w->color_map_editor.g.field[i]->map[0],
2078 		    w->color_map_editor.g.field[i]->map[0]->erase_gc);
2079 	    DrawLine(w->color_map_editor.g.field[i]->map[0]->line,
2080 		    w->color_map_editor.g.field[i]->map[0]->line->erase_gc);
2081 	    RemoveAllControlPoints(w->color_map_editor.g.field[i]);
2082 	    SetArrayValues(w->color_map_editor.g.field[i]->map[0],
2083 	      w->color_map_editor.g.field[i]->line[0]);
2084 	    SetLineCoords(w->color_map_editor.g.field[i]->line[0]);
2085 	    DrawControlBoxes(w->color_map_editor.g.field[i]->map[0],
2086 		    w->color_map_editor.g.field[i]->map[0]->gc);
2087 	    DrawLine(w->color_map_editor.g.field[i]->line[0],
2088 		    w->color_map_editor.g.field[i]->map[0]->line->gc);
2089 	}
2090     }
2091 
2092     if(w->color_map_editor.min_editable)
2093     {
2094 	w->color_map_editor.value_minimum = min;
2095 	XtVaSetValues((Widget)w->color_map_editor.min_num,
2096 		XmNdValue, DoubleVal(min, dx_l), NULL);
2097     }
2098     if(w->color_map_editor.max_editable)
2099     {
2100 	w->color_map_editor.value_maximum = max;
2101 	XtVaSetValues((Widget)w->color_map_editor.max_num,
2102 		XmNdValue, DoubleVal(max, dx_l), NULL);
2103     }
2104 
2105     if(XtIsRealized((Widget)w))
2106 	for(i = 0; i < 4; i++)
2107 	    RemoveAllControlPoints(w->color_map_editor.g.field[i]);
2108 
2109 #if Comment
2110     if (min == max) {
2111 	skip_normalize = True;
2112     } else {
2113 	skip_normalize = False;
2114         range = max - min;
2115     }
2116 #else
2117     skip_normalize = True;
2118 #endif
2119 
2120     for(i = 0; i < nhues; i++)
2121     {
2122 	norm = (skip_normalize ? *hues : (*hues - min) / range) ;
2123 	hues++;
2124 	AddControlPoint(w->color_map_editor.g.field[HUE]->map[0],
2125 			norm,
2126 			*(hues++),
2127 			True );
2128     }
2129     for(i = 0; i < nsats; i++)
2130     {
2131 	norm = (skip_normalize ? *sats : (*sats - min) / range) ;
2132 	sats++;
2133 	AddControlPoint(w->color_map_editor.g.field[SATURATION]->map[0],
2134 			norm,
2135 			*(sats++),
2136 			True );
2137     }
2138     for(i = 0; i < nvals; i++)
2139     {
2140 	norm = (skip_normalize ? *vals : (*vals - min) / range) ;
2141 	vals++;
2142 	AddControlPoint(w->color_map_editor.g.field[VALUE]->map[0],
2143 			norm,
2144 			*(vals++),
2145 			True );
2146     }
2147     for(i = 0; i < nopat; i++)
2148     {
2149 	norm = (skip_normalize ? *opat : (*opat - min) / range) ;
2150 	opat++;
2151 	AddControlPoint(w->color_map_editor.g.field[OPACITY]->map[0],
2152 			norm,
2153 			*(opat++),
2154 			True );
2155     }
2156 
2157     if(XtIsRealized((Widget)w))
2158     {
2159 	for(i = 0; i < 4; i++)
2160 	{
2161 	    SetArrayValues(w->color_map_editor.g.field[i]->map[0],
2162 		w->color_map_editor.g.field[i]->line[0]);
2163 	    SetLineCoords(w->color_map_editor.g.field[i]->line[0]);
2164 
2165 	    DrawControlBoxes(w->color_map_editor.g.field[i]->map[0],
2166 		    w->color_map_editor.g.field[i]->map[0]->gc);
2167 	    DrawLine(w->color_map_editor.g.field[i]->line[0],
2168 		    w->color_map_editor.g.field[i]->map[0]->line->gc);
2169 	}
2170 	w->color_map_editor.g.field[0]->user_callback(w->color_map_editor.g.field[0]);
2171     }
2172 }
2173 
RecalculateControlPointLevels(XmColorMapEditorWidget cmew)2174 void RecalculateControlPointLevels(XmColorMapEditorWidget cmew)
2175 {
2176 int i, j;
2177 
2178     for(i = 0; i < 4; i++)
2179 	{
2180 	for (j = 0; j < cmew->color_map_editor.g.field[i]->map[0]->num_points;
2181 	     			j++)
2182 	    {
2183 	    MoveControlPoint(
2184 			cmew->color_map_editor.g.field[i]->map[0],
2185 			j,
2186 			cmew->color_map_editor.g.field[i]->map[0]->points[j].x,
2187 			cmew->color_map_editor.g.field[i]->map[0]->points[j].y);
2188 	    }
2189 	}
2190 }
CMESawToothWave(Widget w,int nsteps,Boolean start_on_left,Boolean use_selected)2191 void CMESawToothWave(Widget w, int nsteps, Boolean start_on_left,
2192 		     Boolean use_selected)
2193 {
2194 int 			i;
2195 double 			level;
2196 double 			value;
2197 double 			tmp_value;
2198 double 			level_inc;
2199 XmColorMapEditorWidget 	cmew = (XmColorMapEditorWidget)w;
2200 ControlMap 		*map;
2201 double 			real_min_level;
2202 double 			real_max_level;
2203 int			num_selected;
2204 int			pt_index1=0;
2205 int			pt_index2=0;
2206 int			field;
2207 double			min_value;
2208 double			max_value;
2209 double			min_level;
2210 double			max_level;
2211 
2212     PushUndoPoints(cmew);
2213     for(field = 0; field < 4; field++)
2214     {
2215 	if(!cmew->color_map_editor.g.field[field]->map[0]->toggle_on) continue;
2216 	map = cmew->color_map_editor.g.field[field]->map[0];
2217 	num_selected = 0;
2218 	for (i = 0; i < map->num_points; i++)
2219 	    if(map->points[i].multi_point_grab)
2220 	    {
2221 		num_selected++;
2222 		if(num_selected == 1)
2223 		    pt_index1 = i;
2224 		else if(num_selected > 1)
2225 		    pt_index2 = i;
2226 	    }
2227 	if(use_selected && (num_selected < 2) )
2228 	{
2229 	    XtWarning("There must be at least 2 selected Control Points");
2230 	    return;
2231 	}
2232 
2233 	/*
2234 	 * Erase the control points and lines
2235 	 */
2236 	DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2237 		cmew->color_map_editor.g.field[field]->map[0]->erase_gc);
2238 	DrawLine(cmew->color_map_editor.g.field[field]->map[0]->line,
2239 		cmew->color_map_editor.g.field[field]->map[0]->line->erase_gc);
2240 
2241 	if(use_selected)
2242 	{
2243 	    min_level = map->points[pt_index1].level;
2244 	    min_value = map->points[pt_index1].value;
2245 	    max_level = map->points[pt_index2].level;
2246 	    max_value = map->points[pt_index2].value;
2247 	}
2248 	else
2249 	{
2250 	    min_level = 0.0;
2251 	    max_level = 1.0;
2252 	    min_value = 0.0;
2253 	    if(field == 0)
2254 		max_value = 0.66666;
2255 	    else
2256 		max_value = 1.0;
2257 	}
2258 	real_min_level = MIN(min_level, max_level);
2259 	real_max_level = MAX(min_level, max_level);
2260 	if(!use_selected)
2261 	{
2262 	    RemoveAllControlPoints(map->field);
2263 	}
2264 	else
2265 	{
2266 	    for (i = map->num_points - 1; i >= 0 ; i--)
2267 	    {
2268 		if ((map->points[i].level <= real_max_level) &&
2269 		    (map->points[i].level >= real_min_level) )
2270 		{
2271 		    if( (i >= pt_index1) && (i <= pt_index2) )
2272 			RemoveControlPoint(map, i);
2273 		}
2274 	    }
2275 	}
2276 
2277 	level_inc = (max_level - min_level)/(nsteps-1);
2278 
2279 	/*
2280 	 * Insure that the min_value < max_value
2281 	 */
2282 	if(min_value > max_value)
2283 	{
2284 	    tmp_value = min_value;
2285 	    min_value = max_value;
2286 	    max_value = tmp_value;
2287 	}
2288 
2289 	for(i = 0; i < nsteps; i++)
2290 	    {
2291 	    level = min_level + (i * level_inc);
2292 	    if(start_on_left)
2293 		value = min_value;
2294 	    else
2295 		value = max_value;
2296 	    AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2297 		level, value, True );
2298 	    if(start_on_left)
2299 		value = max_value;
2300 	    else
2301 		value = min_value;
2302 	    AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2303 		level, value, True );
2304 	    }
2305 	SetArrayValues(cmew->color_map_editor.g.field[field]->map[0],
2306 	    cmew->color_map_editor.g.field[field]->line[0]);
2307 	SetLineCoords(cmew->color_map_editor.g.field[field]->line[0]);
2308 	DeselectAllPoints(cmew->color_map_editor.g.field[field]->map[0]);
2309 	DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2310 		cmew->color_map_editor.g.field[field]->map[0]->gc);
2311 	DrawLine(cmew->color_map_editor.g.field[field]->line[0],
2312 		cmew->color_map_editor.g.field[field]->map[0]->line->gc);
2313     cmew->color_map_editor.g.field[field]->user_callback(cmew->color_map_editor.g.field[field]);
2314     }
2315     if(cmew->color_map_editor.g.field[0]->map[0]->toggle_on ||
2316        cmew->color_map_editor.g.field[1]->map[0]->toggle_on ||
2317        cmew->color_map_editor.g.field[2]->map[0]->toggle_on ||
2318        cmew->color_map_editor.g.field[3]->map[0]->toggle_on)
2319 	CallActivateCallback(cmew, XmCR_MODIFIED);
2320     PrintAllControlPoints(cmew);
2321 }
2322 
CMESquareWave(Widget w,int nsteps,Boolean start_on_left,Boolean use_selected)2323 void CMESquareWave(Widget w, int nsteps, Boolean start_on_left,
2324 		   Boolean use_selected)
2325 {
2326 int 			i;
2327 double 			level;
2328 double 			value;
2329 double 			tmp_value;
2330 double 			level_inc;
2331 XmColorMapEditorWidget	cmew = (XmColorMapEditorWidget)w;
2332 ControlMap 		*map=NULL;
2333 double 			real_min_level=0;
2334 double 			real_max_level=0;
2335 int			num_selected;
2336 int			pt_index1=0;
2337 int			pt_index2=0;
2338 int			field;
2339 double			min_value=0;
2340 double			max_value=0;
2341 double			min_level=0;
2342 double			max_level=0;
2343 
2344     PushUndoPoints(cmew);
2345     for(field = 0; field < 4; field++)
2346     {
2347 	if(!cmew->color_map_editor.g.field[field]->map[0]->toggle_on) continue;
2348 	map = cmew->color_map_editor.g.field[field]->map[0];
2349 	num_selected = 0;
2350 	for (i = 0; i < map->num_points; i++)
2351 	    if(map->points[i].multi_point_grab)
2352 	    {
2353 		num_selected++;
2354 		if(num_selected == 1)
2355 		    pt_index1 = i;
2356 		else if(num_selected > 1)
2357 		    pt_index2 = i;
2358 	    }
2359 	if(use_selected && (num_selected < 2) )
2360 	{
2361 	    XtWarning("There must be at least 2 selected Control Points");
2362 	    return;
2363 	}
2364 
2365 	if(use_selected)
2366 	{
2367 	    min_level = map->points[pt_index1].level;
2368 	    min_value = map->points[pt_index1].value;
2369 	    max_level = map->points[pt_index2].level;
2370 	    max_value = map->points[pt_index2].value;
2371 	}
2372 	else
2373 	{
2374 	    min_level = 0.0;
2375 	    max_level = 1.0;
2376 	    min_value = 0.0;
2377 	    if(field == 0)
2378 		max_value = 0.66666;
2379 	    else
2380 		max_value = 1.0;
2381 	}
2382 	real_min_level = MIN(min_level, max_level);
2383 	real_max_level = MAX(min_level, max_level);
2384 	break;
2385     }
2386     /*
2387      * Erase the control points and lines
2388      */
2389     DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2390 	    cmew->color_map_editor.g.field[field]->map[0]->erase_gc);
2391     DrawLine(cmew->color_map_editor.g.field[field]->map[0]->line,
2392 	    cmew->color_map_editor.g.field[field]->map[0]->line->erase_gc);
2393 
2394     if(!use_selected)
2395     {
2396 	RemoveAllControlPoints(map->field);
2397     }
2398     else
2399     {
2400 	for (i = map->num_points - 1; i >= 0 ; i--)
2401 	{
2402 	    if ((map->points[i].level <= real_max_level) &&
2403 		(map->points[i].level >= real_min_level) )
2404 	    {
2405 		if( (i >= pt_index1) && (i <= pt_index2) )
2406 		    RemoveControlPoint(map, i);
2407 	    }
2408 	}
2409     }
2410     level_inc = (max_level - min_level)/(nsteps-1);
2411 
2412     /*
2413      * Insure that the min_value < max_value
2414      */
2415     if(min_value > max_value)
2416     {
2417 	tmp_value = min_value;
2418 	min_value = max_value;
2419 	max_value = tmp_value;
2420     }
2421     if(start_on_left)
2422 	value = min_value;
2423     else
2424 	value = max_value;
2425     for(i = 0; i < nsteps; i++)
2426 	{
2427 	level = min_level + (i * level_inc);
2428 	AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2429 	    level, value, True );
2430 	if(value == min_value)
2431 	    {
2432 		value = max_value;
2433 	    }
2434 	else
2435 	    {
2436 		value = min_value;
2437 	    }
2438 	AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2439 	    level, value, True );
2440 	}
2441     SetArrayValues(cmew->color_map_editor.g.field[field]->map[0],
2442 	cmew->color_map_editor.g.field[field]->line[0]);
2443     SetLineCoords(cmew->color_map_editor.g.field[field]->line[0]);
2444     DeselectAllPoints(cmew->color_map_editor.g.field[field]->map[0]);
2445     DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2446 	    cmew->color_map_editor.g.field[field]->map[0]->gc);
2447     DrawLine(cmew->color_map_editor.g.field[field]->line[0],
2448 	    cmew->color_map_editor.g.field[field]->map[0]->line->gc);
2449     cmew->color_map_editor.g.field[field]->user_callback(cmew->color_map_editor.g.field[field]);
2450     if(cmew->color_map_editor.g.field[0]->map[0]->toggle_on ||
2451        cmew->color_map_editor.g.field[1]->map[0]->toggle_on ||
2452        cmew->color_map_editor.g.field[2]->map[0]->toggle_on ||
2453        cmew->color_map_editor.g.field[3]->map[0]->toggle_on)
2454 	CallActivateCallback(cmew, XmCR_MODIFIED);
2455     PrintAllControlPoints(cmew);
2456 }
2457 
CMEStep(Widget w,int nsteps,Boolean use_selected)2458 void CMEStep(Widget w, int nsteps, Boolean use_selected)
2459 {
2460 int 			i;
2461 double 			level;
2462 double 			value;
2463 double 			inc_level;
2464 double 			inc_value;
2465 XmColorMapEditorWidget	cmew = (XmColorMapEditorWidget)w;
2466 ControlMap 		*map;
2467 double 			real_min_level;
2468 double 			real_max_level;
2469 double 			real_min_value;
2470 double 			real_max_value;
2471 int			num_selected;
2472 int			pt_index1=0;
2473 int			pt_index2=0;
2474 int			field;
2475 double			min_value;
2476 double			max_value;
2477 double			min_level;
2478 double			max_level;
2479 
2480     PushUndoPoints(cmew);
2481     for(field = 0; field < 4; field++)
2482     {
2483 	if(!cmew->color_map_editor.g.field[field]->map[0]->toggle_on) continue;
2484 	map = cmew->color_map_editor.g.field[field]->map[0];
2485 	num_selected = 0;
2486 	for (i = 0; i < map->num_points; i++)
2487 	    if(map->points[i].multi_point_grab)
2488 	    {
2489 		num_selected++;
2490 		if(num_selected == 1)
2491 		    pt_index1 = i;
2492 		else if(num_selected > 1)
2493 		    pt_index2 = i;
2494 	    }
2495 
2496 	if( use_selected && (num_selected < 2) )
2497 	{
2498 	    XtWarning("There must be at least 2 selected Control Points");
2499 	    return;
2500 	}
2501 
2502 	/*
2503 	 * Erase the control points and lines
2504 	 */
2505 	DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2506 		cmew->color_map_editor.g.field[field]->map[0]->erase_gc);
2507 	DrawLine(cmew->color_map_editor.g.field[field]->map[0]->line,
2508 		cmew->color_map_editor.g.field[field]->map[0]->line->erase_gc);
2509 
2510 	if(use_selected)
2511 	{
2512 	    min_level = map->points[pt_index1].level;
2513 	    min_value = map->points[pt_index1].value;
2514 	    max_level = map->points[pt_index2].level;
2515 	    max_value = map->points[pt_index2].value;
2516 	}
2517 	else
2518 	{
2519 	    min_level = 0.0;
2520 	    max_level = 1.0;
2521 	    if(field == 0)
2522 	    {
2523 		min_value = 0.66666;
2524 		max_value = 0.0;
2525 	    }
2526 	    else
2527 	    {
2528 		min_value = 0.0;
2529 		max_value = 1.0;
2530 	    }
2531 	}
2532 	real_min_level = MIN(min_level, max_level);
2533 	real_max_level = MAX(min_level, max_level);
2534 	real_min_value = MIN(min_value, max_value);
2535 	real_max_value = MAX(min_value, max_value);
2536 	if(!use_selected)
2537 	{
2538 	    RemoveAllControlPoints(map->field);
2539 	}
2540 	else
2541 	{
2542 	    for (i = map->num_points - 1; i >= 0 ; i--)
2543 	    {
2544 		if ((map->points[i].level <= real_max_level) &&
2545 		    (map->points[i].level >= real_min_level) )
2546 		{
2547 		    if( (i >= pt_index1) && (i <= pt_index2) )
2548 			RemoveControlPoint(map, i);
2549 		}
2550 	    }
2551 	}
2552 
2553 	level = min_level;
2554 	value = min_value;
2555 	inc_level = (max_level - min_level)/(nsteps+1);
2556 	inc_value = (max_value - min_value)/nsteps;
2557 
2558 	/*
2559 	 * Add the first point
2560 	 */
2561 	AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2562 	    level, value, True );
2563 	level += inc_level;
2564 
2565 	for(i = 0; i < nsteps; i++)
2566 	{
2567 	    /*
2568 	     * Deal with rounding errors.
2569 	     */
2570 	    if(level > real_max_level) level = real_max_level;
2571 	    if(level < real_min_level) level = real_min_level;
2572 	    /*
2573 	     * If max_level < min_level, we have to reverse the order we add
2574 	     * the points in at each level, since a point is considered to be
2575 	     * "below" when added at the same level.
2576 	     */
2577 	    if(max_level < min_level)
2578 		value += inc_value;
2579 	    AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2580 		level, value, True );
2581 	    if(max_level < min_level)
2582 		value -= inc_value;
2583 	    else
2584 		value += inc_value;
2585 	    if(value > real_max_value) value = real_max_value;
2586 	    if(value < real_min_value) value = real_min_value;
2587 	    AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2588 		level, value, True );
2589 	    if(max_level < min_level)
2590 		value += inc_value;
2591 	    level += inc_level;
2592 	}
2593 	/*
2594 	 * Add the last point
2595 	 */
2596 	AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2597 	    max_level, value, False );
2598 
2599 	SetArrayValues(cmew->color_map_editor.g.field[field]->map[0],
2600 	    cmew->color_map_editor.g.field[field]->line[0]);
2601 	SetLineCoords(cmew->color_map_editor.g.field[field]->line[0]);
2602 	DeselectAllPoints(cmew->color_map_editor.g.field[field]->map[0]);
2603 	DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2604 		cmew->color_map_editor.g.field[field]->map[0]->gc);
2605 	DrawLine(cmew->color_map_editor.g.field[field]->line[0],
2606 		cmew->color_map_editor.g.field[field]->map[0]->line->gc);
2607 	cmew->color_map_editor.g.field[field]->user_callback(cmew->color_map_editor.g.field[field]);
2608     }
2609     if(cmew->color_map_editor.g.field[0]->map[0]->toggle_on ||
2610        cmew->color_map_editor.g.field[1]->map[0]->toggle_on ||
2611        cmew->color_map_editor.g.field[2]->map[0]->toggle_on ||
2612        cmew->color_map_editor.g.field[3]->map[0]->toggle_on)
2613 	CallActivateCallback(cmew, XmCR_MODIFIED);
2614     PrintAllControlPoints(cmew);
2615 }
PrintAllControlPoints(XmColorMapEditorWidget cmew)2616 void PrintAllControlPoints(XmColorMapEditorWidget cmew)
2617 {
2618 ControlMap *map;
2619 int        i;
2620 int        j;
2621 Dimension  width;
2622 Dimension  height;
2623 
2624 
2625     XtVaGetValues(cmew->color_map_editor.grid_w,
2626 	XmNwidth, &width,
2627 	XmNheight, &height,
2628 	NULL);
2629 
2630     XClearArea(XtDisplay(cmew),
2631 	       XtWindow(cmew->color_map_editor.grid_w),
2632 	       0, 0, width, height, False);
2633 
2634     if(cmew->color_map_editor.print_points == XmPRINT_NONE) return;
2635 
2636     for(i = 0; i < 4; i++)
2637     {
2638 	map = cmew->color_map_editor.g.field[i]->map[0];
2639 	if(!map->toggle_on) continue;
2640 	for(j = 0; j < map->num_points; j++)
2641 	{
2642 	    if(cmew->color_map_editor.print_points == XmPRINT_SELECTED)
2643 	    {
2644 		if( (map->points[j].multi_point_grab) ||
2645 		    (j == map->grabbed) )
2646 		{
2647 		    PrintControlPoint(map, j);
2648 		}
2649 	    }
2650 	    else if(cmew->color_map_editor.print_points == XmPRINT_ALL)
2651 	    {
2652 		PrintControlPoint(map, j);
2653 	    }
2654 	}
2655     }
2656 }
2657 
PrintControlPoint(ControlMap * map,int point_num)2658 void PrintControlPoint(ControlMap *map, int point_num)
2659 {
2660 int         direction;
2661 int         ascent;
2662 int         descent;
2663 XCharStruct overall;
2664 char	    string[256];
2665 XmColorMapEditorWidget cmew;
2666 Dimension   width;
2667 Position    x;
2668 Position    y;
2669 
2670     cmew = map->field->cmew;
2671     XtVaGetValues(cmew->color_map_editor.grid_w,
2672 	XmNwidth, &width,
2673 	NULL);
2674 
2675     sprintf(string, "%g", cmew->color_map_editor.value_minimum +
2676 	(cmew->color_map_editor.value_maximum -
2677 	 cmew->color_map_editor.value_minimum) *
2678 	 map->points[point_num].level);
2679 
2680     XTextExtents(cmew->color_map_editor.font, string, strlen(string),
2681 		&direction, &ascent, &descent, &overall);
2682     x = (width - overall.width) - 5;
2683     y = map->points[point_num].y;
2684     if( (y - (ascent + descent)) < 0)
2685     {
2686 	y = ascent + descent;
2687     }
2688     XDrawString(XtDisplay(cmew),
2689 		XtWindow(cmew->color_map_editor.grid_w),
2690 		cmew->color_map_editor.fontgc,
2691 		x,
2692 		y,
2693 		string, strlen(string));
2694 
2695 }
2696 
PointExists(ControlMap * map,double level,double value)2697 static Boolean PointExists(ControlMap *map, double level, double value)
2698 {
2699 int i;
2700 
2701     for(i = 0; i < map->num_points; i++)
2702     {
2703 	if( (map->points[i].level == level) &&
2704 	    (map->points[i].value == value) )
2705 	    return True;
2706     }
2707     return False;
2708 }
DeselectAllPoints(ControlMap * map)2709 static void DeselectAllPoints(ControlMap *map)
2710 {
2711 int i;
2712     for(i = 0; i < map->num_points; i++)
2713 	{
2714 	map->points[i].multi_point_grab = False;
2715 	}
2716     map->grabbed = -1;
2717 }
2718