Initial commit
[amiga/OpenBoopsi.git] / gadgets / ListView / ListViewHooks.c
1 /*
2 **      $Id: ListViewHooks.c,v 1.3 2000/01/12 21:18:07 bernie Exp $
3 **
4 **      Copyright (C) 1996,97 Bernardo Innocenti
5 **
6 **      Use 4 chars wide TABs to read this file
7 **
8 **      Internal drawing and browsing hooks the listview class
9 */
10
11 #define USE_BUILTIN_MATH
12 #define INTUI_V36_NAMES_ONLY
13 #define __USE_SYSBASE
14 #define  CLIB_ALIB_PROTOS_H             /* Avoid dupe defs of boopsi funcs */
15
16 #include <exec/types.h>
17 #include <intuition/intuition.h>
18 #include <intuition/intuitionbase.h>
19 #include <graphics/gfxbase.h>
20 #include <graphics/gfxmacros.h>
21
22 #include <proto/intuition.h>
23 #include <proto/graphics.h>
24
25 #ifdef __STORM__
26         #pragma header
27 #endif
28
29 #define LV_GADTOOLS_STUFF
30 #include <gadgets/ListViewClass.h>
31
32 #include <CompilerSpecific.h>
33 #include <DebugMacros.h>
34
35
36
37 /* Definitions for builtin List hook */
38
39 APTR HOOKCALL ListGetItem(
40         REG(a0, struct Hook                     *hook),
41         REG(a1, struct Node                     *node),
42         REG(a2, struct lvGetItem        *lvgi));
43 APTR HOOKCALL ListGetNext(
44         REG(a0, struct Hook                     *hook),
45         REG(a1, struct Node                     *node),
46         REG(a2, struct lvGetNext        *lvgn));
47 APTR HOOKCALL ListGetPrev(
48         REG(a0, struct Hook                     *hook),
49         REG(a1, struct Node                     *node),
50         REG(a2, struct lvGetPrev        *lvgp));
51 ULONG HOOKCALL ListStringDrawItem(
52         REG(a0, struct Hook                     *hook),
53         REG(a1, struct Node                     *node),
54         REG(a2, struct lvDrawItem       *lvdi));
55 ULONG HOOKCALL ListImageDrawItem(
56         REG(a0, struct Hook                     *hook),
57         REG(a1, struct Node                     *node),
58         REG(a2, struct lvDrawItem       *lvdi));
59
60
61 /* Definitions for builtin Array hook */
62
63 APTR HOOKCALL ArrayGetItem(
64         REG(a0, struct Hook                     *hook),
65         REG(a1, STRPTR                          *item),
66         REG(a2, struct lvGetItem        *lvgi));
67 ULONG HOOKCALL StringDrawItem(
68         REG(a0, struct Hook                     *hook),
69         REG(a1, STRPTR                           str),
70         REG(a2, struct lvDrawItem       *lvdi));
71 ULONG HOOKCALL ImageDrawItem(
72         REG(a0, struct Hook                     *hook),
73         REG(a1, struct Image            *img),
74         REG(a2, struct lvDrawItem       *lvdi));
75
76
77
78 APTR HOOKCALL ListGetItem(
79         UNUSED(REG(a0, struct Hook *hook)),
80         REG(a1, struct Node *node),
81         REG(a2, struct lvGetItem *lvg))
82 {
83         ULONG i;
84
85         ASSERT_VALID_PTR(lvg)
86
87         node = ((struct List *)(lvg->lvgi_Items))->lh_Head;
88
89         /* Warning: no sanity check is made against
90          * list being shorter than expected!
91          */
92         for (i = 0; i < lvg->lvgi_Number; i++)
93         {
94                 ASSERT_VALID_PTR(node)
95                 node = node->ln_Succ;
96         }
97
98         return (APTR)node;
99 }
100
101
102
103 APTR HOOKCALL ListGetNext(
104         UNUSED(REG(a0, struct Hook *hook)),
105         REG(a1, struct Node *node),
106         UNUSED(REG(a2, struct lvGetItem *lvg)))
107 {
108         ASSERT_VALID_PTR(node)
109         ASSERT_VALID_PTR(lvg)
110
111         return (APTR)(node->ln_Succ->ln_Succ ? node->ln_Succ : NULL);
112 }
113
114
115
116 APTR HOOKCALL ListGetPrev(
117         UNUSED(REG(a0, struct Hook *hook)),
118         REG(a1, struct Node *node),
119         UNUSED(REG(a2, struct lvGetItem *lvg)))
120 {
121         ASSERT_VALID_PTR(node)
122         ASSERT_VALID_PTR(lvg)
123
124         return (APTR)(node->ln_Pred->ln_Pred ? node->ln_Pred : NULL);
125 }
126
127
128
129 ULONG HOOKCALL ListStringDrawItem(
130         REG(a0, struct Hook *hook),
131         REG(a1, struct Node *node),
132         REG(a2, struct lvDrawItem *lvdi))
133 {
134         ASSERT_VALID_PTR(node)
135         ASSERT_VALID_PTR(lvdi)
136
137         return StringDrawItem(hook, node->ln_Name, lvdi);
138 }
139
140
141
142 ULONG HOOKCALL ListImageDrawItem(
143         REG(a0, struct Hook *hook),
144         REG(a1, struct Node *node),
145         REG(a2, struct lvDrawItem *lvdi))
146 {
147         ASSERT_VALID_PTR(node)
148         ASSERT_VALID_PTR(lvdi)
149
150         return ImageDrawItem(hook, (struct Image *)node->ln_Name, lvdi);
151 }
152
153
154
155 APTR HOOKCALL ArrayGetItem(
156         UNUSED(REG(a0, struct Hook *hook)),
157         UNUSED(REG(a1, STRPTR *item)),
158         REG(a2, struct lvGetItem *lvg))
159 {
160         ASSERT_VALID_PTR(lvg)
161         ASSERT_VALID_PTR(lvg->lvgi_Items)
162
163         return (APTR)(((STRPTR *)lvg->lvgi_Items)[lvg->lvgi_Number]);
164 }
165
166
167
168 ULONG HOOKCALL StringDrawItem(
169         UNUSED(REG(a0, struct Hook *hook)),
170         REG(a1, STRPTR str),
171         REG(a2, struct lvDrawItem       *lvdi))
172 {
173         struct RastPort *rp;
174         ULONG len;
175
176         ASSERT_VALID_PTR(lvdi)
177         rp = lvdi->lvdi_RastPort;
178         ASSERT_VALID_PTR(rp)
179         ASSERT_VALID_PTR_OR_NULL(str)
180
181         if (!str)
182                 /* Move to the leftmost pixel of the rectangle
183                  * to have the following RectFill() clear all the line
184                  */
185                 Move(rp, lvdi->lvdi_Bounds.MinX, 0);
186         else
187         {
188                 struct TextExtent textent;
189
190                 if (lvdi->lvdi_State == LVR_NORMAL)
191                 {
192                         SetABPenDrMd(rp, lvdi->lvdi_DrawInfo->dri_Pens[TEXTPEN],
193                                 lvdi->lvdi_DrawInfo->dri_Pens[BACKGROUNDPEN],
194                                 JAM2);
195                 }
196                 else
197                 {
198                         SetABPenDrMd(rp, lvdi->lvdi_DrawInfo->dri_Pens[FILLTEXTPEN],
199                                 lvdi->lvdi_DrawInfo->dri_Pens[FILLPEN],
200                                 JAM2);
201                 }
202
203                 Move(rp, lvdi->lvdi_Bounds.MinX, lvdi->lvdi_Bounds.MinY + rp->Font->tf_Baseline);
204
205                 len = strlen(str);
206
207                 if (!(lvdi->lvdi_Flags & LVF_CLIPPED))
208                 {
209                         /* Calculate how much text will fit in the listview width */
210                         len = TextFit(rp, str, len, &textent, NULL, 1,
211                                 lvdi->lvdi_Bounds.MaxX - lvdi->lvdi_Bounds.MinX + 1,
212                                 lvdi->lvdi_Bounds.MaxY - lvdi->lvdi_Bounds.MinY + 1);
213                 }
214
215                 Text(rp, str, len);
216
217                 /* Text() will move the pen X position to
218                  * lvdi->lvdi_Bounds.MinX + textent.te_Width.
219                  */
220         }
221
222         /* Now clear the rest of the row. rp->cp_x is updated by Text() to the
223          * next character to print.
224          */
225         SetAPen(rp, lvdi->lvdi_DrawInfo->dri_Pens[(lvdi->lvdi_State == LVR_NORMAL) ?
226                 BACKGROUNDPEN : FILLPEN]);
227         RectFill(rp, rp->cp_x,
228                 lvdi->lvdi_Bounds.MinY,
229                 lvdi->lvdi_Bounds.MaxX,
230                 lvdi->lvdi_Bounds.MaxY);
231
232
233         return LVCB_OK;
234 }
235
236
237
238 ULONG HOOKCALL ImageDrawItem(
239         UNUSED(REG(a0, struct Hook *hook)),
240         REG(a1, struct Image *img),
241         REG(a2, struct lvDrawItem *lvdi))
242 {
243         struct RastPort *rp;
244         UWORD left;
245
246         ASSERT_VALID_PTR_OR_NULL(img)
247         ASSERT_VALID_PTR(lvdi)
248         rp = lvdi->lvdi_RastPort;
249         ASSERT_VALID_PTR(rp)
250
251         if (!img)
252                 /* Move to the leftmost pixel of the item rectangle
253                  * to have the following RectFill() clear all the line
254                  */
255                 left = lvdi->lvdi_Bounds.MinX;
256         else
257         {
258                 DrawImageState(rp, img,
259                         lvdi->lvdi_Bounds.MinX, lvdi->lvdi_Bounds.MinY,
260                         lvdi->lvdi_State, lvdi->lvdi_DrawInfo);
261
262                 left = lvdi->lvdi_Bounds.MinX + img->Width;
263         }
264
265         /* Now clear the rest of the row. rp->cp_x is updated by Text() to the
266          * next character to print.
267          */
268         SetAPen(rp, lvdi->lvdi_DrawInfo->dri_Pens[(lvdi->lvdi_State == LVR_NORMAL) ?
269                 BACKGROUNDPEN : FILLPEN]);
270         RectFill(rp, left,
271                 lvdi->lvdi_Bounds.MinY,
272                 lvdi->lvdi_Bounds.MaxX,
273                 lvdi->lvdi_Bounds.MaxY);
274
275         return LVCB_OK;
276 }