1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #ifdef HAVE_CONFIG_H
30 #include "../config.h"
31 #endif
32
33 #include "managedList.h"
34 #include "misc.h"
35 #include "DialogF.h"
36 #include "nedit_malloc.h"
37
38 #include <stdio.h>
39 #include <string.h>
40
41 #include <X11/Intrinsic.h>
42 #include <Xm/Form.h>
43 #include <Xm/List.h>
44 #include <Xm/PushB.h>
45 #include <Xm/RowColumn.h>
46
47 #ifdef HAVE_DEBUG_H
48 #include "../debug.h"
49 #endif
50
51
52 typedef struct {
53 Widget listW, deleteBtn, copyBtn, moveUpBtn, moveDownBtn;
54 void *(*getDialogDataCB)(
void *,
int,
int *,
void *);
55 void *getDialogDataArg;
56 void (*setDialogDataCB)(
void *,
void *);
57 void *setDialogDataArg;
58 void *(*copyItemCB)(
void *);
59 void (*freeItemCB)(
void *);
60 int (*deleteConfirmCB)(
int,
void *);
61 void *deleteConfirmArg;
62 int maxItems;
63 int *nItems;
64 void **itemList;
65 int lastSelection;
66 } managedListData;
67
68 static void destroyCB(Widget w, XtPointer clientData, XtPointer callData);
69 static void deleteCB(Widget w, XtPointer clientData, XtPointer callData);
70 static void copyCB(Widget w, XtPointer clientData, XtPointer callData);
71 static void moveUpCB(Widget w, XtPointer clientData, XtPointer callData);
72 static void moveDownCB(Widget w, XtPointer clientData, XtPointer callData);
73 static int incorporateDialogData(managedListData *ml,
int listPos,
74 int explicit);
75 static void updateDialogFromList(managedListData *ml,
int selection);
76 static void updateListWidgetItem(managedListData *ml,
int listPos);
77 static void listSelectionCB(Widget w, XtPointer clientData, XtPointer callData);
78 static int selectedListPosition(managedListData *ml);
79 static void selectItem(Widget listW,
int itemIndex,
int updateDialog);
80 static Widget shellOfWidget(Widget w);
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 Widget CreateManagedList(Widget parent,
char *name, Arg *args,
102 int argC,
void **itemList,
int *nItems,
int maxItems,
int nColumns,
103 void *(*getDialogDataCB)(
void *,
int,
int *,
void *),
104 void *getDialogDataArg,
void (*setDialogDataCB)(
void *,
void *),
105 void *setDialogDataArg,
void (*freeItemCB)(
void *))
106 {
107 int ac;
108 Arg al[
20];
109 XmString s1;
110 Widget form, rowCol, listW;
111 Widget deleteBtn, copyBtn, moveUpBtn, moveDownBtn;
112 XmString *placeholderTable;
113 char *placeholderStr;
114
115 form = XmCreateForm(parent, name, args, argC);
116 XtManageChild(form);
117 rowCol = XtVaCreateManagedWidget(
"mlRowCol", xmRowColumnWidgetClass, form,
118 XmNpacking, XmPACK_COLUMN,
119 XmNleftAttachment, XmATTACH_FORM,
120 XmNtopAttachment, XmATTACH_FORM,
121 XmNbottomAttachment, XmATTACH_FORM,
NULL);
122 deleteBtn = XtVaCreateManagedWidget(
"delete", xmPushButtonWidgetClass,
123 rowCol, XmNlabelString, s1=XmStringCreateSimple(
"Delete"),
NULL);
124 XmStringFree(s1);
125 copyBtn = XtVaCreateManagedWidget(
"copy", xmPushButtonWidgetClass, rowCol,
126 XmNlabelString, s1=XmStringCreateSimple(
"Copy"),
NULL);
127 XmStringFree(s1);
128 moveUpBtn = XtVaCreateManagedWidget(
"moveUp", xmPushButtonWidgetClass,
129 rowCol, XmNlabelString, s1=XmStringCreateSimple(
"Move ^"),
NULL);
130 XmStringFree(s1);
131 moveDownBtn = XtVaCreateManagedWidget(
"moveDown", xmPushButtonWidgetClass,
132 rowCol, XmNlabelString, s1=XmStringCreateSimple(
"Move v"),
NULL);
133 XmStringFree(s1);
134
135
136
137 placeholderStr = (
char*)NEditMalloc(nColumns+
1);
138 memset(placeholderStr,
'm', nColumns);
139 placeholderStr[nColumns] =
'\0';
140 placeholderTable = StringTable(
1, placeholderStr);
141 NEditFree(placeholderStr);
142
143 ac =
0;
144 XtSetArg(al[ac], XmNscrollBarDisplayPolicy, XmAS_NEEDED); ac++;
145 XtSetArg(al[ac], XmNlistSizePolicy, XmCONSTANT); ac++;
146 XtSetArg(al[ac], XmNitems, placeholderTable); ac++;
147 XtSetArg(al[ac], XmNitemCount,
1); ac++;
148 XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
149 XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
150 XtSetArg(al[ac], XmNleftWidget, rowCol); ac++;
151 XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
152 XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
153 listW = XmCreateScrolledList(form,
"list", al, ac);
154 AddMouseWheelSupport(listW);
155 XtManageChild(listW);
156 FreeStringTable(placeholderTable);
157
158 return ManageListAndButtons(listW, deleteBtn, copyBtn, moveUpBtn,
159 moveDownBtn, itemList, nItems, maxItems, getDialogDataCB,
160 getDialogDataArg, setDialogDataCB, setDialogDataArg, freeItemCB);
161 }
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239 Widget ManageListAndButtons(Widget listW, Widget deleteBtn, Widget copyBtn,
240 Widget moveUpBtn, Widget moveDownBtn,
void **itemList,
int *nItems,
241 int maxItems,
void *(*getDialogDataCB)(
void *,
int,
int *,
void *),
242 void *getDialogDataArg,
void (*setDialogDataCB)(
void *,
void *),
243 void *setDialogDataArg,
void (*freeItemCB)(
void *))
244 {
245 managedListData *ml;
246
247
248
249 ml = (managedListData *)NEditMalloc(
sizeof(managedListData));
250 ml->listW = listW;
251 ml->deleteBtn = deleteBtn;
252 ml->copyBtn = copyBtn;
253 ml->moveUpBtn = moveUpBtn;
254 ml->moveDownBtn = moveDownBtn;
255 ml->getDialogDataCB =
NULL;
256 ml->getDialogDataArg = getDialogDataArg;
257 ml->setDialogDataCB =
NULL;
258 ml->setDialogDataArg = setDialogDataArg;
259 ml->freeItemCB = freeItemCB;
260 ml->deleteConfirmCB =
NULL;
261 ml->deleteConfirmArg =
NULL;
262 ml->nItems = nItems;
263 ml->maxItems = maxItems;
264 ml->itemList = itemList;
265 ml->lastSelection =
1;
266
267
268
269 XtVaSetValues(ml->listW, XmNuserData, ml,
NULL);
270 XtAddCallback(ml->listW, XmNdestroyCallback, destroyCB, ml);
271
272
273 XtAddCallback(ml->deleteBtn, XmNactivateCallback, deleteCB, ml);
274 XtAddCallback(ml->copyBtn, XmNactivateCallback, copyCB, ml);
275 XtAddCallback(ml->moveUpBtn, XmNactivateCallback, moveUpCB, ml);
276 XtAddCallback(ml->moveDownBtn, XmNactivateCallback, moveDownCB, ml);
277 XtAddCallback(ml->listW, XmNbrowseSelectionCallback, listSelectionCB, ml);
278
279
280
281 updateDialogFromList(ml, -
1);
282 ml->getDialogDataCB = getDialogDataCB;
283 ml->setDialogDataCB = setDialogDataCB;
284
285 return ml->listW;
286 }
287
288
289
290
291
292
293
294
295 int UpdateManagedList(Widget listW,
int explicitRequest)
296 {
297 managedListData *ml;
298
299
300
301 XtVaGetValues(listW, XmNuserData, &ml,
NULL);
302
303
304 return incorporateDialogData(ml, selectedListPosition(ml), explicitRequest);
305 }
306
307
308
309
310
311 void ChangeManagedListData(Widget listW)
312 {
313 managedListData *ml;
314
315
316
317 XtVaGetValues(listW, XmNuserData, &ml,
NULL);
318
319 updateDialogFromList(ml, -
1);
320 }
321
322
323
324
325
326 void SelectManagedListItem(Widget listW,
int itemIndex)
327 {
328 selectItem(listW, itemIndex, True);
329 }
330
331
332
333
334 int ManagedListSelectedIndex(Widget listW)
335 {
336 managedListData *ml;
337
338 XtVaGetValues(listW, XmNuserData, &ml,
NULL);
339 return selectedListPosition(ml)-
2;
340 }
341
342
343
344
345
346
347 void AddDeleteConfirmCB(Widget listW,
int (*deleteConfirmCB)(
int,
void *),
348 void *deleteConfirmArg)
349 {
350 managedListData *ml;
351
352 XtVaGetValues(listW, XmNuserData, &ml,
NULL);
353 ml->deleteConfirmCB = deleteConfirmCB;
354 ml->deleteConfirmArg = deleteConfirmArg;
355 }
356
357
358
359
360 static void destroyCB(Widget w, XtPointer clientData, XtPointer callData)
361 {
362
363 NEditFree(clientData);
364 }
365
366
367
368
369 static void deleteCB(Widget w, XtPointer clientData, XtPointer callData)
370 {
371 managedListData *ml = (managedListData *)clientData;
372 int i, ind, listPos;
373
374
375 listPos = selectedListPosition(ml);
376 ind = listPos-
2;
377
378
379
380 if (ml->deleteConfirmCB !=
NULL)
381 if (!(*ml->deleteConfirmCB)(ind, ml->deleteConfirmArg))
382 return;
383
384
385 (*ml->freeItemCB)(ml->itemList[ind]);
386 for (i=ind; i<*ml->nItems-
1; i++)
387 ml->itemList[i] = ml->itemList[i+
1];
388 (*ml->nItems)--;
389
390
391
392 updateDialogFromList(ml, ind-
1);
393 }
394
395 static void copyCB(Widget w, XtPointer clientData, XtPointer callData)
396 {
397 managedListData *ml = (managedListData *)clientData;
398 int i, listPos, abort = False;
399 void *item;
400
401
402 listPos = selectedListPosition(ml);
403 if (listPos ==
1)
404 return;
405
406 if ((*ml->nItems) == ml->maxItems) {
407 DialogF(
DF_ERR, shellOfWidget(ml->listW),
1,
"Limits exceeded",
408 "Cannot copy item.\nToo many items in list.",
409 "OK");
410 return;
411 }
412
413
414 item = (*ml->getDialogDataCB)(ml->itemList[listPos-
2], False, &abort,
415 ml->getDialogDataArg);
416 if (abort)
417 return;
418 if (item !=
NULL) {
419 (*ml->freeItemCB)(ml->itemList[listPos-
2]);
420 ml->itemList[listPos-
2] = item;
421 }
422
423
424
425
426
427
428 updateDialogFromList(ml, listPos-
2);
429 item = (*ml->getDialogDataCB)(ml->itemList[listPos-
2], True, &abort,
430 ml->getDialogDataArg);
431 if (abort)
432 return;
433
434
435 for (i= *ml->nItems; i>=listPos; i--)
436 ml->itemList[i] = ml->itemList[i-
1];
437 ml->itemList[listPos-
1] = item;
438 (*ml->nItems)++;
439
440
441 updateDialogFromList(ml, listPos-
1);
442 }
443
444 static void moveUpCB(Widget w, XtPointer clientData, XtPointer callData)
445 {
446 managedListData *ml = (managedListData *)clientData;
447 int ind, listPos;
448 void *temp;
449
450
451 listPos = selectedListPosition(ml);
452 ind = listPos-
2;
453
454
455
456
457 if (!incorporateDialogData(ml, ml->lastSelection, False))
458 return;
459
460
461 temp = ml->itemList[ind];
462 ml->itemList[ind] = ml->itemList[ind-
1];
463 ml->itemList[ind-
1] = temp;
464
465
466 updateDialogFromList(ml, ind-
1);
467 }
468
469 static void moveDownCB(Widget w, XtPointer clientData, XtPointer callData)
470 {
471 managedListData *ml = (managedListData *)clientData;
472 int ind, listPos;
473 void *temp;
474
475
476 listPos = selectedListPosition(ml);
477 ind = listPos-
2;
478
479
480
481 if (!incorporateDialogData(ml, ml->lastSelection, False))
482 return;
483
484
485 temp = ml->itemList[ind];
486 ml->itemList[ind] = ml->itemList[ind+
1];
487 ml->itemList[ind+
1] = temp;
488
489
490 updateDialogFromList(ml, ind+
1);
491 }
492
493
494
495
496 static void listSelectionCB(Widget w, XtPointer clientData, XtPointer callData)
497 {
498 managedListData *ml = (managedListData *)clientData;
499 int ind, listPos = ((XmListCallbackStruct *)callData)->item_position;
500
501
502
503
504 if (ml->getDialogDataCB !=
NULL && ml->lastSelection !=
0) {
505 if (!incorporateDialogData(ml, ml->lastSelection, False)) {
506 XmListDeselectAllItems(ml->listW);
507 XmListSelectPos(ml->listW, ml->lastSelection, False);
508 return;
509 }
510
511 selectItem(ml->listW, listPos-
2, False);
512 }
513 ml->lastSelection = listPos;
514
515
516
517 if (listPos ==
1) {
518 XtSetSensitive(ml->copyBtn, False);
519 XtSetSensitive(ml->deleteBtn, False);
520 XtSetSensitive(ml->moveUpBtn, False);
521 XtSetSensitive(ml->moveDownBtn, False);
522 }
else {
523 XtSetSensitive(ml->copyBtn, True);
524 XtSetSensitive(ml->deleteBtn, True);
525 XtSetSensitive(ml->moveUpBtn, listPos !=
2);
526 XtSetSensitive(ml->moveDownBtn, listPos != *ml->nItems+
1);
527 }
528
529
530 ind = listPos -
2;
531
532
533 if (ml->setDialogDataCB !=
NULL)
534 (*ml->setDialogDataCB)(listPos==
1 ?
NULL : ml->itemList[ind],
535 ml->setDialogDataArg);
536 }
537
538
539
540
541
542
543
544
545 static int incorporateDialogData(managedListData *ml,
int listPos,
int explicit)
546 {
547 int abort = False;
548 void *item;
549
550
551
552 item = (*ml->getDialogDataCB)(listPos ==
1 ?
NULL : ml->itemList[
553 listPos-
2], explicit, &abort, ml->getDialogDataArg);
554 if (abort)
555 return False;
556 if (item ==
NULL)
557 return True;
558
559
560
561 if (listPos ==
1) {
562 if ((*ml->nItems) == ml->maxItems) {
563 DialogF(
DF_ERR, shellOfWidget(ml->listW),
1,
"Limits exceeded",
564 "Cannot add new item.\nToo many items in list.",
565 "OK");
566 return False;
567 }
568 ml->itemList[(*ml->nItems)++] = item;
569 updateDialogFromList(ml, *ml->nItems -
1);
570 }
else {
571 (*ml->freeItemCB)(ml->itemList[listPos-
2]);
572 ml->itemList[listPos-
2] = item;
573 updateListWidgetItem(ml, listPos);
574 }
575 return True;
576 }
577
578
579
580
581
582
583 static void updateDialogFromList(managedListData *ml,
int selection)
584 {
585 int i;
586 XmString *stringTable;
587
588
589
590 XmListDeselectAllItems(ml->listW);
591
592
593 stringTable = (XmString *)NEditMalloc(
sizeof(XmString) * (*ml->nItems+
1));
594 stringTable[
0] = XmStringCreateSimple(
"New");
595 for (i=
0; i < *ml->nItems; i++)
596 stringTable[i+
1] = XmStringCreateSimple(*(
char **)ml->itemList[i]);
597 XtVaSetValues(ml->listW, XmNitems, stringTable,
598 XmNitemCount, *ml->nItems+
1,
NULL);
599 for (i=
0; i < *ml->nItems+
1; i++)
600 XmStringFree(stringTable[i]);
601 NEditFree(stringTable);
602
603
604
605
606 ml->lastSelection =
0;
607 selectItem(ml->listW, selection, True);
608 }
609
610
611
612
613
614 static void updateListWidgetItem(managedListData *ml,
int listPos)
615 {
616 int savedPos;
617 XmString newString[
1];
618
619
620
621
622 savedPos = selectedListPosition(ml);
623 XmListDeselectAllItems(ml->listW);
624
625
626 newString[
0] = XmStringCreateSimple(*(
char **)ml->itemList[listPos-
2]);
627 XmListReplaceItemsPos(ml->listW, newString,
1, listPos);
628 XmStringFree(newString[
0]);
629
630
631 XmListSelectPos(ml->listW, savedPos, False);
632 }
633
634
635
636
637 static int selectedListPosition(managedListData *ml)
638 {
639 int listPos;
640 int *posList =
NULL, posCount =
0;
641
642 if (!XmListGetSelectedPos(ml->listW, &posList, &posCount)) {
643 fprintf(stderr,
"Internal error (nothing selected)");
644 return 1;
645 }
646 listPos = *posList;
647 NEditFree(posList);
648 if (listPos <
1 || listPos > *ml->nItems+
1) {
649 fprintf(stderr,
"Internal error (XmList bad value)");
650 return 1;
651 }
652 return listPos;
653 }
654
655
656
657
658
659
660 static void selectItem(Widget listW,
int itemIndex,
int updateDialog)
661 {
662 int topPos, nVisible, selection = itemIndex+
2;
663
664
665 XmListDeselectAllItems(listW);
666 XmListSelectPos(listW, selection, updateDialog);
667
668
669 XtVaGetValues(listW, XmNtopItemPosition, &topPos, XmNvisibleItemCount,
670 &nVisible,
NULL);
671 if (selection < topPos)
672 XmListSetPos(listW, selection);
673 else if (selection >= topPos + nVisible)
674 XmListSetPos(listW, selection - nVisible +
1);
675 }
676
677 static Widget shellOfWidget(Widget w)
678 {
679 while(
1) {
680 if (!w)
return 0;
681 if (XtIsSubclass(w, shellWidgetClass))
return w;
682 w = XtParent(w);
683 }
684 }
685