1 
2 /*	$Id: tixGrSel.c,v 1.2 2004/03/28 02:44:56 hobbs Exp $	*/
3 
4 /*
5  * tixGrSel.c --
6  *
7  *	This module handles the selection
8  *
9  * Copyright (c) 1996, Expert Interface Technologies
10  *
11  * See the file "license.terms" for information on usage and redistribution
12  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13  *
14  */
15 
16 #include <tixPort.h>
17 #include <tixInt.h>
18 #include <tixDef.h>
19 #include <tixGrid.h>
20 
21 EXTERN TIX_DECLARE_SUBCMD(Tix_GrSelection);
22 static TIX_DECLARE_SUBCMD(Tix_GrSelIncludes);
23 static TIX_DECLARE_SUBCMD(Tix_GrSelModify);
24 
25 static int		Tix_GrSelIncludes _ANSI_ARGS_((ClientData clientData,
26 			    Tcl_Interp *interp, int argc, CONST84 char **argv));
27 static void		Tix_GrAdjustSelection _ANSI_ARGS_((
28 			    WidgetPtr wPtr, SelectBlock * sbPtr));
29 static void		Tix_GrMergeSelection _ANSI_ARGS_((
30 			    WidgetPtr wPtr, SelectBlock * sbPtr));
31 
32 int
Tix_GrSelection(clientData,interp,argc,argv)33 Tix_GrSelection(clientData, interp, argc, argv)
34     ClientData clientData;
35     Tcl_Interp *interp;		/* Current interpreter. */
36     int argc;			/* Number of arguments. */
37     CONST84 char **argv;	/* Argument strings. */
38 {
39     static Tix_SubCmdInfo subCmdInfo[] = {
40 	{TIX_DEFAULT_LEN, "adjust",   2, 4, Tix_GrSelModify,
41 	   "x1 y1 ?x2 y2?"},
42 	{TIX_DEFAULT_LEN, "clear",    2, 4, Tix_GrSelModify,
43 	   "x1 y1 ?x2 y2?"},
44 	{TIX_DEFAULT_LEN, "includes", 2, 4, Tix_GrSelIncludes,
45 	   "x1 y1 ?x2 y2?"},
46 	{TIX_DEFAULT_LEN, "set",      2, 4, Tix_GrSelModify,
47 	   "x1 y1 ?x2 y2?"},
48 	{TIX_DEFAULT_LEN, "toggle",   2, 4, Tix_GrSelModify,
49 	   "x1 y1 ?x2 y2?"},
50     };
51     static Tix_CmdInfo cmdInfo = {
52 	Tix_ArraySize(subCmdInfo), 1, TIX_VAR_ARGS, "?option? ?arg ...?",
53     };
54 
55     return Tix_HandleSubCmds(&cmdInfo, subCmdInfo, clientData,
56 	interp, argc+1, argv-1);
57 }
58 
59 static int
Tix_GrSelIncludes(clientData,interp,argc,argv)60 Tix_GrSelIncludes(clientData, interp, argc, argv)
61     ClientData clientData;
62     Tcl_Interp *interp;		/* Current interpreter. */
63     int argc;			/* Number of arguments. */
64     CONST84 char **argv;	/* Argument strings. */
65 {
66 #if 0
67     WidgetPtr wPtr = (WidgetPtr) clientData;
68 #endif
69     return TCL_OK;
70 }
71 
72 static void
Tix_GrMergeSelection(wPtr,sbPtr)73 Tix_GrMergeSelection(wPtr, sbPtr)
74     WidgetPtr wPtr;
75     SelectBlock * sbPtr;
76 {
77     Tix_ListIterator li;
78 
79     switch (sbPtr->type) {
80       case TIX_GR_SET:
81       case TIX_GR_CLEAR:
82 	if (sbPtr->range[0][0] == 0 &&
83 	    sbPtr->range[1][0] == 0 &&
84 	    sbPtr->range[0][1] == TIX_GR_MAX &&
85 	    sbPtr->range[1][1] == TIX_GR_MAX) {
86 
87 	    /* clear everything else from the list
88 	     */
89 	    Tix_SimpleListIteratorInit(&li);
90 
91 	    for (Tix_SimpleListStart(&wPtr->selList, &li);
92 		 !Tix_SimpleListDone(&li);
93 		 Tix_SimpleListNext (&wPtr->selList, &li)) {
94 
95 		SelectBlock *ptr = (SelectBlock *)li.curr;
96 		Tix_SimpleListDelete(&wPtr->selList, &li);
97 		ckfree((char*)ptr);
98 	    }
99 	}
100 	if (sbPtr->type == TIX_GR_SET) {
101 	    Tix_SimpleListAppend(&wPtr->selList, (char*)sbPtr, 0);
102 	}
103 	goto done;
104     }
105 
106 #if 0
107 
108     switch (sbPtr->type) {
109         case TIX_GR_TOGGLE: {
110         }
111 	break;
112         case TIX_GR_SET: {
113 	  Tix_SimpleListAppend(&wPtr->selList, (char*)sbPtr, 0);
114         }
115         break;
116         case TIX_GR_CLEAR: {
117 	    Tix_SimpleListIteratorInit(&li);
118 
119 	    for (Tix_SimpleListStart(&wPtr->selList, &li);
120 		 !Tix_SimpleListDone(&li);
121 		 Tix_SimpleListNext (&wPtr->selList, &li)) {
122 	    }
123         }
124 
125     }
126 #else
127 
128     Tix_SimpleListAppend(&wPtr->selList, (char*)sbPtr, 0);
129 
130 #endif
131 
132   done:
133     Tix_GrAddChangedRect(wPtr, sbPtr->range, 0);
134 }
135 
136 static void
Tix_GrAdjustSelection(wPtr,sbPtr)137 Tix_GrAdjustSelection(wPtr, sbPtr)
138     WidgetPtr wPtr;
139     SelectBlock * sbPtr;
140 {
141     int changed[2][2];
142     SelectBlock * current;
143 
144     current = (SelectBlock*)wPtr->selList.tail;
145 
146     /*
147      * The changed region is the union of the area of the current selection
148      * and the adjusted selection.
149      */
150     changed[TIX_X][0] = sbPtr->range[TIX_X][0];
151     changed[TIX_X][1] = sbPtr->range[TIX_X][1];
152     changed[TIX_Y][0] = sbPtr->range[TIX_Y][0];
153     changed[TIX_Y][1] = sbPtr->range[TIX_Y][1];
154 
155     if (changed[TIX_X][0] > current->range[TIX_X][0]) {
156 	changed[TIX_X][0] = current->range[TIX_X][0];
157     }
158     if (changed[TIX_X][1] < current->range[TIX_X][1]) {
159 	changed[TIX_X][1] = current->range[TIX_X][1];
160     }
161     if (changed[TIX_Y][0] > current->range[TIX_Y][0]) {
162 	changed[TIX_Y][0] = current->range[TIX_Y][0];
163     }
164     if (changed[TIX_Y][1] < current->range[TIX_Y][1]) {
165 	changed[TIX_Y][1] = current->range[TIX_Y][1];
166     }
167 
168     /* Adjust the current selection according to sbPtr */
169     current->range[TIX_X][0] = sbPtr->range[TIX_X][0];
170     current->range[TIX_X][1] = sbPtr->range[TIX_X][1];
171     current->range[TIX_Y][0] = sbPtr->range[TIX_Y][0];
172     current->range[TIX_Y][1] = sbPtr->range[TIX_Y][1];
173 
174     /* Set the changed area */
175     Tix_GrAddChangedRect(wPtr, changed, 0);
176 
177     /* sbPtr is no longer needed */
178     ckfree((char*)sbPtr);
179 }
180 
181 static int
Tix_GrSelModify(clientData,interp,argc,argv)182 Tix_GrSelModify(clientData, interp, argc, argv)
183     ClientData clientData;
184     Tcl_Interp *interp;		/* Current interpreter. */
185     int argc;			/* Number of arguments. */
186     CONST84 char **argv;	/* Argument strings. */
187 {
188     WidgetPtr wPtr = (WidgetPtr) clientData;
189     int type, adjust = 0;
190     SelectBlock * sbPtr = NULL;
191     int tmp;
192 
193     if (argc != 2 && argc != 4) {
194 	return Tix_ArgcError(interp, argc+2, argv-2, 2, "x1 y1 ?x2 y2?");
195     }
196 
197     /*
198      * (1) find out the type of operation.
199      */
200     if (argv[-1][0] == 'a') {
201 	if (wPtr->selList.numItems <= 0) {
202 	    /*
203 	     * There is nothing in the selection list to adjust!
204 	     */
205 	    Tcl_AppendResult(interp, "selection list is empty", NULL);
206 	    return TCL_ERROR;
207 	}
208 	adjust = 1;
209 	type = 0;
210     }
211     else if (argv[-1][0] == 'c') {
212 	type = TIX_GR_CLEAR;
213     }
214     else if (argv[-1][0] == 's') {
215 	type = TIX_GR_SET;
216     }
217     else {
218 	type = TIX_GR_TOGGLE;
219     }
220 
221     sbPtr = (SelectBlock*)ckalloc(sizeof(SelectBlock));
222     sbPtr->type = type;
223 
224     if (Tcl_GetInt(interp, argv[0], &sbPtr->range[0][0]) != TCL_OK) {
225 	goto error;
226     }
227     if (Tcl_GetInt(interp, argv[1], &sbPtr->range[1][0]) != TCL_OK) {
228 	goto error;
229     }
230     if (argc == 4) {
231 	if (Tcl_GetInt(interp, argv[2], &sbPtr->range[0][1]) != TCL_OK) {
232 	    if (strcmp(argv[2], "max") == 0) {
233 		Tcl_ResetResult(interp);
234 		sbPtr->range[0][1] = TIX_GR_MAX;
235 	    } else {
236 		goto error;
237 	    }
238 	}
239 	if (Tcl_GetInt(interp, argv[3], &sbPtr->range[1][1]) != TCL_OK) {
240 	    if (strcmp(argv[3], "max") == 0) {
241 		Tcl_ResetResult(interp);
242 		sbPtr->range[1][1] = TIX_GR_MAX;
243 	    } else {
244 		goto error;
245 	    }
246 	}
247     } else {
248 	sbPtr->range[0][1] = sbPtr->range[0][0];
249 	sbPtr->range[1][1] = sbPtr->range[1][0];
250     }
251 
252     if (wPtr->selectUnit != tixRowUid) {
253 	if (sbPtr->range[0][0] > sbPtr->range[0][1]) {
254 	    tmp = sbPtr->range[0][1];
255 	    sbPtr->range[0][1] = sbPtr->range[0][0];
256 	    sbPtr->range[0][0] = tmp;
257 	}
258     } else {
259 	sbPtr->range[0][0] = 0;
260 	sbPtr->range[0][1] = TIX_GR_MAX;
261     }
262 
263     if (wPtr->selectUnit != tixColumnUid) {
264 	if (sbPtr->range[1][0] > sbPtr->range[1][1]) {
265 	    tmp = sbPtr->range[1][1];
266 	    sbPtr->range[1][1] = sbPtr->range[1][0];
267 	    sbPtr->range[1][0] = tmp;
268 	}
269     } else {
270 	sbPtr->range[1][0] = 0;
271 	sbPtr->range[1][1] = TIX_GR_MAX;
272     }
273 
274     if (adjust) {
275 	Tix_GrAdjustSelection(wPtr, sbPtr);
276 	sbPtr = NULL;
277     } else {
278 	Tix_GrMergeSelection(wPtr, sbPtr);
279     }
280     wPtr->toComputeSel = 1;
281     return TCL_OK;
282 
283   error:
284     if (sbPtr) {
285 	ckfree((char*)sbPtr);
286     }
287     return TCL_ERROR;
288 }
289