2 Copyright © 2002-2012, The AROS Development Team. All rights reserved.
9 #include <exec/memory.h>
10 #include <graphics/gfx.h>
11 #include <graphics/view.h>
12 #include <devices/rawkeycodes.h>
13 #include <clib/alib_protos.h>
14 #include <proto/exec.h>
15 #include <proto/graphics.h>
16 #include <proto/utility.h>
17 #include <proto/dos.h>
18 #include <proto/intuition.h>
19 #include <proto/muimaster.h>
21 /* #define MYDEBUG 1 */
24 #include "muimaster_intern.h"
27 #include "textengine.h"
28 #include "listimage.h"
31 extern struct Library
*MUIMasterBase
;
33 #define ENTRY_TITLE (-1)
35 #define FORMAT_TEMPLATE "DELTA=D/N,PREPARSE=P/K,WEIGHT=W/N,MINWIDTH=MIW/N," \
36 "MAXWIDTH=MAW/N,COL=C/N,BAR/S"
56 LONG
*widths
; /* Widths of the columns */
57 LONG width
; /* Line width */
58 LONG height
; /* Line height */
59 WORD flags
; /* see below */
62 #define ENTRY_SELECTED (1<<0)
67 int colno
; /* Column number */
68 int user_width
; /* user set width; -1 if entry width */
69 int min_width
; /* min width percentage */
70 int max_width
; /* min width percentage */
72 int delta
; /* ignored for the first and last column, defaults to 4 */
75 int entries_width
; /* width of the entries (maximum of all widths) */
78 struct MUI_ImageSpec_intern
;
85 APTR intern_pool
; /* The internal pool which the class has allocated */
86 LONG intern_puddle_size
;
87 LONG intern_thresh_size
;
88 APTR pool
; /* the pool which is used to allocate list entries */
90 struct Hook
*construct_hook
;
91 struct Hook
*compare_hook
;
92 struct Hook
*destruct_hook
;
93 struct Hook
*display_hook
;
95 struct Hook default_compare_hook
;
97 /* List management, currently we use a simple flat array, which is not
98 * good if many entries are inserted/deleted */
99 LONG entries_num
; /* Number of Entries in the list */
100 LONG entries_allocated
;
101 struct ListEntry
**entries
;
103 LONG entries_first
; /* first visible entry */
104 LONG entries_visible
; /* number of visible entries,
105 * determined at MUIM_Layout */
107 LONG insert_position
; /* pos of the last insertion */
109 LONG entry_maxheight
; /* Maximum height of an entry */
110 ULONG entry_minheight
; /* from MUIA_List_MinLineHeight */
112 LONG entries_totalheight
;
113 LONG entries_maxwidth
;
115 LONG vertprop_entries
;
116 LONG vertprop_visible
;
119 LONG confirm_entries_num
; /* These are the correct entries num, used
120 * so you cannot set MUIA_List_Entries to
123 LONG entries_top_pixel
; /* Where the entries start */
125 /* Column managment, is allocated by ParseListFormat() and freed
126 * by CleanListFormat() */
128 LONG columns
; /* Number of columns the list has */
129 struct ColumnInfo
*ci
;
131 STRPTR
*strings
; /* the strings for the display function, one
132 * more than needed (for the entry position) */
135 int title_height
; /* The complete height of the title */
136 STRPTR title
; /* On single comlums this is the title, otherwise 1 */
138 struct MUI_EventHandlerNode ehn
;
139 int mouse_click
; /* see below if mouse is hold down */
142 struct MUI_ImageSpec_intern
*list_cursor
;
143 struct MUI_ImageSpec_intern
*list_select
;
144 struct MUI_ImageSpec_intern
*list_selcur
;
146 /* Render optimization */
147 int update
; /* 1 - update everything, 2 - redraw entry at update_pos,
148 * 3 - scroll to current entries_first (old value is in
162 ULONG input
; /* FALSE - readonly, otherwise TRUE */
165 struct MinList images
;
168 ListviewMulti prefs_multi
;
169 ListviewRefresh prefs_refresh
;
170 UWORD prefs_linespacing
;
172 UWORD prefs_smoothval
;
175 #define LIST_ADJUSTWIDTH (1<<0)
176 #define LIST_ADJUSTHEIGHT (1<<1)
177 #define LIST_AUTOVISIBLE (1<<2)
178 #define LIST_DRAGSORTABLE (1<<3)
179 #define LIST_SHOWDROPMARKS (1<<4)
180 #define LIST_QUIET (1<<5)
183 #define MOUSE_CLICK_ENTRY 1 /* on entry clicked */
184 #define MOUSE_CLICK_TITLE 2 /* on title clicked */
186 /**************************************************************************
187 Allocate a single list entry, does not initialize it (except the pointer)
188 **************************************************************************/
189 static struct ListEntry
*AllocListEntry(struct MUI_ListData
*data
)
192 struct ListEntry
*le
;
193 int size
= sizeof(struct ListEntry
) + sizeof(LONG
) * data
->columns
+ 4;
197 mem
= AllocPooled(data
->pool
, size
);
200 D(bug("List AllocListEntry %p, %ld bytes\n", mem
, size
));
202 mem
[0] = size
; /* Save the size */
203 le
= (struct ListEntry
*)(mem
+ 1);
204 le
->widths
= (LONG
*) (le
+ 1);
206 /* Initialize fields */
209 for (j
= 0; j
< data
->columns
; j
++)
215 /**************************************************************************
216 Deallocate a single list entry, does not deinitialize it
217 **************************************************************************/
218 static void FreeListEntry(struct MUI_ListData
*data
,
219 struct ListEntry
*entry
)
221 ULONG
*mem
= ((ULONG
*) entry
) - 1;
222 D(bug("FreeListEntry %p size=%ld\n", mem
, mem
[0]));
223 FreePooled(data
->pool
, mem
, mem
[0]);
226 /**************************************************************************
227 Ensures that we there can be at least the given amount of entries within
228 the list. Returns 0 if not. It also allocates the space for the title.
229 It can be accesses with data->entries[ENTRY_TITLE]
230 **************************************************************************/
231 static int SetListSize(struct MUI_ListData
*data
, LONG size
)
233 struct ListEntry
**new_entries
;
234 int new_entries_allocated
;
236 if (size
+ 1 <= data
->entries_allocated
)
239 new_entries_allocated
= data
->entries_allocated
* 2 + 4;
240 if (new_entries_allocated
< size
+ 1)
241 new_entries_allocated
= size
+ 1 + 10; /* 10 is just random */
243 D(bug("List %p : SetListSize allocating %ld bytes\n", data
,
244 new_entries_allocated
* sizeof(struct ListEntry
*)));
246 AllocVec(new_entries_allocated
* sizeof(struct ListEntry
*), 0);
247 if (NULL
== new_entries
)
251 CopyMem(data
->entries
- 1, new_entries
,
252 (data
->entries_num
+ 1) * sizeof(struct ListEntry
*));
253 FreeVec(data
->entries
- 1);
255 data
->entries
= new_entries
+ 1;
256 data
->entries_allocated
= new_entries_allocated
;
260 /**************************************************************************
261 Prepares the insertion of count entries at pos.
262 This function doesn't care if there is enough space in the datastructure.
263 SetListSize() must be used first.
264 With current implementation, this call will never fail
265 **************************************************************************/
266 static int PrepareInsertListEntries(struct MUI_ListData
*data
, int pos
,
269 memmove(&data
->entries
[pos
+ count
], &data
->entries
[pos
],
270 (data
->entries_num
- pos
) * sizeof(struct ListEntry
*));
274 /**************************************************************************
275 Inserts a already initialized array of Entries at the given position.
276 This function doesn't care if there is enough space in the datastructure
277 Returns 1 if something failed (never in current implementation)
278 **************************************************************************/
280 static int InsertListEntries(struct MUI_ListData
*data
, int pos
,
281 struct ListEntry
**array
, int count
)
283 memmove(&data
->entries
[pos
+ count
], &data
->entries
[pos
],
284 data
->entries_num
- pos
);
285 memcpy(&data
->entries
[pos
], array
, count
);
291 /**************************************************************************
292 Removes count (already deinitalized) list entries starting az pos.
293 **************************************************************************/
294 static void RemoveListEntries(struct MUI_ListData
*data
, int pos
, int count
)
296 // FIXME: segfault if entries_num = pos = count = 1
297 memmove(&data
->entries
[pos
], &data
->entries
[pos
+ count
],
298 (data
->entries_num
- (pos
+ count
)) * sizeof(struct ListEntry
*));
301 /**************************************************************************
302 Frees all memory allocated by ParseListFormat()
303 **************************************************************************/
304 static void FreeListFormat(struct MUI_ListData
*data
)
310 for (i
= 0; i
< data
->columns
; i
++)
312 FreeVec(data
->ci
[i
].preparse
);
313 data
->ci
[i
].preparse
= NULL
;
318 FreeVec(data
->preparses
);
319 data
->preparses
= NULL
;
322 FreeVec(data
->strings
- 1);
323 data
->strings
= NULL
;
328 /**************************************************************************
329 Parses the given format string (also frees a previouly parsed format).
331 **************************************************************************/
332 static int ParseListFormat(struct MUI_ListData
*data
, STRPTR format
)
340 struct RDArgs
*rdargs
;
343 format
= (STRPTR
) "";
347 FreeListFormat(data
);
351 /* Count the number of columns first */
356 if (!(data
->preparses
=
357 AllocVec((new_columns
+ 10) * sizeof(STRPTR
), 0)))
360 if (!(data
->strings
= AllocVec((new_columns
+ 1 + 10)
361 * sizeof(STRPTR
), 0))) /* hold enough space also for the entry pos,
362 * used by orginal MUI and also some
366 if (!(data
->ci
= AllocVec(new_columns
* sizeof(struct ColumnInfo
), 0)))
370 for (i
= 0; i
< new_columns
; i
++)
372 data
->ci
[i
].colno
= -1; // -1 means: use unassigned column
373 data
->ci
[i
].weight
= 100;
374 data
->ci
[i
].delta
= 4;
375 data
->ci
[i
].min_width
= -1;
376 data
->ci
[i
].max_width
= -1;
377 data
->ci
[i
].user_width
= -1;
378 data
->ci
[i
].bar
= FALSE
;
379 data
->ci
[i
].preparse
= NULL
;
382 if ((format_sep
= StrDup(format
)) != 0)
384 for (i
= 0; format_sep
[i
] != '\0'; i
++)
386 if (format_sep
[i
] == ',')
387 format_sep
[i
] = '\0';
390 if ((rdargs
= AllocDosObject(DOS_RDARGS
, NULL
)) != 0)
396 rdargs
->RDA_Source
.CS_Buffer
= ptr
;
397 rdargs
->RDA_Source
.CS_Length
= strlen(ptr
);
398 rdargs
->RDA_Source
.CS_CurChr
= 0;
399 rdargs
->RDA_DAList
= 0;
400 rdargs
->RDA_Buffer
= NULL
;
401 rdargs
->RDA_BufSiz
= 0;
402 rdargs
->RDA_ExtHelp
= NULL
;
403 rdargs
->RDA_Flags
= 0;
405 memset(args
, 0, sizeof args
);
406 if (ReadArgs(FORMAT_TEMPLATE
, args
, rdargs
))
409 data
->ci
[i
].colno
= *(LONG
*) args
[ARG_COL
];
410 if (args
[ARG_WEIGHT
])
411 data
->ci
[i
].weight
= *(LONG
*) args
[ARG_WEIGHT
];
413 data
->ci
[i
].delta
= *(LONG
*) args
[ARG_DELTA
];
414 if (args
[ARG_MINWIDTH
])
415 data
->ci
[i
].min_width
=
416 *(LONG
*) args
[ARG_MINWIDTH
];
417 if (args
[ARG_MAXWIDTH
])
418 data
->ci
[i
].max_width
=
419 *(LONG
*) args
[ARG_MAXWIDTH
];
420 data
->ci
[i
].bar
= args
[ARG_BAR
];
421 if (args
[ARG_PREPARSE
])
422 data
->ci
[i
].preparse
=
423 StrDup((STRPTR
) args
[ARG_PREPARSE
]);
427 ptr
+= strlen(ptr
) + 1;
430 while (i
< new_columns
);
431 FreeDosObject(DOS_RDARGS
, rdargs
);
436 for (i
= 0; i
< new_columns
; i
++)
438 D(bug("colno %d weight %d delta %d preparse %s\n",
439 data
->ci
[i
].colno
, data
->ci
[i
].weight
, data
->ci
[i
].delta
,
440 data
->ci
[i
].preparse
));
443 data
->columns
= new_columns
;
444 data
->strings
++; /* Skip entry pos */
449 /**************************************************************************
450 Call the MUIM_List_Display for the given entry. It fills out
451 data->string and data->preparses
452 **************************************************************************/
453 static void DisplayEntry(struct IClass
*cl
, Object
*obj
, int entry_pos
)
455 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
459 for (col
= 0; col
< data
->columns
; col
++)
460 data
->preparses
[col
] = data
->ci
[col
].preparse
;
462 if (entry_pos
== ENTRY_TITLE
)
464 if ((data
->columns
== 1) && (data
->title
!= (STRPTR
) 1))
466 *data
->strings
= data
->title
;
469 entry_data
= NULL
; /* it's a title request */
472 entry_data
= data
->entries
[entry_pos
]->data
;
474 /* Get the display formation */
475 DoMethod(obj
, MUIM_List_Display
, (IPTR
) entry_data
,
476 (IPTR
) data
->strings
, entry_pos
, (IPTR
) data
->preparses
);
479 /**************************************************************************
480 Determine the dims of a single entry and adapt the columninfo according
481 to it. pos might be ENTRY_TITLE. Returns 0 if pos entry needs to
482 be redrawn after this operation, 1 if all entries need to be redrawn.
483 **************************************************************************/
484 static int CalcDimsOfEntry(struct IClass
*cl
, Object
*obj
, int pos
)
486 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
487 struct ListEntry
*entry
= data
->entries
[pos
];
494 if (!(_flags(obj
) & MADF_SETUP
))
497 DisplayEntry(cl
, obj
, pos
);
499 /* Set height to at least minheight */
500 if (data
->entries
[pos
]->height
< data
->entry_minheight
)
501 data
->entries
[pos
]->height
= data
->entry_minheight
;
503 for (j
= 0; j
< data
->columns
; j
++)
506 zune_text_new(data
->preparses
[j
], data
->strings
[j
],
510 zune_text_get_bounds(text
, obj
);
512 if (text
->height
> data
->entries
[pos
]->height
)
514 data
->entries
[pos
]->height
= text
->height
;
515 /* entry height changed, redraw all entries later */
518 data
->entries
[pos
]->widths
[j
] = text
->width
;
520 if (text
->width
> data
->ci
[j
].entries_width
)
522 /* This columns width is bigger than the other in the same
523 * columns, so we store this value
525 data
->ci
[j
].entries_width
= text
->width
;
526 /* column width changed, redraw all entries later */
530 zune_text_destroy(text
);
533 if (data
->entries
[pos
]->height
> data
->entry_maxheight
)
535 data
->entry_maxheight
= data
->entries
[pos
]->height
;
536 /* maximum entry height changed, redraw all entries later */
543 /**************************************************************************
544 Determine the widths of the entries
545 **************************************************************************/
546 static void CalcWidths(struct IClass
*cl
, Object
*obj
)
549 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
551 if (!(_flags(obj
) & MADF_SETUP
))
554 for (j
= 0; j
< data
->columns
; j
++)
555 data
->ci
[j
].entries_width
= 0;
557 data
->entry_maxheight
= 0;
558 data
->entries_totalheight
= 0;
559 data
->entries_maxwidth
= 0;
561 for (i
= (data
->title
? ENTRY_TITLE
: 0); i
< data
->entries_num
; i
++)
563 CalcDimsOfEntry(cl
, obj
, i
);
564 data
->entries_totalheight
+= data
->entries
[i
]->height
;
567 for (j
= 0; j
< data
->columns
; j
++)
568 data
->entries_maxwidth
+= data
->ci
[j
].entries_width
;
570 if (!data
->entry_maxheight
)
571 data
->entry_maxheight
= 1;
574 /**************************************************************************
575 Calculates the number of visible entry lines. Returns 1 if it has
577 **************************************************************************/
578 static int CalcVertVisible(struct IClass
*cl
, Object
*obj
)
580 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
581 int old_entries_visible
= data
->entries_visible
;
582 int old_entries_top_pixel
= data
->entries_top_pixel
;
584 data
->entries_visible
= (_mheight(obj
) - data
->title_height
)
585 / (data
->entry_maxheight
/* + data->prefs_linespacing */ );
587 data
->entries_top_pixel
= _mtop(obj
) + data
->title_height
588 + (_mheight(obj
) - data
->title_height
590 data
->entries_visible
*
591 (data
->entry_maxheight
/* + data->prefs_linespacing */ )) / 2;
593 return (old_entries_visible
!= data
->entries_visible
)
594 || (old_entries_top_pixel
!= data
->entries_top_pixel
);
597 /**************************************************************************
598 Default hook to compare two list entries. Works for strings only.
599 **************************************************************************/
600 AROS_UFH3S(int, default_compare_func
,
601 AROS_UFHA(struct Hook
*, h
, A0
),
602 AROS_UFHA(char *, s2
, A2
),
603 AROS_UFHA(char *, s1
, A1
))
607 return Stricmp(s1
, s2
);
612 /**************************************************************************
614 **************************************************************************/
615 IPTR
List__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
617 struct MUI_ListData
*data
;
619 struct TagItem
*tags
;
621 LONG new_entries_active
= MUIV_List_Active_Off
;
623 obj
= (Object
*) DoSuperNewTags(cl
, obj
, NULL
,
624 MUIA_Font
, MUIV_Font_List
,
625 MUIA_Background
, MUII_ListBack
, TAG_MORE
, (IPTR
) msg
->ops_AttrList
);
629 data
= INST_DATA(cl
, obj
);
632 data
->entries_active
= MUIV_List_Active_Off
;
633 data
->intern_puddle_size
= 2008;
634 data
->intern_thresh_size
= 1024;
636 data
->default_compare_hook
.h_Entry
= (HOOKFUNC
) default_compare_func
;
637 data
->default_compare_hook
.h_SubEntry
= 0;
638 data
->compare_hook
= &(data
->default_compare_hook
);
640 /* parse initial taglist */
641 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
645 case MUIA_List_Active
:
646 new_entries_active
= tag
->ti_Data
;
650 data
->pool
= (APTR
) tag
->ti_Data
;
653 case MUIA_List_PoolPuddleSize
:
654 data
->intern_puddle_size
= tag
->ti_Data
;
657 case MUIA_List_PoolThreshSize
:
658 data
->intern_thresh_size
= tag
->ti_Data
;
661 case MUIA_List_CompareHook
:
662 /* Not tested, if List_CompareHook really works. */
663 data
->compare_hook
= (struct Hook
*)tag
->ti_Data
;
666 case MUIA_List_ConstructHook
:
667 data
->construct_hook
= (struct Hook
*)tag
->ti_Data
;
670 case MUIA_List_DestructHook
:
671 data
->destruct_hook
= (struct Hook
*)tag
->ti_Data
;
674 case MUIA_List_DisplayHook
:
675 data
->display_hook
= (struct Hook
*)tag
->ti_Data
;
678 case MUIA_List_SourceArray
:
679 array
= (APTR
*) tag
->ti_Data
;
682 case MUIA_List_Format
:
683 data
->format
= StrDup((STRPTR
) tag
->ti_Data
);
686 case MUIA_List_Title
:
687 data
->title
= (STRPTR
) tag
->ti_Data
;
690 case MUIA_List_MinLineHeight
:
691 data
->entry_minheight
= tag
->ti_Data
;
694 case MUIA_List_AdjustHeight
:
695 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_ADJUSTHEIGHT
);
698 case MUIA_List_AdjustWidth
:
699 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_ADJUSTWIDTH
);
707 /* No memory pool given, so we create our own */
708 data
->pool
= data
->intern_pool
=
709 CreatePool(0, data
->intern_puddle_size
,
710 data
->intern_thresh_size
);
713 CoerceMethod(cl
, obj
, OM_DISPOSE
);
718 /* parse the list format */
719 if (!(ParseListFormat(data
, data
->format
)))
721 CoerceMethod(cl
, obj
, OM_DISPOSE
);
725 /* This is neccessary for at least the title */
726 if (!SetListSize(data
, 0))
728 CoerceMethod(cl
, obj
, OM_DISPOSE
);
734 if (!(data
->entries
[ENTRY_TITLE
] = AllocListEntry(data
)))
736 CoerceMethod(cl
, obj
, OM_DISPOSE
);
741 data
->entries
[ENTRY_TITLE
] = NULL
;
747 /* Count the number of elements */
748 for (i
= 0; array
[i
] != NULL
; i
++)
751 DoMethod(obj
, MUIM_List_Insert
, (IPTR
) array
, i
,
752 MUIV_List_Insert_Top
);
756 if ((data
->entries_num
) && (new_entries_active
!= MUIV_List_Active_Off
))
758 switch (new_entries_active
)
760 case MUIV_List_Active_Top
:
761 new_entries_active
= 0;
764 case MUIV_List_Active_Bottom
:
765 new_entries_active
= data
->entries_num
- 1;
769 if (new_entries_active
< 0)
770 new_entries_active
= 0;
771 else if (new_entries_active
>= data
->entries_num
)
772 new_entries_active
= data
->entries_num
- 1;
774 data
->entries_active
= new_entries_active
;
775 /* Selected entry will be moved into visible area */
779 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
|
780 IDCMP_RAWKEY
| IDCMP_ACTIVEWINDOW
| IDCMP_INACTIVEWINDOW
;
781 data
->ehn
.ehn_Priority
= 0;
782 data
->ehn
.ehn_Flags
= 0;
783 data
->ehn
.ehn_Object
= obj
;
784 data
->ehn
.ehn_Class
= cl
;
786 NewList((struct List
*)&data
->images
);
788 D(bug("List_New(%lx)\n", obj
));
793 /**************************************************************************
795 **************************************************************************/
796 IPTR
List__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
798 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
800 D(bug("List Dispose\n"));
802 /* Call destruct method for every entry and free the entries manually
803 * to avoid notification */
804 while (data
->confirm_entries_num
)
806 struct ListEntry
*lentry
=
807 data
->entries
[--data
->confirm_entries_num
];
808 DoMethod(obj
, MUIM_List_Destruct
, (IPTR
) lentry
->data
,
810 FreeListEntry(data
, lentry
);
813 if (data
->intern_pool
)
814 DeletePool(data
->intern_pool
);
816 FreeVec(data
->entries
- 1);
817 /* title is currently before all other elements */
819 FreeListFormat(data
);
820 FreeVec(data
->format
);
822 return DoSuperMethodA(cl
, obj
, msg
);
826 /**************************************************************************
828 **************************************************************************/
829 IPTR
List__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
831 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
833 struct TagItem
*tags
;
835 /* parse initial taglist */
836 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
840 case MUIA_List_CompareHook
:
841 data
->compare_hook
= (struct Hook
*)tag
->ti_Data
;
844 case MUIA_List_ConstructHook
:
845 data
->construct_hook
= (struct Hook
*)tag
->ti_Data
;
848 case MUIA_List_DestructHook
:
849 data
->destruct_hook
= (struct Hook
*)tag
->ti_Data
;
852 case MUIA_List_DisplayHook
:
853 data
->display_hook
= (struct Hook
*)tag
->ti_Data
;
856 case MUIA_List_VertProp_First
:
857 data
->vertprop_first
= tag
->ti_Data
;
858 if (data
->entries_first
!= tag
->ti_Data
)
860 set(obj
, MUIA_List_First
, tag
->ti_Data
);
864 case MUIA_List_Format
:
865 data
->format
= StrDup((STRPTR
) tag
->ti_Data
);
866 ParseListFormat(data
, data
->format
);
867 // FIXME: should we check for errors?
868 DoMethod(obj
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
871 case MUIA_List_VertProp_Entries
:
872 data
->vertprop_entries
= tag
->ti_Data
;
875 case MUIA_List_VertProp_Visible
:
876 data
->vertprop_visible
= tag
->ti_Data
;
877 data
->entries_visible
= tag
->ti_Data
;
880 case MUIA_List_Active
:
882 LONG new_entries_active
= tag
->ti_Data
;
884 if ((data
->entries_num
)
885 && (new_entries_active
!= MUIV_List_Active_Off
))
887 switch (new_entries_active
)
889 case MUIV_List_Active_Top
:
890 new_entries_active
= 0;
893 case MUIV_List_Active_Bottom
:
894 new_entries_active
= data
->entries_num
- 1;
897 case MUIV_List_Active_Up
:
898 new_entries_active
= data
->entries_active
- 1;
901 case MUIV_List_Active_Down
:
902 new_entries_active
= data
->entries_active
+ 1;
905 case MUIV_List_Active_PageUp
:
907 data
->entries_active
- data
->entries_visible
;
910 case MUIV_List_Active_PageDown
:
912 data
->entries_active
+ data
->entries_visible
;
916 if (new_entries_active
< 0)
917 new_entries_active
= 0;
918 else if (new_entries_active
>= data
->entries_num
)
919 new_entries_active
= data
->entries_num
- 1;
922 new_entries_active
= -1;
924 if (data
->entries_active
!= new_entries_active
)
926 LONG old
= data
->entries_active
;
927 data
->entries_active
= new_entries_active
;
930 data
->update_pos
= old
;
931 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
933 data
->update_pos
= data
->entries_active
;
934 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
936 /* Selectchange stuff */
939 data
->entries
[old
]->flags
&= ~ENTRY_SELECTED
;
940 DoMethod(obj
, MUIM_List_SelectChange
, old
,
941 MUIV_List_Select_Off
, 0);
944 if (new_entries_active
!= -1)
946 data
->entries
[new_entries_active
]->flags
|=
948 DoMethod(obj
, MUIM_List_SelectChange
,
949 new_entries_active
, MUIV_List_Select_On
, 0);
950 DoMethod(obj
, MUIM_List_SelectChange
,
951 new_entries_active
, MUIV_List_Select_Active
, 0);
954 DoMethod(obj
, MUIM_List_SelectChange
,
955 MUIV_List_Active_Off
, MUIV_List_Select_Off
, 0);
957 set(obj
, MUIA_Listview_SelectChange
, TRUE
);
959 if (new_entries_active
!= -1)
961 DoMethod(obj
, MUIM_List_Jump
,
962 MUIV_List_Jump_Active
);
968 case MUIA_List_First
:
969 data
->update_pos
= data
->entries_first
;
971 data
->entries_first
= tag
->ti_Data
;
973 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
974 if (data
->vertprop_first
!= tag
->ti_Data
)
976 set(obj
, MUIA_List_VertProp_First
, tag
->ti_Data
);
980 case MUIA_List_Visible
:
981 if (data
->vertprop_visible
!= tag
->ti_Data
)
982 set(obj
, MUIA_List_VertProp_Visible
, tag
->ti_Data
);
985 case MUIA_List_Entries
:
986 if (data
->confirm_entries_num
== tag
->ti_Data
)
988 data
->entries_num
= tag
->ti_Data
;
989 set(obj
, MUIA_List_VertProp_Entries
, data
->entries_num
);
993 D(bug("Bug: confirm_entries != MUIA_List_Entries!\n"));
997 case MUIA_List_Quiet
:
998 _handle_bool_tag(data
->flags
, tag
->ti_Data
, LIST_QUIET
);
1001 DoMethod(obj
, MUIM_List_Redraw
, MUIV_List_Redraw_All
);
1005 case MUIA_Listview_ClickColumn
:
1006 data
->click_column
= tag
->ti_Data
;
1011 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1014 /**************************************************************************
1016 **************************************************************************/
1017 IPTR
List__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
1019 /* small macro to simplify return value storage */
1020 #define STORE *(msg->opg_Storage)
1021 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1023 switch (msg
->opg_AttrID
)
1025 case MUIA_List_Entries
:
1026 STORE
= data
->entries_num
;
1028 case MUIA_List_First
:
1029 STORE
= data
->entries_first
;
1031 case MUIA_List_Active
:
1032 STORE
= data
->entries_active
;
1034 case MUIA_List_InsertPosition
:
1035 STORE
= data
->insert_position
;
1037 case MUIA_List_Title
:
1038 STORE
= (unsigned long)data
->title
;
1040 case MUIA_List_VertProp_Entries
:
1041 STORE
= data
->vertprop_entries
;
1043 case MUIA_List_VertProp_Visible
:
1044 STORE
= data
->vertprop_visible
;
1046 case MUIA_List_VertProp_First
:
1047 STORE
= data
->vertprop_first
;
1049 case MUIA_List_Format
:
1050 STORE
= (IPTR
) data
->format
;
1053 case MUIA_Listview_DoubleClick
:
1056 case MUIA_Listview_ClickColumn
:
1057 STORE
= data
->click_column
;
1059 case MUIA_Listview_List
:
1061 return 1; /* Validated with 3rd party application */
1064 if (DoSuperMethodA(cl
, obj
, (Msg
) msg
))
1070 /**************************************************************************
1072 **************************************************************************/
1073 IPTR
List__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
1074 struct MUIP_Setup
*msg
)
1076 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1078 if (!DoSuperMethodA(cl
, obj
, (Msg
) msg
))
1081 data
->prefs_multi
= muiGlobalInfo(obj
)->mgi_Prefs
->list_multi
;
1082 data
->prefs_refresh
= muiGlobalInfo(obj
)->mgi_Prefs
->list_refresh
;
1083 data
->prefs_linespacing
=
1084 muiGlobalInfo(obj
)->mgi_Prefs
->list_linespacing
;
1085 data
->prefs_smoothed
= muiGlobalInfo(obj
)->mgi_Prefs
->list_smoothed
;
1086 data
->prefs_smoothval
= muiGlobalInfo(obj
)->mgi_Prefs
->list_smoothval
;
1088 CalcWidths(cl
, obj
);
1092 data
->title_height
= data
->entries
[ENTRY_TITLE
]->height
+ 2;
1096 data
->title_height
= 0;
1099 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
1102 zune_imspec_setup(MUII_ListCursor
, muiRenderInfo(obj
));
1104 zune_imspec_setup(MUII_ListSelect
, muiRenderInfo(obj
));
1106 zune_imspec_setup(MUII_ListSelCur
, muiRenderInfo(obj
));
1111 /**************************************************************************
1113 **************************************************************************/
1114 IPTR
List__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
1115 struct MUIP_Cleanup
*msg
)
1117 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1118 struct ListImage
*li
= List_First(&data
->images
);
1122 struct ListImage
*next
= Node_Next(li
);
1123 DoMethod(obj
, MUIM_List_DeleteImage
, (IPTR
) li
);
1127 zune_imspec_cleanup(data
->list_cursor
);
1128 zune_imspec_cleanup(data
->list_select
);
1129 zune_imspec_cleanup(data
->list_selcur
);
1131 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
1132 data
->ehn
.ehn_Events
&= ~(IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
);
1133 data
->mouse_click
= 0;
1135 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1138 /**************************************************************************
1140 **************************************************************************/
1141 IPTR
List__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
,
1142 struct MUIP_AskMinMax
*msg
)
1144 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1146 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1149 if ((data
->flags
& LIST_ADJUSTWIDTH
) && (data
->entries_num
> 0))
1151 msg
->MinMaxInfo
->MinWidth
+= data
->entries_maxwidth
;
1152 msg
->MinMaxInfo
->DefWidth
+= data
->entries_maxwidth
;
1153 msg
->MinMaxInfo
->MaxWidth
+= data
->entries_maxwidth
;
1157 msg
->MinMaxInfo
->MinWidth
+= 40;
1158 msg
->MinMaxInfo
->DefWidth
+= 100;
1159 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
1162 if (data
->entries_num
> 0)
1164 if (data
->flags
& LIST_ADJUSTHEIGHT
)
1166 msg
->MinMaxInfo
->MinHeight
+= data
->entries_totalheight
;
1167 msg
->MinMaxInfo
->DefHeight
+= data
->entries_totalheight
;
1168 msg
->MinMaxInfo
->MaxHeight
+= data
->entries_totalheight
;
1172 ULONG h
= data
->entry_maxheight
+ data
->prefs_linespacing
;
1173 msg
->MinMaxInfo
->MinHeight
+= 2 * h
+ data
->prefs_linespacing
;
1174 msg
->MinMaxInfo
->DefHeight
+= 8 * h
+ data
->prefs_linespacing
;
1175 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
1180 msg
->MinMaxInfo
->MinHeight
+= 36;
1181 msg
->MinMaxInfo
->DefHeight
+= 96;
1182 msg
->MinMaxInfo
->MaxHeight
= MUI_MAXMAX
;
1184 D(bug("List %p minheigh=%d, line maxh=%d\n",
1185 obj
, msg
->MinMaxInfo
->MinHeight
, data
->entry_maxheight
));
1189 /**************************************************************************
1191 **************************************************************************/
1192 IPTR
List__MUIM_Layout(struct IClass
*cl
, Object
*obj
,
1193 struct MUIP_Layout
*msg
)
1195 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1196 ULONG rc
= DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1197 LONG new_entries_first
= data
->entries_first
;
1199 /* Calc the numbers of entries visible */
1200 CalcVertVisible(cl
, obj
);
1202 #if 0 /* Don't do this! */
1203 if (data
->entries_active
< new_entries_first
)
1204 new_entries_first
= data
->entries_active
;
1207 if (data
->entries_active
+ 1 >=
1208 (data
->entries_first
+ data
->entries_visible
))
1210 data
->entries_active
- data
->entries_visible
+ 1;
1212 if ((new_entries_first
+ data
->entries_visible
>=
1214 && (data
->entries_visible
<= data
->entries_num
))
1215 new_entries_first
= data
->entries_num
- data
->entries_visible
;
1217 if (data
->entries_num
<= data
->entries_visible
)
1218 new_entries_first
= 0;
1220 if (new_entries_first
< 0)
1221 new_entries_first
= 0;
1223 set(obj
, new_entries_first
!= data
->entries_first
?
1224 MUIA_List_First
: TAG_IGNORE
, new_entries_first
);
1226 /* So the notify takes happens */
1227 set(obj
, MUIA_List_VertProp_Visible
, data
->entries_visible
);
1233 /**************************************************************************
1235 **************************************************************************/
1236 IPTR
List__MUIM_Show(struct IClass
*cl
, Object
*obj
,
1237 struct MUIP_Show
*msg
)
1239 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1240 ULONG rc
= DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1242 zune_imspec_show(data
->list_cursor
, obj
);
1243 zune_imspec_show(data
->list_select
, obj
);
1244 zune_imspec_show(data
->list_selcur
, obj
);
1249 /**************************************************************************
1251 **************************************************************************/
1252 IPTR
List__MUIM_Hide(struct IClass
*cl
, Object
*obj
,
1253 struct MUIP_Hide
*msg
)
1255 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1258 if (data
->ehn
.ehn_Events
& (IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
))
1260 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1261 (IPTR
) & data
->ehn
);
1262 data
->ehn
.ehn_Events
&= ~(IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
);
1263 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1264 (IPTR
) & data
->ehn
);
1266 data
->mouse_click
= 0;
1269 zune_imspec_hide(data
->list_cursor
);
1270 zune_imspec_hide(data
->list_select
);
1271 zune_imspec_hide(data
->list_selcur
);
1273 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1277 /**************************************************************************
1278 Draw an entry at entry_pos at the given y location. To draw the title,
1279 set pos to ENTRY_TITLE
1280 **************************************************************************/
1281 static VOID
List_DrawEntry(struct IClass
*cl
, Object
*obj
, int entry_pos
,
1284 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1287 /* To be sure we don't draw anything if there is no title */
1288 if (entry_pos
== ENTRY_TITLE
&& !data
->title
)
1291 DisplayEntry(cl
, obj
, entry_pos
);
1294 for (col
= 0; col
< data
->columns
; col
++)
1297 x2
= x1
+ data
->ci
[col
].entries_width
;
1300 zune_text_new(data
->preparses
[col
], data
->strings
[col
],
1301 ZTEXT_ARG_NONE
, 0)))
1303 /* Could be made simpler, as we don't really need the bounds */
1304 zune_text_get_bounds(text
, obj
);
1305 /* Note, this was MPEN_SHADOW before */
1306 SetAPen(_rp(obj
), muiRenderInfo(obj
)->mri_Pens
[MPEN_TEXT
]);
1307 zune_text_draw(text
, obj
, x1
, x2
, y
); /* totally wrong! */
1308 zune_text_destroy(text
);
1310 x1
= x2
+ data
->ci
[col
].delta
+ (data
->ci
[col
].bar
? BAR_WIDTH
: 0);
1314 /**************************************************************************
1316 **************************************************************************/
1317 IPTR
List__MUIM_Draw(struct IClass
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
1319 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1323 BOOL scroll_caused_damage
= FALSE
;
1325 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1327 if (msg
->flags
& MADF_DRAWUPDATE
)
1329 if (data
->update
== 1)
1330 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), _mtop(obj
),
1331 _mwidth(obj
), _mheight(obj
),
1332 0, data
->entries_first
* data
->entry_maxheight
, 0);
1336 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), _mtop(obj
),
1337 _mwidth(obj
), _mheight(obj
),
1338 0, data
->entries_first
* data
->entry_maxheight
, 0);
1341 clip
= MUI_AddClipping(muiRenderInfo(obj
), _mleft(obj
), _mtop(obj
),
1342 _mwidth(obj
), _mheight(obj
));
1344 if (!(msg
->flags
& MADF_DRAWUPDATE
)
1345 || ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 1))
1350 if (data
->title_height
&& data
->title
)
1352 List_DrawEntry(cl
, obj
, ENTRY_TITLE
, y
);
1353 y
+= data
->entries
[ENTRY_TITLE
]->height
;
1354 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
1355 Move(_rp(obj
), _mleft(obj
), y
);
1356 Draw(_rp(obj
), _mright(obj
), y
);
1357 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
1359 Move(_rp(obj
), _mleft(obj
), y
);
1360 Draw(_rp(obj
), _mright(obj
), y
);
1364 y
= data
->entries_top_pixel
;
1366 start
= data
->entries_first
;
1367 end
= data
->entries_first
+ data
->entries_visible
;
1369 if ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 3)
1371 int diffy
= data
->entries_first
- data
->update_pos
;
1373 if (abs(diffy
) < data
->entries_visible
)
1375 scroll_caused_damage
=
1376 (_rp(obj
)->Layer
->Flags
& LAYERREFRESH
) ? FALSE
: TRUE
;
1378 ScrollRaster(_rp(obj
), 0, diffy
* data
->entry_maxheight
,
1381 y
+ data
->entry_maxheight
* data
->entries_visible
);
1383 scroll_caused_damage
=
1384 scroll_caused_damage
1385 && (_rp(obj
)->Layer
->Flags
& LAYERREFRESH
);
1389 start
= end
- diffy
;
1390 y
+= data
->entry_maxheight
* (data
->entries_visible
-
1394 end
= start
- diffy
;
1398 bottom
= y
+ (end
- start
) * data
->entry_maxheight
;
1400 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), top
,
1401 _mwidth(obj
), bottom
- top
+ 1,
1403 top
- _mtop(obj
) + data
->entries_first
* data
->entry_maxheight
,
1407 for (entry_pos
= start
;
1408 entry_pos
< end
&& entry_pos
< data
->entries_num
; entry_pos
++)
1410 //struct ListEntry *entry = data->entries[entry_pos];
1412 if (!(msg
->flags
& MADF_DRAWUPDATE
) ||
1413 ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 1) ||
1414 ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 3) ||
1415 ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 2
1416 && data
->update_pos
== entry_pos
))
1418 if (entry_pos
== data
->entries_active
)
1420 zune_imspec_draw(data
->list_cursor
, muiRenderInfo(obj
),
1421 _mleft(obj
), y
, _mwidth(obj
), data
->entry_maxheight
,
1422 0, y
- data
->entries_top_pixel
, 0);
1426 if ((msg
->flags
& MADF_DRAWUPDATE
) && data
->update
== 2
1427 && data
->update_pos
== entry_pos
)
1429 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), y
,
1430 _mwidth(obj
), data
->entry_maxheight
, 0,
1432 data
->entries_first
* data
->entry_maxheight
, 0);
1435 List_DrawEntry(cl
, obj
, entry_pos
, y
);
1437 y
+= data
->entry_maxheight
;
1440 MUI_RemoveClipping(muiRenderInfo(obj
), clip
);
1444 if (scroll_caused_damage
)
1446 if (MUI_BeginRefresh(muiRenderInfo(obj
), 0))
1448 /* Theoretically it might happen that more damage is caused
1449 after ScrollRaster. By something else, like window movement
1450 in front of our window. Therefore refresh root object of
1451 window, not just this object */
1455 get(_win(obj
), MUIA_Window_RootObject
, &o
);
1456 MUI_Redraw(o
, MADF_DRAWOBJECT
);
1458 MUI_EndRefresh(muiRenderInfo(obj
), 0);
1462 ULONG x1
= _mleft(obj
);
1466 if (data
->title_height
&& data
->title
)
1468 for (col
= 0; col
< data
->columns
; col
++)
1470 ULONG halfdelta
= data
->ci
[col
].delta
/ 2;
1471 x1
+= data
->ci
[col
].entries_width
+ halfdelta
;
1473 if (x1
+ (data
->ci
[col
].bar
? BAR_WIDTH
: 0) > _mright(obj
))
1476 if (data
->ci
[col
].bar
)
1478 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
1479 Move(_rp(obj
), x1
, y
);
1481 y
+ data
->entries
[ENTRY_TITLE
]->height
- 1);
1482 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
1483 Move(_rp(obj
), x1
+ 1, y
);
1484 Draw(_rp(obj
), x1
+ 1,
1485 y
+ data
->entries
[ENTRY_TITLE
]->height
- 1);
1489 x1
+= data
->ci
[col
].delta
- halfdelta
;
1491 y
+= data
->entries
[ENTRY_TITLE
]->height
+ 1;
1496 for (col
= 0; col
< data
->columns
; col
++)
1498 ULONG halfdelta
= data
->ci
[col
].delta
/ 2;
1499 x1
+= data
->ci
[col
].entries_width
+ halfdelta
;
1501 if (x1
+ (data
->ci
[col
].bar
? BAR_WIDTH
: 0) > _mright(obj
))
1504 if (data
->ci
[col
].bar
)
1506 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHINE
]);
1507 Move(_rp(obj
), x1
, y
);
1508 Draw(_rp(obj
), x1
, _mbottom(obj
));
1509 SetAPen(_rp(obj
), _pens(obj
)[MPEN_SHADOW
]);
1510 Move(_rp(obj
), x1
+ 1, y
);
1511 Draw(_rp(obj
), x1
+ 1, _mbottom(obj
));
1516 x1
+= data
->ci
[col
].delta
- halfdelta
;
1522 /**************************************************************************
1523 Makes the entry at the given mouse position the active one.
1524 Relx and Rely are relative mouse coordinates to the upper left of
1526 **************************************************************************/
1527 static VOID
List_MakeActive(struct IClass
*cl
, Object
*obj
, LONG relx
,
1530 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1532 if (data
->entries_num
== 0)
1535 LONG eclicky
= rely
+ _top(obj
) - data
->entries_top_pixel
;
1536 /* y coordinates transformed to the entries */
1537 LONG new_act
= eclicky
/ data
->entry_maxheight
+ data
->entries_first
;
1538 LONG old_act
= data
->entries_active
;
1542 new_act
= data
->entries_first
- 1;
1544 else if (new_act
> data
->entries_first
+ data
->entries_visible
)
1546 new_act
= data
->entries_first
+ data
->entries_visible
;
1549 if (new_act
>= data
->entries_num
)
1550 new_act
= data
->entries_num
- 1;
1551 else if (new_act
< 0)
1554 /* Notify only when active entry has changed */
1555 if (old_act
!= new_act
)
1556 set(obj
, MUIA_List_Active
, new_act
);
1559 static void DoWheelMove(struct IClass
*cl
, Object
*obj
, LONG wheely
,
1562 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1563 LONG
new = data
->entries_first
;
1565 if (qual
& IEQUALIFIER_CONTROL
)
1570 new = data
->entries_num
;
1572 else if (qual
& (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
1574 new += (wheely
* data
->entries_visible
);
1581 if (new > data
->entries_num
- data
->entries_visible
)
1583 new = data
->entries_num
- data
->entries_visible
;
1591 if (new != data
->entries_first
)
1593 set(obj
, MUIA_List_First
, new);
1598 /**************************************************************************
1600 **************************************************************************/
1601 IPTR
List__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
,
1602 struct MUIP_HandleEvent
*msg
)
1604 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1608 LONG mx
= msg
->imsg
->MouseX
- _left(obj
);
1609 LONG my
= msg
->imsg
->MouseY
- _top(obj
);
1610 switch (msg
->imsg
->Class
)
1612 case IDCMP_MOUSEBUTTONS
:
1613 if (msg
->imsg
->Code
== SELECTDOWN
)
1615 if (mx
>= 0 && mx
< _width(obj
) && my
>= 0
1616 && my
< _height(obj
))
1618 LONG eclicky
= my
+ _top(obj
) - data
->entries_top_pixel
;
1619 /* y coordinates transformed to the entries */
1620 data
->mouse_click
= MOUSE_CLICK_ENTRY
;
1622 /* Now check if it was clicked on a title or on entries */
1625 data
->entries_visible
* data
->entry_maxheight
)
1627 List_MakeActive(cl
, obj
, mx
, my
);
1628 /* sets data->entries_active */
1630 if (data
->last_active
== data
->entries_active
1631 && DoubleClick(data
->last_secs
, data
->last_mics
,
1632 msg
->imsg
->Seconds
, msg
->imsg
->Micros
))
1634 /* Handle MUIA_ListView_ClickColumn */
1635 data
->click_column
= 0;
1636 if (data
->entries_num
> 0 && data
->columns
> 0)
1640 for (col
= 0; col
< data
->columns
; col
++)
1643 data
->ci
[col
].entries_width
+
1644 data
->ci
[col
].delta
+
1645 (data
->ci
[col
].bar
? BAR_WIDTH
: 0);
1647 ("[List/MUIM_HandleEvent] col %d "
1648 "width %d width_sum %d mx %d\n",
1650 data
->ci
[col
].entries_width
,
1655 ("[List/MUIM_HandleEvent] "
1658 set(obj
, MUIA_Listview_ClickColumn
,
1665 set(obj
, MUIA_Listview_DoubleClick
, TRUE
);
1666 data
->last_active
= -1;
1667 data
->last_secs
= data
->last_mics
= 0;
1671 data
->last_active
= data
->entries_active
;
1672 data
->last_secs
= msg
->imsg
->Seconds
;
1673 data
->last_mics
= msg
->imsg
->Micros
;
1677 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1678 (IPTR
) & data
->ehn
);
1679 data
->ehn
.ehn_Events
|=
1680 (IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
);
1681 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1682 (IPTR
) & data
->ehn
);
1684 return MUI_EventHandlerRC_Eat
;
1689 if (msg
->imsg
->Code
== SELECTUP
&& data
->mouse_click
)
1691 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1692 (IPTR
) & data
->ehn
);
1693 data
->ehn
.ehn_Events
&=
1694 ~(IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
);
1695 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1696 (IPTR
) & data
->ehn
);
1697 data
->mouse_click
= 0;
1703 case IDCMP_INTUITICKS
:
1704 case IDCMP_MOUSEMOVE
:
1705 if (data
->mouse_click
)
1707 List_MakeActive(cl
, obj
, mx
, my
);
1712 switch (msg
->imsg
->Code
)
1714 case RAWKEY_NM_WHEEL_UP
:
1715 if (_isinobject(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
))
1717 DoWheelMove(cl
, obj
, -1, msg
->imsg
->Qualifier
);
1721 case RAWKEY_NM_WHEEL_DOWN
:
1722 if (_isinobject(msg
->imsg
->MouseX
, msg
->imsg
->MouseY
))
1724 DoWheelMove(cl
, obj
, 1, msg
->imsg
->Qualifier
);
1731 case IDCMP_ACTIVEWINDOW
:
1732 case IDCMP_INACTIVEWINDOW
:
1733 if (data
->ehn
.ehn_Events
& (IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
))
1735 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1736 (IPTR
) & data
->ehn
);
1737 data
->ehn
.ehn_Events
&=
1738 ~(IDCMP_MOUSEMOVE
| IDCMP_INTUITICKS
);
1739 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1740 (IPTR
) & data
->ehn
);
1741 data
->mouse_click
= 0;
1750 /**************************************************************************
1752 **************************************************************************/
1753 IPTR
List__MUIM_Clear(struct IClass
*cl
, Object
*obj
,
1754 struct MUIP_List_Clear
*msg
)
1756 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1758 while (data
->confirm_entries_num
)
1760 struct ListEntry
*lentry
=
1761 data
->entries
[--data
->confirm_entries_num
];
1762 DoMethod(obj
, MUIM_List_Destruct
, (IPTR
) lentry
->data
,
1764 FreeListEntry(data
, lentry
);
1766 /* Should never fail when shrinking */
1767 SetListSize(data
, 0);
1769 if (data
->confirm_entries_num
!= data
->entries_num
)
1771 SetAttrs(obj
, MUIA_List_Entries
, 0, MUIA_List_First
, 0,
1772 /* Notify only when no entry was active */
1773 data
->entries_active
!=
1774 MUIV_List_Active_Off
? MUIA_List_Active
: TAG_DONE
,
1775 MUIV_List_Active_Off
, TAG_DONE
);
1778 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1784 /**************************************************************************
1786 **************************************************************************/
1787 IPTR
List__MUIM_Exchange(struct IClass
*cl
, Object
*obj
,
1788 struct MUIP_List_Exchange
*msg
)
1790 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1795 case MUIV_List_Exchange_Top
:
1798 case MUIV_List_Exchange_Active
:
1799 pos1
= data
->entries_active
;
1801 case MUIV_List_Exchange_Bottom
:
1802 pos1
= data
->entries_num
- 1;
1810 case MUIV_List_Exchange_Top
:
1813 case MUIV_List_Exchange_Active
:
1814 pos2
= data
->entries_active
;
1816 case MUIV_List_Exchange_Bottom
:
1817 pos2
= data
->entries_num
- 1;
1819 case MUIV_List_Exchange_Next
:
1822 case MUIV_List_Exchange_Previous
:
1829 if (pos1
>= 0 && pos1
< data
->entries_num
&& pos2
>= 0
1830 && pos2
< data
->entries_num
&& pos1
!= pos2
)
1832 struct ListEntry
*save
= data
->entries
[pos1
];
1833 data
->entries
[pos1
] = data
->entries
[pos2
];
1834 data
->entries
[pos2
] = save
;
1837 data
->update_pos
= pos1
;
1838 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1841 data
->update_pos
= pos2
;
1842 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1852 /**************************************************************************
1854 **************************************************************************/
1855 IPTR
List__MUIM_Redraw(struct IClass
*cl
, Object
*obj
,
1856 struct MUIP_List_Redraw
*msg
)
1858 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1860 if (msg
->pos
== MUIV_List_Redraw_All
)
1863 CalcWidths(cl
, obj
);
1864 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1869 if (msg
->pos
== MUIV_List_Redraw_Active
)
1870 pos
= data
->entries_active
;
1871 else if (msg
->pos
== MUIV_List_Redraw_Entry
)
1874 for (i
= 0; i
< data
->entries_num
; i
++)
1875 if (data
->entries
[i
]->data
== msg
->entry
)
1886 if (CalcDimsOfEntry(cl
, obj
, pos
))
1891 data
->update_pos
= pos
;
1893 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1899 /**************************************************************************
1901 **************************************************************************/
1902 IPTR
List__MUIM_Remove(struct IClass
*cl
, Object
*obj
,
1903 struct MUIP_List_Remove
*msg
)
1905 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1908 struct ListEntry
*lentry
;
1909 //int rem_count = 1;
1911 if (!data
->entries_num
)
1916 case MUIV_List_Remove_First
:
1920 case MUIV_List_Remove_Active
:
1921 pos
= data
->entries_active
;
1924 case MUIV_List_Remove_Last
:
1925 pos
= data
->entries_num
- 1;
1928 case MUIV_List_Remove_Selected
:
1929 /* TODO: needs special handling */
1930 pos
= data
->entries_active
;
1938 if (pos
< 0 || pos
>= data
->entries_num
)
1941 new_act
= data
->entries_active
;
1943 if (pos
== new_act
&& new_act
== data
->entries_num
- 1)
1944 new_act
--; /* might become MUIV_List_Active_Off */
1946 lentry
= data
->entries
[pos
];
1947 DoMethod(obj
, MUIM_List_Destruct
, (IPTR
) lentry
->data
,
1952 RemoveListEntries(data
, pos
, cur
- pos
);
1953 data
->confirm_entries_num
-= cur
- pos
;
1955 /* ensure that the active element is in a valid range */
1956 if (new_act
>= data
->entries_num
)
1957 new_act
= data
->entries_num
- 1;
1959 SetAttrs(obj
, MUIA_List_Entries
, data
->confirm_entries_num
,
1960 (new_act
>= pos
) || (new_act
!= data
->entries_active
) ?
1961 MUIA_List_Active
: TAG_DONE
,
1962 new_act
, /* Inform only if neccessary (for notify) */
1966 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1971 /**************************************************************************
1973 **************************************************************************/
1974 IPTR
List__MUIM_Select(struct IClass
*cl
, Object
*obj
,
1975 struct MUIP_List_Select
*msg
)
1977 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
1978 LONG pos
, i
, count
, selcount
=0, state
=0;
1980 /* Establish the range of entries affected */
1983 case MUIV_List_Select_Active
:
1984 pos
= data
->entries_active
;
1985 if (pos
== MUIV_List_Active_Off
)
1991 case MUIV_List_Select_All
:
1993 count
= data
->entries_num
;
1999 if (pos
< 0 || pos
>= data
->entries_num
)
2004 /* Change or check state of each entry in the range */
2005 for (i
= pos
; i
< pos
+ count
; i
++)
2007 state
= data
->entries
[i
]->flags
& ENTRY_SELECTED
;
2008 switch (msg
->seltype
)
2010 case MUIV_List_Select_Off
:
2011 data
->entries
[i
]->flags
&= ~ENTRY_SELECTED
;
2014 case MUIV_List_Select_On
:
2015 data
->entries
[i
]->flags
|= ENTRY_SELECTED
;
2018 case MUIV_List_Select_Toggle
:
2019 data
->entries
[i
]->flags
^= ENTRY_SELECTED
;
2023 if (data
->entries
[i
]->flags
& ENTRY_SELECTED
)
2029 /* Report old state or number of selected entries */
2032 if (msg
->pos
== MUIV_List_Select_All
2033 && msg
->seltype
== MUIV_List_Select_Ask
)
2034 *msg
->info
= selcount
;
2039 /* Redraw unless it was just an enquiry */
2040 if (msg
->seltype
!= MUIV_List_Select_Ask
)
2043 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2049 /**************************************************************************
2051 **************************************************************************/
2053 IPTR
List__MUIM_Insert(struct IClass
*cl
, Object
*obj
,
2054 struct MUIP_List_Insert
*msg
)
2056 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2057 LONG pos
, count
, sort
;
2064 /* Count the number of entries */
2065 for (count
= 0; msg
->entries
[count
] != NULL
; count
++)
2074 case MUIV_List_Insert_Top
:
2078 case MUIV_List_Insert_Active
:
2079 if (data
->entries_active
!= -1)
2080 pos
= data
->entries_active
;
2085 case MUIV_List_Insert_Sorted
:
2086 pos
= data
->entries_num
;
2087 sort
= 1; /* we sort'em later */
2090 case MUIV_List_Insert_Bottom
:
2091 pos
= data
->entries_num
;
2095 if (msg
->pos
> data
->entries_num
)
2096 pos
= data
->entries_num
;
2097 else if (msg
->pos
< 0)
2104 if (!(SetListSize(data
, data
->entries_num
+ count
)))
2107 LONG until
= pos
+ count
;
2108 APTR
*toinsert
= msg
->entries
;
2110 if (!(PrepareInsertListEntries(data
, pos
, count
)))
2115 struct ListEntry
*lentry
;
2117 if (!(lentry
= AllocListEntry(data
)))
2119 /* Panic, but we must be in a consistent state, so remove
2120 * the space where the following list entries should have gone
2122 RemoveListEntries(data
, pos
, until
- pos
);
2126 /* now call the construct method which returns us a pointer which
2128 lentry
->data
= (APTR
) DoMethod(obj
, MUIM_List_Construct
,
2129 (IPTR
) * toinsert
, (IPTR
) data
->pool
);
2132 FreeListEntry(data
, lentry
);
2133 RemoveListEntries(data
, pos
, until
- pos
);
2135 /* TODO: Also check for visible stuff like below */
2136 if (data
->entries_num
!= data
->confirm_entries_num
)
2137 set(obj
, MUIA_List_Entries
, data
->confirm_entries_num
);
2141 data
->entries
[pos
] = lentry
;
2142 data
->confirm_entries_num
++;
2144 if (_flags(obj
) & MADF_SETUP
)
2146 /* We have to calculate the width and height of the newly
2147 * inserted entry. This has to be done after inserting the
2148 * element into the list */
2149 CalcDimsOfEntry(cl
, obj
, pos
);
2154 } // while (pos < until)
2157 /* Recalculate the number of visible entries */
2158 if (_flags(obj
) & MADF_SETUP
)
2159 CalcVertVisible(cl
, obj
);
2161 if (data
->entries_num
!= data
->confirm_entries_num
)
2164 MUIA_List_Entries
, data
->confirm_entries_num
,
2165 MUIA_List_Visible
, data
->entries_visible
, TAG_DONE
);
2168 /* If the array is already sorted, we could do a simple insert
2169 * sort and would be much faster than with qsort.
2170 * If an array is not yet sorted, does a MUIV_List_Insert_Sorted
2171 * sort the whole array?
2173 * I think, we better sort the whole array:
2177 DoMethod(obj
, MUIM_List_Sort
);
2178 /* TODO: which pos to return here !? */
2179 /* MUIM_List_Sort already called MUI_Redraw */
2183 if (!(data
->flags
& LIST_QUIET
))
2186 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2189 data
->insert_position
= pos
;
2194 /**************************************************************************
2195 MUIM_List_InsertSingle
2196 **************************************************************************/
2197 IPTR
List__MUIM_InsertSingle(struct IClass
*cl
, Object
*obj
,
2198 struct MUIP_List_InsertSingle
*msg
)
2200 return DoMethod(obj
, MUIM_List_Insert
, (IPTR
) & msg
->entry
, 1,
2204 /**************************************************************************
2206 **************************************************************************/
2207 IPTR
List__MUIM_GetEntry(struct IClass
*cl
, Object
*obj
,
2208 struct MUIP_List_GetEntry
*msg
)
2210 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2213 if (pos
== MUIV_List_GetEntry_Active
)
2214 pos
= data
->entries_active
;
2216 if (pos
< 0 || pos
>= data
->entries_num
)
2221 *msg
->entry
= data
->entries
[pos
]->data
;
2222 return (IPTR
) *msg
->entry
;
2225 /**************************************************************************
2227 **************************************************************************/
2228 IPTR
List__MUIM_Construct(struct IClass
*cl
, Object
*obj
,
2229 struct MUIP_List_Construct
*msg
)
2231 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2233 if (NULL
== data
->construct_hook
)
2234 return (IPTR
) msg
->entry
;
2235 if ((IPTR
) data
->construct_hook
== MUIV_List_ConstructHook_String
)
2237 int len
= msg
->entry
? strlen((STRPTR
) msg
->entry
) : 0;
2238 ULONG
*mem
= AllocPooled(msg
->pool
, len
+ 5);
2243 if (msg
->entry
!= NULL
)
2244 strcpy((STRPTR
) (mem
+ 1), (STRPTR
) msg
->entry
);
2246 *(STRPTR
) (mem
+ 1) = 0;
2247 return (IPTR
) (mem
+ 1);
2249 return CallHookPkt(data
->construct_hook
, msg
->pool
, msg
->entry
);
2252 /**************************************************************************
2254 **************************************************************************/
2255 IPTR
List__MUIM_Destruct(struct IClass
*cl
, Object
*obj
,
2256 struct MUIP_List_Destruct
*msg
)
2258 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2260 if (NULL
== data
->destruct_hook
)
2263 if ((IPTR
) data
->destruct_hook
== MUIV_List_DestructHook_String
)
2265 ULONG
*mem
= ((ULONG
*) msg
->entry
) - 1;
2266 FreePooled(msg
->pool
, mem
, mem
[0]);
2270 CallHookPkt(data
->destruct_hook
, msg
->pool
, msg
->entry
);
2275 /**************************************************************************
2277 **************************************************************************/
2278 IPTR
List__MUIM_Compare(struct IClass
*cl
, Object
*obj
,
2279 struct MUIP_List_Compare
*msg
)
2281 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2283 return CallHookPkt(data
->compare_hook
, msg
->entry2
, msg
->entry1
);
2286 /**************************************************************************
2288 **************************************************************************/
2289 IPTR
List__MUIM_Display(struct IClass
*cl
, Object
*obj
,
2290 struct MUIP_List_Display
*msg
)
2292 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2294 if (NULL
== data
->display_hook
)
2297 *msg
->array
= msg
->entry
;
2303 *((ULONG
*) (msg
->array
- 1)) = msg
->entry_pos
;
2304 return CallHookPkt(data
->display_hook
, msg
->array
, msg
->entry
);
2307 /**************************************************************************
2308 MUIM_List_SelectChange
2309 **************************************************************************/
2310 IPTR
List__MUIM_SelectChange(struct IClass
*cl
, Object
*obj
,
2311 struct MUIP_List_SelectChange
*msg
)
2316 /**************************************************************************
2317 MUIM_List_CreateImage
2318 Called by a List subclass in its Setup method.
2319 Connects an Area subclass object to the list, much like an object gets
2320 connected to a window. List calls Setup and AskMinMax on that object,
2321 keeps a reference to it (that reference will be returned).
2322 Text engine will dereference that pointer and draw the object with its
2324 **************************************************************************/
2325 IPTR
List__MUIM_CreateImage(struct IClass
*cl
, Object
*obj
,
2326 struct MUIP_List_CreateImage
*msg
)
2328 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2329 struct ListImage
*li
;
2331 /* List must be already setup in Setup of your subclass */
2332 if (!(_flags(obj
) & MADF_SETUP
))
2334 li
= AllocPooled(data
->pool
, sizeof(struct ListImage
));
2339 AddTail((struct List
*)&data
->images
, (struct Node
*)li
);
2340 DoMethod(li
->obj
, MUIM_ConnectParent
, (IPTR
) obj
);
2341 DoSetupMethod(li
->obj
, muiRenderInfo(obj
));
2347 /**************************************************************************
2348 MUIM_List_DeleteImage
2349 **************************************************************************/
2350 IPTR
List__MUIM_DeleteImage(struct IClass
*cl
, Object
*obj
,
2351 struct MUIP_List_DeleteImage
*msg
)
2353 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2354 struct ListImage
*li
= (struct ListImage
*)msg
->listimg
;
2358 DoMethod(li
->obj
, MUIM_Cleanup
);
2359 DoMethod(li
->obj
, MUIM_DisconnectParent
);
2360 Remove((struct Node
*)li
);
2361 FreePooled(data
->pool
, li
, sizeof(struct ListImage
));
2367 /**************************************************************************
2369 **************************************************************************/
2370 IPTR
List__MUIM_Jump(struct IClass
*cl
, Object
*obj
,
2371 struct MUIP_List_Jump
*msg
)
2373 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2374 LONG pos
= msg
->pos
;
2378 case MUIV_List_Jump_Top
:
2382 case MUIV_List_Jump_Active
:
2383 pos
= data
->entries_active
;
2386 case MUIV_List_Jump_Bottom
:
2387 pos
= data
->entries_num
- 1;
2390 case MUIV_List_Jump_Down
:
2391 pos
= data
->entries_first
+ data
->entries_visible
;
2394 case MUIV_List_Jump_Up
:
2395 pos
= data
->entries_first
- 1;
2400 if (pos
> data
->entries_num
)
2402 pos
= data
->entries_num
- 1;
2407 if (pos
< data
->entries_first
)
2409 set(obj
, MUIA_List_First
, pos
);
2411 else if (pos
>= data
->entries_first
+ data
->entries_visible
)
2413 pos
-= (data
->entries_visible
- 1);
2416 if (pos
!= data
->entries_first
)
2418 set(obj
, MUIA_List_First
, pos
);
2426 /**************************************************************************
2428 **************************************************************************/
2429 IPTR
List__MUIM_Sort(struct IClass
*cl
, Object
*obj
,
2430 struct MUIP_List_Sort
*msg
)
2432 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2435 struct MUIP_List_Compare cmpmsg
=
2436 { MUIM_List_Compare
, NULL
, NULL
, 0, 0 };
2438 if (data
->entries_num
> 1)
2441 Simple sort algorithm. Feel free to improve it.
2443 for (i
= 0; i
< data
->entries_num
- 1; i
++)
2446 for (j
= i
+ 1; j
< data
->entries_num
; j
++)
2448 cmpmsg
.entry1
= data
->entries
[max
]->data
;
2449 cmpmsg
.entry2
= data
->entries
[j
]->data
;
2450 if ((LONG
) DoMethodA(obj
, (Msg
) & cmpmsg
) > 0)
2457 APTR tmp
= data
->entries
[i
];
2458 data
->entries
[i
] = data
->entries
[max
];
2459 data
->entries
[max
] = tmp
;
2464 if (!(data
->flags
& LIST_QUIET
))
2467 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2473 /**************************************************************************
2475 **************************************************************************/
2476 IPTR
List__MUIM_Move(struct IClass
*cl
, Object
*obj
,
2477 struct MUIP_List_Move
*msg
)
2479 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2486 case MUIV_List_Move_Top
:
2489 case MUIV_List_Move_Active
:
2490 from
= data
->entries_active
;
2492 case MUIV_List_Move_Bottom
:
2493 from
= data
->entries_num
- 1;
2501 case MUIV_List_Move_Top
:
2504 case MUIV_List_Move_Active
:
2505 to
= data
->entries_active
;
2507 case MUIV_List_Move_Bottom
:
2508 to
= data
->entries_num
- 1;
2510 case MUIV_List_Move_Next
:
2513 case MUIV_List_Move_Previous
:
2520 if (from
> data
->entries_num
- 1 || from
< 0
2521 || to
> data
->entries_num
- 1 || to
< 0 || from
== to
)
2522 return (IPTR
) FALSE
;
2526 struct ListEntry
*backup
= data
->entries
[from
];
2527 for (i
= from
; i
< to
; i
++)
2528 data
->entries
[i
] = data
->entries
[i
+ 1];
2529 data
->entries
[to
] = backup
;
2533 struct ListEntry
*backup
= data
->entries
[from
];
2534 for (i
= from
; i
> to
; i
--)
2535 data
->entries
[i
] = data
->entries
[i
- 1];
2536 data
->entries
[to
] = backup
;
2540 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2545 /**************************************************************************
2546 MUIM_List_NextSelected
2547 **************************************************************************/
2548 IPTR
List__MUIM_NextSelected(struct IClass
*cl
, Object
*obj
,
2549 struct MUIP_List_NextSelected
*msg
)
2551 struct MUI_ListData
*data
= INST_DATA(cl
, obj
);
2555 /* Get the first entry to check */
2557 if (pos
== MUIV_List_NextSelected_Start
)
2562 /* Find the next selected entry */
2563 for (i
= pos
; i
< data
->entries_num
&& !found
; i
++)
2565 if (data
->entries
[i
]->flags
& ENTRY_SELECTED
)
2572 /* Return index of selected entry, or indicate there are no more */
2574 pos
= MUIV_List_NextSelected_End
;
2580 /**************************************************************************
2582 **************************************************************************/
2583 BOOPSI_DISPATCHER(IPTR
, List_Dispatcher
, cl
, obj
, msg
)
2585 switch (msg
->MethodID
)
2588 return List__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
2590 return List__OM_DISPOSE(cl
, obj
, msg
);
2592 return List__OM_SET(cl
, obj
, (struct opSet
*)msg
);
2594 return List__OM_GET(cl
, obj
, (struct opGet
*)msg
);
2597 return List__MUIM_Setup(cl
, obj
, (struct MUIP_Setup
*)msg
);
2599 return List__MUIM_Cleanup(cl
, obj
, (struct MUIP_Cleanup
*)msg
);
2600 case MUIM_AskMinMax
:
2601 return List__MUIM_AskMinMax(cl
, obj
, (struct MUIP_AskMinMax
*)msg
);
2603 return List__MUIM_Show(cl
, obj
, (struct MUIP_Show
*)msg
);
2605 return List__MUIM_Hide(cl
, obj
, (struct MUIP_Hide
*)msg
);
2607 return List__MUIM_Draw(cl
, obj
, (struct MUIP_Draw
*)msg
);
2609 return List__MUIM_Layout(cl
, obj
, (struct MUIP_Layout
*)msg
);
2610 case MUIM_HandleEvent
:
2611 return List__MUIM_HandleEvent(cl
, obj
,
2612 (struct MUIP_HandleEvent
*)msg
);
2613 case MUIM_List_Clear
:
2614 return List__MUIM_Clear(cl
, obj
, (struct MUIP_List_Clear
*)msg
);
2615 case MUIM_List_Sort
:
2616 return List__MUIM_Sort(cl
, obj
, (struct MUIP_List_Sort
*)msg
);
2617 case MUIM_List_Exchange
:
2618 return List__MUIM_Exchange(cl
, obj
,
2619 (struct MUIP_List_Exchange
*)msg
);
2620 case MUIM_List_Insert
:
2621 return List__MUIM_Insert(cl
, obj
, (APTR
) msg
);
2622 case MUIM_List_InsertSingle
:
2623 return List__MUIM_InsertSingle(cl
, obj
, (APTR
) msg
);
2624 case MUIM_List_GetEntry
:
2625 return List__MUIM_GetEntry(cl
, obj
, (APTR
) msg
);
2626 case MUIM_List_Redraw
:
2627 return List__MUIM_Redraw(cl
, obj
, (APTR
) msg
);
2628 case MUIM_List_Remove
:
2629 return List__MUIM_Remove(cl
, obj
, (APTR
) msg
);
2630 case MUIM_List_Select
:
2631 return List__MUIM_Select(cl
, obj
, (APTR
) msg
);
2632 case MUIM_List_Construct
:
2633 return List__MUIM_Construct(cl
, obj
, (APTR
) msg
);
2634 case MUIM_List_Destruct
:
2635 return List__MUIM_Destruct(cl
, obj
, (APTR
) msg
);
2636 case MUIM_List_Compare
:
2637 return List__MUIM_Compare(cl
, obj
, (APTR
) msg
);
2638 case MUIM_List_Display
:
2639 return List__MUIM_Display(cl
, obj
, (APTR
) msg
);
2640 case MUIM_List_SelectChange
:
2641 return List__MUIM_SelectChange(cl
, obj
, (APTR
) msg
);
2642 case MUIM_List_CreateImage
:
2643 return List__MUIM_CreateImage(cl
, obj
, (APTR
) msg
);
2644 case MUIM_List_DeleteImage
:
2645 return List__MUIM_DeleteImage(cl
, obj
, (APTR
) msg
);
2646 case MUIM_List_Jump
:
2647 return List__MUIM_Jump(cl
, obj
, (APTR
) msg
);
2648 case MUIM_List_Move
:
2649 return List__MUIM_Move(cl
, obj
, (struct MUIP_List_Move
*)msg
);
2650 case MUIM_List_NextSelected
:
2651 return List__MUIM_NextSelected(cl
, obj
,
2652 (struct MUIP_List_NextSelected
*)msg
);
2655 return DoSuperMethodA(cl
, obj
, msg
);
2657 BOOPSI_DISPATCHER_END
2662 const struct __MUIBuiltinClass _MUI_List_desc
=
2666 sizeof(struct MUI_ListData
),
2667 (void *) List_Dispatcher