Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / muimaster / classes / text.c
blobc9130c4b1653cca3117d3a7342d5f037c54c15d8
1 /*
2 Copyright 1999, David Le Corfec.
3 Copyright 2002-2006, The AROS Development Team.
4 All rights reserved.
6 $Id$
7 */
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <exec/types.h>
14 #include <clib/alib_protos.h>
15 #include <proto/exec.h>
16 #include <proto/intuition.h>
17 #include <proto/graphics.h>
18 #include <proto/utility.h>
19 #include <proto/dos.h>
20 #include <proto/muimaster.h>
22 #include "mui.h"
23 #include "muimaster_intern.h"
24 #include "support.h"
25 #include "textengine.h"
27 extern struct Library *MUIMasterBase;
29 //#define MYDEBUG 1
30 #include "debug.h"
33 struct MUI_TextData {
34 ULONG mtd_Flags;
35 STRPTR contents;
36 CONST_STRPTR preparse;
37 TEXT hichar;
38 ZText *ztext;
39 LONG xpixel; /* needed for cursor up/down movements, can be -1 */
40 LONG xpos;
41 LONG ypos;
42 struct MUI_EventHandlerNode ehn;
44 LONG update; /* type of update 1 - everything, 2 - insert char, no scroll */
45 LONG update_arg1;
46 LONG update_arg2;
49 #define MTDF_SETMIN (1<<0)
50 #define MTDF_SETMAX (1<<1)
51 #define MTDF_SETVMAX (1<<2)
52 #define MTDF_HICHAR (1<<3)
53 #define MTDF_HICHARIDX (1<<4)
54 #if 0
55 #define MTDF_EDITABLE (1<<5)
56 #define MTDF_MULTILINE (1<<6)
57 #endif
58 #define MTDF_ADVANCEONCR (1<<7)
60 static const int __version = 1;
61 static const int __revision = 1;
63 static void setup_text (struct MUI_TextData *data, Object *obj);
65 /**************************************************************************
66 OM_NEW
67 **************************************************************************/
68 IPTR Text__OM_NEW(struct IClass *cl, Object *obj, struct opSet *msg)
70 struct MUI_TextData *data;
71 struct TagItem *tags,*tag;
73 obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg);
74 if (!obj)
75 return FALSE;
77 data = INST_DATA(cl, obj);
78 data->mtd_Flags = MTDF_SETMIN | MTDF_SETVMAX;
80 /* parse initial taglist */
82 for (tags = msg->ops_AttrList; (tag = NextTagItem((const struct TagItem **)&tags)); )
84 switch (tag->ti_Tag)
86 case MUIA_Text_Contents:
87 if (tag->ti_Data) data->contents = StrDup((STRPTR)tag->ti_Data);
88 break;
90 case MUIA_Text_HiChar:
91 data->hichar = tag->ti_Data;
92 _handle_bool_tag(data->mtd_Flags, tag->ti_Data, MTDF_HICHAR);
93 break;
95 case MUIA_Text_HiCharIdx:
96 data->hichar = tag->ti_Data;
97 _handle_bool_tag(data->mtd_Flags, tag->ti_Data, MTDF_HICHARIDX);
98 break;
100 case MUIA_Text_PreParse:
101 data->preparse = StrDup((STRPTR)tag->ti_Data);
102 break;
104 case MUIA_Text_SetMin:
105 _handle_bool_tag(data->mtd_Flags, tag->ti_Data, MTDF_SETMIN);
106 break;
108 case MUIA_Text_SetMax:
109 _handle_bool_tag(data->mtd_Flags, tag->ti_Data, MTDF_SETMAX);
110 break;
112 case MUIA_Text_SetVMax:
113 _handle_bool_tag(data->mtd_Flags, tag->ti_Data, MTDF_SETVMAX);
114 break;
116 #if 0
117 case MUIA_Text_Editable:
118 _handle_bool_tag(data->mtd_Flags, tag->ti_Data, MTDF_EDITABLE);
119 break;
121 case MUIA_Text_Multiline:
122 _handle_bool_tag(data->mtd_Flags, tag->ti_Data, MTDF_MULTILINE);
123 break;
124 #endif
128 if (!data->preparse) data->preparse = StrDup("");
129 if (!data->contents) data->contents = StrDup("");
131 if (!data->contents || !data->preparse)
133 CoerceMethod(cl, obj, OM_DISPOSE);
134 return (IPTR)NULL;
137 /* D(bug("Text_New(0x%lx)\n", obj)); */
139 data->ehn.ehn_Events = IDCMP_MOUSEBUTTONS;
140 data->ehn.ehn_Priority = 0;
141 data->ehn.ehn_Flags = 0;
142 data->ehn.ehn_Object = obj;
143 data->ehn.ehn_Class = cl;
145 data->xpixel = -1;
147 return (IPTR)obj;
150 /**************************************************************************
151 OM_DISPOSE
152 **************************************************************************/
153 IPTR Text__OM_DISPOSE(struct IClass *cl, Object *obj, Msg msg)
155 struct MUI_TextData *data = INST_DATA(cl, obj);
157 FreeVec(data->contents);
158 FreeVec((APTR)data->preparse);
160 return DoSuperMethodA(cl, obj, msg);
163 /**************************************************************************
164 OM_SET
165 **************************************************************************/
166 IPTR Text__OM_SET(struct IClass *cl, Object *obj, struct opSet *msg)
168 struct MUI_TextData *data = INST_DATA(cl, obj);
169 struct TagItem *tags = msg->ops_AttrList;
170 struct TagItem *tag;
172 while ((tag = NextTagItem((const struct TagItem **)&tags)) != NULL)
174 switch (tag->ti_Tag)
176 case MUIA_Text_Contents:
178 char *new_contents = StrDup(((char*)tag->ti_Data)?(char*)tag->ti_Data:"");
179 if (new_contents)
181 if (data->ztext)
183 zune_text_destroy(data->ztext);
184 data->ztext = NULL;
186 FreeVec(data->contents);
187 data->contents = new_contents;
188 if (_flags(obj) & MADF_SETUP) setup_text(data, obj);
189 MUI_Redraw(obj,MADF_DRAWOBJECT); /* should be optimized */
192 break;
194 case MUIA_Text_PreParse:
196 char *new_preparse = StrDup(((char*)tag->ti_Data)?(char*)tag->ti_Data:"");
197 if (new_preparse)
199 if (data->ztext)
201 zune_text_destroy(data->ztext);
202 data->ztext = NULL;
204 FreeVec((APTR)data->preparse);
205 data->preparse = new_preparse;
206 if (_flags(obj) & MADF_SETUP) setup_text(data, obj);
207 MUI_Redraw(obj,MADF_DRAWOBJECT); /* should be opimized */
210 break;
212 case MUIA_Selected:
213 D(bug("Text_Set(%p) : MUIA_Selected val=%ld sss=%d\n", obj, tag->ti_Data, !!(_flags(obj) & MADF_SHOWSELSTATE)));
214 break;
218 return DoSuperMethodA(cl, obj, (Msg)msg);
222 /**************************************************************************
223 OM_GET
224 **************************************************************************/
225 IPTR Text__OM_GET(struct IClass *cl, Object *obj, struct opGet *msg)
227 struct MUI_TextData *data = INST_DATA(cl, obj);
229 #define STORE *(msg->opg_Storage)
230 switch(msg->opg_AttrID)
232 case MUIA_Text_Contents:
233 STORE = (IPTR)data->contents;
234 return TRUE;
236 case MUIA_Text_PreParse:
237 STORE = (IPTR)data->preparse;
238 return TRUE;
240 case MUIA_Version:
241 STORE = __version;
242 return TRUE;
244 case MUIA_Revision:
245 STORE = __revision;
246 return TRUE;
248 return DoSuperMethodA(cl, obj, (Msg) msg);
249 #undef STORE
252 /**************************************************************************
254 **************************************************************************/
255 static void setup_text (struct MUI_TextData *data, Object *obj)
257 if (data->mtd_Flags & MTDF_HICHAR)
259 data->ztext = zune_text_new(data->preparse, data->contents,
260 ZTEXT_ARG_HICHAR, data->hichar);
262 else if (data->mtd_Flags & MTDF_HICHARIDX)
264 data->ztext = zune_text_new(data->preparse, data->contents,
265 ZTEXT_ARG_HICHARIDX, data->hichar);
267 else
269 data->ztext = zune_text_new(data->preparse, data->contents,
270 ZTEXT_ARG_NONE, 0);
272 zune_text_get_bounds(data->ztext, obj);
274 /* D(bug("muimaster.library/text.c: ZText of 0x%lx at 0x%lx\n",obj,data->ztext)); */
277 /**************************************************************************
278 MUIM_Setup
279 **************************************************************************/
280 IPTR Text__MUIM_Setup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg)
282 struct MUI_TextData *data = INST_DATA(cl, obj);
284 if (!(DoSuperMethodA(cl, obj, (Msg) msg)))
285 return FALSE;
287 setup_text(data, obj);
289 DoMethod(_win(obj), MUIM_Window_AddEventHandler, (IPTR)&data->ehn);
290 return TRUE;
293 /**************************************************************************
294 MUIM_Cleanup
295 **************************************************************************/
296 IPTR Text__MUIM_Cleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg)
298 struct MUI_TextData *data = INST_DATA(cl, obj);
300 DoMethod(_win(obj), MUIM_Window_RemEventHandler, (IPTR)&data->ehn);
302 if (data->ztext)
304 zune_text_destroy(data->ztext);
305 data->ztext = NULL;
308 return (DoSuperMethodA(cl, obj, (Msg) msg));
311 /**************************************************************************
312 MUIM_Show
313 **************************************************************************/
314 IPTR Text__MUIM_Show(struct IClass *cl, Object *obj, struct MUIP_Show *msg)
316 //struct MUI_TextData *data = INST_DATA(cl, obj);
318 if (!(DoSuperMethodA(cl, obj, (Msg) msg)))
319 return FALSE;
321 return TRUE;
324 /**************************************************************************
325 MUIM_Hide
326 **************************************************************************/
327 IPTR Text__MUIM_Hide(struct IClass *cl, Object *obj, struct MUIP_Hide *msg)
329 //struct MUI_TextData *data = INST_DATA(cl, obj);
330 return DoSuperMethodA(cl, obj, (Msg) msg);
333 /**************************************************************************
334 MUIM_AskMinMax
335 **************************************************************************/
336 IPTR Text__MUIM_AskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg)
338 int height;
339 struct MUI_TextData *data = INST_DATA(cl, obj);
341 DoSuperMethodA(cl, obj, (Msg)msg);
343 height = data->ztext->height;
344 if (_font(obj)->tf_YSize > height) height = _font(obj)->tf_YSize;
345 /* D(bug("YSize=%ld\n", _font(obj)->tf_YSize)); */
347 #if 0
348 if (!(data->mtd_Flags & MTDF_EDITABLE))
349 #endif
351 msg->MinMaxInfo->MinWidth += data->ztext->width;
352 msg->MinMaxInfo->DefWidth += data->ztext->width;
353 msg->MinMaxInfo->MaxWidth += data->ztext->width;
355 #if 0
356 else
358 msg->MinMaxInfo->MinWidth += _font(obj)->tf_XSize*4;
359 msg->MinMaxInfo->DefWidth += _font(obj)->tf_XSize*12;
360 msg->MinMaxInfo->MaxWidth += MUI_MAXMAX;
362 #endif
364 #if 0
365 if (!(data->mtd_Flags & MTDF_MULTILINE))
366 #endif
368 msg->MinMaxInfo->MinHeight += height;
369 msg->MinMaxInfo->DefHeight += height;
370 if (!(data->mtd_Flags & MTDF_SETVMAX))
371 msg->MinMaxInfo->MaxHeight += MUI_MAXMAX;
372 else
373 msg->MinMaxInfo->MaxHeight += height;
375 #if 0
376 else
378 msg->MinMaxInfo->MinHeight += _font(obj)->tf_YSize;
379 msg->MinMaxInfo->DefHeight += _font(obj)->tf_YSize*10;
380 msg->MinMaxInfo->MaxHeight += MUI_MAXMAX;
382 #endif
384 if (!(data->mtd_Flags & MTDF_SETMAX))
385 msg->MinMaxInfo->MaxWidth = MUI_MAXMAX;
387 if (!(data->mtd_Flags & MTDF_SETMIN))
388 msg->MinMaxInfo->MinWidth = 0;
390 D(bug("Text_AskMinMax 0x%lx (%s): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n", obj, data->contents,
391 msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight,
392 msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight,
393 msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight));
395 return TRUE;
398 /**************************************************************************
399 MUIM_Draw
400 **************************************************************************/
401 IPTR Text__MUIM_Draw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg)
403 struct MUI_TextData *data = INST_DATA(cl, obj);
404 Object *act;
405 APTR clip;
407 /* D(bug("muimaster.library/text.c: Draw Text Object at 0x%lx %ldx%ldx%ldx%ld\n",obj,_left(obj),_top(obj),_right(obj),_bottom(obj))); */
409 DoSuperMethodA(cl,obj,(Msg)msg);
411 if ((msg->flags & MADF_DRAWUPDATE) && !data->update)
412 return 0;
414 if (!(msg->flags & MADF_DRAWUPDATE)) data->update = 0;
416 if (msg->flags & MADF_DRAWUPDATE && data->update == 1)
418 DoMethod(obj,MUIM_DrawBackground, _mleft(obj),_mtop(obj),_mwidth(obj),_mheight(obj), _mleft(obj), _mtop(obj), 0);
421 clip = MUI_AddClipping(muiRenderInfo(obj), _mleft(obj), _mtop(obj),
422 _mwidth(obj), _mheight(obj));
424 SetAPen(_rp(obj), _pens(obj)[MPEN_TEXT]);
427 get(_win(obj),MUIA_Window_ActiveObject,&act);
429 int y = (_mheight(obj) - data->ztext->height) / 2;
430 zune_text_draw(data->ztext, obj,
431 _mleft(obj), _mright(obj),
432 _mtop(obj) + y);
436 MUI_RemoveClipping(muiRenderInfo(obj), clip);
437 data->update = 0;
438 return TRUE;
441 /**************************************************************************
442 MUIM_Export : to export an objects "contents" to a dataspace object.
443 **************************************************************************/
444 IPTR Text__MUIM_Export(struct IClass *cl, Object *obj, struct MUIP_Export *msg)
446 //struct MUI_TextData *data = INST_DATA(cl, obj);
447 //STRPTR id;
449 #if 0
450 if ((id = muiNotifyData(obj)->mnd_ObjectID))
452 DoMethod(msg->dataspace, MUIM_Dataspace_AddString,
453 _U(id), _U("contents"), _U(data->contents));
455 #endif
456 return 0;
460 /**************************************************************************
461 MUIM_Import : to import an objects "contents" from a dataspace object.
462 **************************************************************************/
463 IPTR Text__MUIM_Import(struct IClass *cl, Object *obj, struct MUIP_Import *msg)
465 //STRPTR id;
466 //STRPTR s;
468 #if 0
469 if ((id = muiNotifyData(obj)->mnd_ObjectID))
471 if ((s = (STRPTR)DoMethod(msg->dataspace, MUIM_Dataspace_FindString,
472 _U(id), _U("contents"))))
474 set(obj, MUIA_Text_Contents, _U(s));
477 #endif
478 return 0;
482 BOOPSI_DISPATCHER(IPTR, Text_Dispatcher, cl, obj, msg)
484 switch (msg->MethodID)
486 case OM_NEW: return Text__OM_NEW(cl, obj, (struct opSet *) msg);
487 case OM_DISPOSE: return Text__OM_DISPOSE(cl, obj, msg);
488 case OM_SET: return Text__OM_SET(cl, obj, (struct opSet *)msg);
489 case OM_GET: return Text__OM_GET(cl, obj, (struct opGet *)msg);
491 case MUIM_AskMinMax: return Text__MUIM_AskMinMax(cl, obj, (APTR)msg);
492 case MUIM_Draw: return Text__MUIM_Draw(cl, obj, (APTR)msg);
493 case MUIM_Setup: return Text__MUIM_Setup(cl, obj, (APTR)msg);
494 case MUIM_Cleanup: return Text__MUIM_Cleanup(cl, obj, (APTR)msg);
495 case MUIM_Show: return Text__MUIM_Show(cl, obj, (APTR)msg);
496 case MUIM_Hide: return Text__MUIM_Hide(cl, obj, (APTR)msg);
497 case MUIM_Export: return Text__MUIM_Export(cl, obj, (APTR)msg);
498 case MUIM_Import: return Text__MUIM_Import(cl, obj, (APTR)msg);
501 return DoSuperMethodA(cl, obj, msg);
503 BOOPSI_DISPATCHER_END
508 * Class descriptor.
510 const struct __MUIBuiltinClass _MUI_Text_desc = {
511 MUIC_Text,
512 MUIC_Area,
513 sizeof(struct MUI_TextData),
514 (void*)Text_Dispatcher