2 Copyright © 2003-2006, The AROS Development Team. All rights reserved.
6 /* This is based on muimaster/class/text.c (first string version)
7 * and on rom/intuition/str*.c
10 #define MUIMASTER_YES_INLINE_STDARG
17 #include <exec/types.h>
18 #include <clib/alib_protos.h>
20 #include <proto/exec.h>
21 #include <proto/dos.h>
22 #include <proto/graphics.h>
23 #include <proto/intuition.h>
24 #include <proto/utility.h>
25 #include <proto/muimaster.h>
26 #include <proto/locale.h>
29 #include <devices/rawkeycodes.h>
33 #include "muimaster_intern.h"
38 #include "clipboard.h"
44 extern struct Library
*MUIMasterBase
;
46 struct MUI_StringData
{
48 CONST_STRPTR msd_Accept
; /* MUIA_String_Accept */
49 CONST_STRPTR msd_Reject
; /* MUIA_String_Reject */
51 struct Hook
*msd_EditHook
;
52 Object
*msd_AttachedList
;
53 LONG msd_RedrawReason
;
56 /* Fields mostly ripped from rom/intuition/strgadgets.c */
57 STRPTR Buffer
; /* char container */
58 ULONG BufferSize
; /* memory allocated */
59 STRPTR SecBuffer
; /* Buffer for secret string */
60 ULONG NumChars
; /* string length */
61 ULONG BufferPos
; /* cursor (insert/delete) position */
62 ULONG MarkPos
; /* cursor text marking start pos */
63 LONG DispPos
; /* leftmost visible char */
64 ULONG DispCount
; /* number of visible chars */
74 struct MUI_EventHandlerNode ehn
;
75 struct MUI_PenSpec_intern inactive_text
;
76 struct MUI_PenSpec_intern active_text
;
77 struct MUI_PenSpec_intern marked_text
;
78 struct MUI_PenSpec_intern marked_bg
;
79 struct MUI_PenSpec_intern cursor
;
84 #define MSDF_ADVANCEONCR (1<<0)
85 #define MSDF_LONELYEDITHOOK (1<<1)
86 #define MSDF_MARKING (1<<2)
87 #define MSDF_KEYMARKING (1<<3)
88 #define MSDF_NOINPUT (1<<4)
89 #define MSDF_STAYACTIVE (1<<5)
106 /**************************************************************************
107 Buffer_SetNewContents
108 Allocate memory for buffer
109 **************************************************************************/
110 static BOOL
Buffer_Alloc (struct MUI_StringData
*data
)
112 data
->Buffer
= (STRPTR
)AllocVec(data
->BufferSize
* sizeof(char), MEMF_ANY
);
113 if (NULL
== data
->Buffer
)
115 bug("MUIC_String: Can't allocate %ld bytes for buffer1\n",
116 data
->BufferSize
* sizeof(char));
119 if (data
->msd_useSecret
)
121 data
->SecBuffer
= (STRPTR
)AllocVec(data
->BufferSize
* sizeof(char), MEMF_ANY
);
122 if (NULL
== data
->SecBuffer
)
124 bug("MUIC_String: Can't allocate %ld bytes for buffer2\n",
125 data
->BufferSize
* sizeof(char));
126 FreeVec(data
->Buffer
);
134 /**************************************************************************
135 Buffer_SetNewContents
136 Initialize buffer with a string, replace former content if any
137 **************************************************************************/
138 static BOOL
Buffer_SetNewContents (struct MUI_StringData
*data
, CONST_STRPTR str
)
140 if (NULL
== data
->Buffer
)
146 if (data
->msd_useSecret
) data
->SecBuffer
[0] = 0;
151 data
->NumChars
= strlen(str
);
152 if (data
->NumChars
>= data
->BufferSize
)
153 data
->NumChars
= data
->BufferSize
- 1;
155 if (data
->msd_useSecret
)
157 strncpy(data
->SecBuffer
, str
, data
->BufferSize
);
158 data
->SecBuffer
[data
->BufferSize
- 1] = 0;
160 for (i
=0; i
< data
->NumChars
; i
++) data
->Buffer
[i
]=0x78;
161 data
->Buffer
[data
->NumChars
] = 0;
165 strncpy(data
->Buffer
, str
, data
->BufferSize
);
166 data
->Buffer
[data
->BufferSize
- 1] = 0;
170 data
->BufferPos
= data
->NumChars
;
175 /**************************************************************************
177 Add a char on cursor position
178 **************************************************************************/
179 static BOOL
Buffer_AddChar (struct MUI_StringData
*data
, unsigned char code
)
183 if (data
->Buffer
== NULL
)
186 if (data
->NumChars
+ 1 >= data
->BufferSize
)
189 if (data
->msd_useSecret
)
191 dst
= &data
->SecBuffer
[data
->BufferPos
+ 1];
193 memmove(dst
, &data
->SecBuffer
[data
->BufferPos
],
194 data
->NumChars
- data
->BufferPos
);
196 data
->Buffer
[data
->NumChars
]=0x78;
197 data
->Buffer
[data
->NumChars
+ 1]=0;
201 dst
= &data
->Buffer
[data
->BufferPos
+ 1];
203 memmove(dst
, &data
->Buffer
[data
->BufferPos
],
204 data
->NumChars
- data
->BufferPos
);
208 dst
[data
->NumChars
- data
->BufferPos
] = 0;
216 static WORD
Buffer_GetWordStartIndex(struct MUI_StringData
*data
, WORD startindex
)
218 WORD index
= startindex
;
222 if (data
->Buffer
[index
- 1] == ' ')
232 static WORD
Buffer_GetWordEndIndex(struct MUI_StringData
*data
, WORD startindex
)
234 WORD index
= startindex
;
236 while(index
< data
->NumChars
)
238 if (data
->Buffer
[index
] == ' ')
248 static WORD
Buffer_GetPrevWordIndex(struct MUI_StringData
*data
, WORD startindex
)
250 WORD index
= startindex
;
257 ((data
->Buffer
[index
- 1] == ' ') &&
258 (data
->Buffer
[index
] != ' ')))
268 static WORD
Buffer_GetSuccWordIndex(struct MUI_StringData
*data
, WORD startindex
)
270 WORD index
= startindex
;
272 while(index
< data
->NumChars
)
276 if ((index
== data
->NumChars
) ||
277 ((data
->Buffer
[index
- 1] == ' ') &&
278 (data
->Buffer
[index
] != ' ')))
287 static BOOL
Buffer_GetMarkedRange(struct MUI_StringData
*data
, WORD
*start
, WORD
*stop
)
289 WORD markstart
= data
->MarkPos
;
290 WORD markstop
= data
->BufferPos
;
292 markstart
= MIN(markstart
, data
->NumChars
);
293 markstart
= MAX(markstart
, 0);
295 markstop
= MIN(markstop
, data
->NumChars
);
296 markstop
= MAX(markstop
, 0);
298 if (markstart
> markstop
)
300 markstart
^= markstop
;
301 markstop
^= markstart
;
302 markstart
^= markstop
;
305 switch(data
->MultiClick
)
313 markstart
= Buffer_GetWordStartIndex(data
, markstart
);
314 markstop
= Buffer_GetWordEndIndex(data
, markstop
);
320 markstop
= data
->NumChars
;
325 if (markstart
== markstop
) return FALSE
;
327 if (start
) *start
= markstart
;
328 if (stop
) *stop
= markstop
;
330 //kprintf("Buffer_GetMarkedRange: returning %d .. %d\n", markstart, markstop);
335 static BOOL
Buffer_AnythingMarked(struct MUI_StringData
*data
)
337 if (!(data
->msd_Flags
& MSDF_MARKING
)) return FALSE
;
339 return Buffer_GetMarkedRange(data
, NULL
, NULL
);
342 static BOOL
Buffer_KillMarked(struct MUI_StringData
*data
)
344 WORD markstart
= data
->MarkPos
;
345 WORD markstop
= data
->BufferPos
;
348 //kprintf("\nBuffer_KillMarked 1 markpos %d bufferpos %d numchars %d\n", markstart, markstop, data->NumChars);
350 if (!(data
->msd_Flags
& MSDF_MARKING
)) return FALSE
;
352 data
->msd_Flags
&= ~MSDF_MARKING
;
354 if (!Buffer_GetMarkedRange(data
, &markstart
, &markstop
)) return FALSE
;
356 //kprintf("Buffer_KillMarked 2 markstart %d markstop %d\n", markstart, markstop);
358 if (markstart
> markstop
)
360 markstart
^= markstop
;
361 markstop
^= markstart
;
362 markstart
^= markstop
;
365 marklen
= markstop
- markstart
;
367 //kprintf("Buffer_KillMarked: markstart %d markstop %d\n", markstart, markstop);
369 memmove(&data
->Buffer
[markstart
],
370 &data
->Buffer
[markstart
+ marklen
], data
->NumChars
- markstart
- marklen
+ 1);
372 data
->NumChars
-= marklen
;
373 data
->BufferPos
= markstart
;
378 /**************************************************************************
380 **************************************************************************/
381 IPTR
String__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
383 struct MUI_StringData
*data
;
384 struct TagItem
*tags
,*tag
;
385 CONST_STRPTR str
= NULL
;
388 obj
= (Object
*)DoSuperNewTags(cl
, obj
, NULL
,
389 /* MUIA_FillArea, TRUE, */
390 TAG_MORE
, (IPTR
) msg
->ops_AttrList
);
394 data
= INST_DATA(cl
, obj
);
395 data
->msd_useSecret
= FALSE
;
396 data
->msd_Align
= MUIV_String_Format_Left
;
397 data
->BufferSize
= 80;
400 Buffer_SetNewContents(data
, ""); /* <-- isnt this pointless? */
402 /* parse initial taglist */
403 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem((const struct TagItem
**)&tags
)); )
407 case MUIA_String_Accept
:
408 data
->msd_Accept
= (CONST_STRPTR
)tag
->ti_Data
;
411 case MUIA_String_Reject
:
412 data
->msd_Reject
= (CONST_STRPTR
)tag
->ti_Data
;
415 case MUIA_String_AdvanceOnCR
:
416 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_ADVANCEONCR
);
419 case MUIA_String_AttachedList
:
420 data
->msd_AttachedList
= (Object
*)tag
->ti_Data
;
423 case MUIA_String_Secret
:
424 data
->msd_useSecret
= (BOOL
)tag
->ti_Data
;
427 case MUIA_String_Contents
:
428 str
= (CONST_STRPTR
)tag
->ti_Data
;
431 case MUIA_String_EditHook
:
432 data
->msd_EditHook
= (struct Hook
*)tag
->ti_Data
;
435 case MUIA_String_Format
:
436 data
->msd_Align
= (LONG
)tag
->ti_Data
;
439 case MUIA_String_Integer
:
440 snprintf(integerbuf
, 19, "%ld", tag
->ti_Data
);
444 case MUIA_String_LonelyEditHook
:
445 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_LONELYEDITHOOK
);
448 case MUIA_String_MaxLen
:
449 data
->BufferSize
= tag
->ti_Data
;
450 if (data
->BufferSize
< 1)
451 data
->BufferSize
= 1;
454 case MUIA_String_Columns
: /* BetterString */
455 data
->Columns
= (WORD
)tag
->ti_Data
;
458 case MUIA_String_NoInput
: /* BetterString */
459 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_NOINPUT
);
462 case MUIA_String_StayActive
: /* BetterString */
463 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_STAYACTIVE
);
469 if (Buffer_Alloc(data
))
471 Buffer_SetNewContents(data
, str
);
474 if (NULL
== data
->Buffer
)
476 CoerceMethod(cl
, obj
, OM_DISPOSE
);
480 D(bug("String_New(%p)\n",obj
));
482 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
483 data
->ehn
.ehn_Priority
= 0;
484 data
->ehn
.ehn_Flags
= 0;
485 data
->ehn
.ehn_Object
= obj
;
486 data
->ehn
.ehn_Class
= cl
;
488 CurrentTime(&data
->OldClick_Sec
, &data
->OldClick_Micro
);
493 /**************************************************************************
495 **************************************************************************/
496 IPTR
String__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
498 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
500 FreeVec(data
->Buffer
);
501 FreeVec(data
->SecBuffer
);
503 D(bug("String_Dispose %p\n", obj
));
505 return DoSuperMethodA(cl
, obj
, msg
);
508 /**************************************************************************
510 **************************************************************************/
511 IPTR
String__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
513 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
514 struct TagItem
*tags
= msg
->ops_AttrList
;
517 while ((tag
= NextTagItem((const struct TagItem
**)&tags
)) != NULL
)
521 case MUIA_String_Contents
:
522 Buffer_SetNewContents(data
, (STRPTR
)tag
->ti_Data
);
523 data
->msd_RedrawReason
= NEW_CONTENTS
;
524 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
525 MUI_Redraw(obj
, MADF_DRAWOBJECT
);
528 case MUIA_String_Accept
:
529 data
->msd_Accept
= (CONST_STRPTR
)tag
->ti_Data
;
532 case MUIA_String_Reject
:
533 data
->msd_Reject
= (CONST_STRPTR
)tag
->ti_Data
;
536 case MUIA_String_AttachedList
:
537 data
->msd_AttachedList
= (Object
*)tag
->ti_Data
;
540 case MUIA_String_Integer
:
544 snprintf(buf
, 19, "%ld", tag
->ti_Data
);
545 set(obj
, MUIA_String_Contents
, buf
);
549 case MUIA_String_AdvanceOnCR
:
550 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_ADVANCEONCR
);
553 case MUIA_String_BufferPos
:
554 data
->BufferPos
= (ULONG
)tag
->ti_Data
;
555 data
->msd_Flags
&= ~MSDF_MARKING
;
556 data
->msd_RedrawReason
= MOVE_CURSOR
;
557 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
560 case MUIA_String_DisplayPos
:
561 data
->BufferPos
= (ULONG
)tag
->ti_Data
;
562 data
->DispPos
= data
->BufferPos
; // move both pos
563 data
->msd_Flags
&= ~MSDF_MARKING
;
564 data
->msd_RedrawReason
= MOVE_CURSOR
;
565 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
568 case MUIA_String_NoInput
: /* BetterString */
569 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_NOINPUT
);
572 case MUIA_String_StayActive
: /* BetterString */
573 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_STAYACTIVE
);
576 case MUIA_String_SelectSize
: /* BetterString */
577 #warning "TODO: Implement OM_SET(MUIA_String_SelectSize)!"
583 return DoSuperMethodA(cl
, obj
, (Msg
)msg
);
587 /**************************************************************************
589 **************************************************************************/
590 IPTR
String__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
592 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
594 #define STORE *(msg->opg_Storage)
595 switch(msg
->opg_AttrID
)
597 case MUIA_String_Contents
:
598 if (data
->msd_useSecret
) STORE
= (IPTR
) data
->SecBuffer
;
599 else STORE
= (IPTR
) data
->Buffer
;
602 case MUIA_String_Secret
:
603 STORE
= (IPTR
) data
->msd_useSecret
;
606 case MUIA_String_Accept
:
607 STORE
= (IPTR
) data
->msd_Accept
;
610 case MUIA_String_Reject
:
611 STORE
= (IPTR
) data
->msd_Reject
;
614 case MUIA_String_AttachedList
:
615 STORE
= (IPTR
) data
->msd_AttachedList
;
618 case MUIA_String_Integer
:
622 get(obj
, MUIA_String_Contents
, &buf
);
626 StrToLong(buf
, &val
);
632 case MUIA_String_MaxLen
:
633 STORE
= (IPTR
) data
->BufferSize
;
636 case MUIA_String_AdvanceOnCR
:
637 STORE
= (data
->msd_Flags
& MSDF_ADVANCEONCR
) ? TRUE
: FALSE
;
640 case MUIA_String_BufferPos
:
641 STORE
= data
->BufferPos
;
644 case MUIA_String_DisplayPos
:
645 STORE
= data
->DispPos
;
648 case MUIA_String_NoInput
: /* BetterString */
649 STORE
= (data
->msd_Flags
& MSDF_NOINPUT
) ? TRUE
: FALSE
;
652 case MUIA_String_StayActive
: /* BetterString */
653 STORE
= (data
->msd_Flags
& MSDF_STAYACTIVE
) ? TRUE
: FALSE
;
656 case MUIA_String_SelectSize
: /* BetterString */
657 if (data
->msd_Flags
& MSDF_MARKING
)
659 WORD markstart
, markstop
;
661 if (Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
663 LONG size
= markstop
- markstart
;
665 if (data
->MarkPos
< data
->BufferPos
) size
= -size
;
679 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
683 /**************************************************************************
685 **************************************************************************/
686 IPTR
String__MUIM_Setup(struct IClass
*cl
, Object
*obj
, struct MUIP_Setup
*msg
)
688 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
690 if (0 == DoSuperMethodA(cl
, obj
, (Msg
) msg
))
693 data
->is_active
= FALSE
;
694 set(obj
, MUIA_Background
,
695 (IPTR
)muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
697 zune_pen_spec_to_intern(
698 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->string_text_inactive
,
699 &data
->inactive_text
);
700 zune_penspec_setup(&data
->inactive_text
, muiRenderInfo(obj
));
702 zune_pen_spec_to_intern(
703 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->string_text_active
,
705 zune_penspec_setup(&data
->active_text
, muiRenderInfo(obj
));
707 zune_pen_spec_to_intern(
708 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->string_text_marked
,
710 zune_penspec_setup(&data
->marked_text
, muiRenderInfo(obj
));
712 zune_pen_spec_to_intern(
713 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_marked
,
715 zune_penspec_setup(&data
->marked_bg
, muiRenderInfo(obj
));
717 zune_pen_spec_to_intern(
718 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->string_cursor
,
720 zune_penspec_setup(&data
->cursor
, muiRenderInfo(obj
));
722 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
726 /**************************************************************************
728 **************************************************************************/
729 IPTR
String__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
, struct MUIP_Cleanup
*msg
)
731 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
733 D(bug("String_Cleanup %p\n", obj
));
734 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
736 zune_penspec_cleanup(&data
->inactive_text
);
737 zune_penspec_cleanup(&data
->active_text
);
738 zune_penspec_cleanup(&data
->marked_text
);
739 zune_penspec_cleanup(&data
->marked_bg
);
740 zune_penspec_cleanup(&data
->cursor
);
742 return (DoSuperMethodA(cl
, obj
, (Msg
) msg
));
745 /**************************************************************************
747 **************************************************************************/
748 IPTR
String__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
, struct MUIP_AskMinMax
*msg
)
750 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
752 DoSuperMethodA(cl
, obj
, (Msg
)msg
);
754 if (data
->Columns
>= 0)
756 msg
->MinMaxInfo
->MinWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
757 msg
->MinMaxInfo
->DefWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
758 msg
->MinMaxInfo
->MaxWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
762 msg
->MinMaxInfo
->MinWidth
+= _font(obj
)->tf_XSize
* 4;
763 msg
->MinMaxInfo
->DefWidth
+= _font(obj
)->tf_XSize
* 12;
764 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
767 msg
->MinMaxInfo
->MinHeight
+= _font(obj
)->tf_YSize
;
768 msg
->MinMaxInfo
->DefHeight
+= _font(obj
)->tf_YSize
;
769 msg
->MinMaxInfo
->MaxHeight
+= _font(obj
)->tf_YSize
;
771 /* D(bug("String_AskMinMax(%p): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n", obj, */
772 /* msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight, */
773 /* msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight, */
774 /* msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight)); */
780 static WORD
MaxDispPos(struct IClass
*cl
, Object
*obj
)
782 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
783 WORD numfit
, max_disppos
, numchars
;
784 struct TextExtent te
;
787 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
789 /* D(bug("MaxDispPos(current length: %d, bufferpos=%d)\n", */
790 /* data->NumChars, data->BufferPos)); */
792 /* D(bug("cursor_at_end: %d\n", cursor_at_end)); */
794 if (cursor_at_end
) /* Cursor at end of string ? */
796 /* D(bug("Making cursor last char\n")); */
797 numchars
= data
->NumChars
+ 1; /* Take cursor into account */
799 /* This has already been done by UpdateDisp() which called us
800 strinfo->Buffer[strinfo->NumChars] = 0x20;
806 numchars
= data
->NumChars
;
809 /* Find the amount of characters that fit into the bbox, counting
810 ** from the last character in the buffer and forward,
812 numfit
= TextFit(_rp(obj
),
813 &(data
->Buffer
[numchars
- 1]),
815 -1, _mwidth(obj
), _mheight(obj
));
817 max_disppos
= numchars
- numfit
;
819 /* if ((max_disppos > 0) && (!cursor_at_end))
823 /* D(bug("Numchars w/cursor: %d, Numfit: %d, maxdisppos=%d " */
824 /* "bbox->Width = %d te->te_Width = %d\n", */
825 /* numchars, numfit, max_disppos, _mwidth(obj), te.te_Width)); */
831 static void UpdateDisp(struct IClass
*cl
, Object
*obj
)
833 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
834 struct TextExtent te
;
837 /* If the cursor is at the trailing \0, insert a SPACE instead */
838 if (data
->BufferPos
== data
->NumChars
)
839 data
->Buffer
[data
->NumChars
] = 0x20;
841 /* In this function we check if the cursor has gone outside
842 ** of the visible area (because of application setting
843 ** strinfo->BufferPos or strinfo->DispPos to a different value, or
844 ** because of user input).
845 ** This is made a bit difficult by the rule (R), that there
846 ** should NOT be available space on the right, and characters
847 ** scrolled out at the left, at the same time.
848 ** We have 3 possible scenarios:
849 ** 1) Cursor to the left of DispPos:
850 ** Set DispPos to the lowest of BufferPos and the
851 ** maximum allowed disppos (according to (R) ).
852 ** 2) Cursor to the right of visible area:
853 ** Set dispose sou that the cursor is the last visible character.
854 ** This afheres to (R).
855 ** 3) Cursor inside visible area. Do a check on rule (R),
856 ** and if DispPos > max allowed, then adjust it down,
857 ** so that the last character in the buffer becomes last character
858 ** displayed. (The cursor will still be visible after adjustion)
861 /* 1) Cursor to the left of visible area */
862 if (data
->BufferPos
< data
->DispPos
)
866 max_disppos
= MaxDispPos(cl
, obj
);
867 data
->DispPos
= MIN(data
->BufferPos
, max_disppos
);
869 else /* Cursor equal to the right of disppos [ 2) or 3) ] */
873 /* How many pixels are there from current 1st displayed to the cursor ? */
874 strsize
= TextLength(_rp(obj
),
875 data
->Buffer
+ data
->DispPos
,
876 data
->BufferPos
- data
->DispPos
+ 1);
878 /* 2) More than fits into the gadget ? */
879 if (strsize
> _mwidth(obj
))
881 /* Compute new DispPos such that the cursor is at the right */
882 data
->DispPos
= data
->BufferPos
884 &(data
->Buffer
[data
->BufferPos
]),
885 data
->NumChars
, &te
, NULL
, -1,
886 _mwidth(obj
), _mheight(obj
))
889 /* D(bug("cursor right of visible area, new disppos: %d\n", data->DispPos)); */
891 else /* 3). Cursor inside gadget */
895 max_disppos
= MaxDispPos(cl
, obj
);
896 if (data
->DispPos
> max_disppos
)
897 data
->DispPos
= max_disppos
;
899 } /* if (cursor inside or to the right of visible area )*/
903 /* Update the DispCount */
904 /* It might be necessary with special handling for centre aligned gads */
905 dispstr
= &(data
->Buffer
[data
->DispPos
]);
906 /* D(bug("DispCount before = %d\n", data->DispCount)); */
907 data
->DispCount
= TextFit(_rp(obj
), dispstr
,
908 data
->NumChars
- data
->DispPos
,
912 /* D(bug("DispCount after = %d\n", data->DispCount)); */
914 /* 0-terminate string */
915 data
->Buffer
[data
->NumChars
] = 0x00;
919 /* Gets left position of text in the string gadget */
920 static UWORD
GetTextLeft(struct IClass
*cl
, Object
*obj
)
922 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
924 STRPTR dispstr
= &(data
->Buffer
[data
->DispPos
]);
928 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
929 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
931 switch (data
->msd_Align
)
933 case MUIV_String_Format_Left
:
934 text_left
= _mleft(obj
);
937 case MUIV_String_Format_Center
: {
938 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
939 if (cursor_at_end
) textwidth
+= TextLength(_rp(obj
), " ", 1);
940 text_left
= _mleft(obj
) + ((_mwidth(obj
) - textwidth
) / 2);
941 /* D(bug("GetTextLeft: dispstr=%s, dispstrlen=%d, textw=%d, textl=%d\n", */
942 /* dispstr, dispstrlen, textwidth, text_left)); */
945 case MUIV_String_Format_Right
: {
946 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
948 if (cursor_at_end
) textwidth
+= TextLength(_rp(obj
), " ", 1);
949 text_left
= _mleft(obj
) + (_mwidth(obj
) - 1 - textwidth
);
955 /* Gets right offset of text in the string gadget */
956 static UWORD
GetTextRight(struct IClass
*cl
, Object
*obj
)
958 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
959 UWORD text_right
= 0;
960 STRPTR dispstr
= &(data
->Buffer
[data
->DispPos
]);
964 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
965 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
967 switch (data
->msd_Align
)
969 case MUIV_String_Format_Left
:
970 text_right
= _mleft(obj
) + TextLength(_rp(obj
), dispstr
, dispstrlen
);
973 case MUIV_String_Format_Center
: {
974 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
976 if (cursor_at_end
) textwidth
+= TextLength(_rp(obj
), " ", 1);
977 text_right
= _mright(obj
) - ((_mwidth(obj
) - textwidth
) / 2);
980 case MUIV_String_Format_Right
:
981 text_right
= _mright(obj
);
988 /* Updates the stringdata in case user has set some fields */
989 static VOID
UpdateStringData(struct IClass
*cl
, Object
*obj
)
991 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
993 data
->NumChars
= strlen(data
->Buffer
);
995 if (data
->BufferPos
> data
->NumChars
)
997 data
->BufferPos
= data
->NumChars
;
1001 static VOID
TextM(Object
*obj
, struct MUI_StringData
*data
,
1002 STRPTR text
, WORD textlen
, WORD markstart
, WORD markend
)
1004 struct RastPort
*rp
= _rp(obj
);
1008 if (data
->is_active
)
1009 textpen
= data
->active_text
.p_pen
;
1011 textpen
= data
->inactive_text
.p_pen
;
1013 //kprintf("TextM: textlen %d markstart %d markend %d ... \n", textlen, markstart, markend);
1015 /* <unmarked><marked><unmarked> */
1019 len
= MIN(markstart
, textlen
);
1024 //kprintf("A: %d ", len);
1026 SetABPenDrMd(rp
, textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1027 Text(rp
, text
, len
);
1029 text
+= len
; textlen
-= len
;
1033 len
= MIN(markend
- len
, textlen
);
1038 //kprintf("B: %d ", len);
1039 SetABPenDrMd(_rp(obj
), data
->marked_text
.p_pen
, data
->marked_bg
.p_pen
, JAM2
);
1040 Text(rp
, text
, len
);
1042 text
+= len
; textlen
-= len
;
1047 //kprintf("C: %d ", textlen);
1049 SetABPenDrMd(rp
, textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1050 Text(rp
, text
, textlen
);
1055 /**************************************************************************
1057 **************************************************************************/
1058 IPTR
String__MUIM_Draw(struct IClass
*cl
, Object
*obj
, struct MUIP_Draw
*msg
)
1060 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1066 UWORD textleft_save
;
1067 WORD markstart
= 0, markstop
= 0;
1069 /* D(bug("\nString_Draw(%p) %ldx%ldx%ldx%ld reason=%ld msgflgs=%ld curs=%d " */
1070 /* "displ=%ld len=%ld buf='%s'\n",obj,_mleft(obj),_mtop(obj), */
1071 /* _mwidth(obj),_mheight(obj), data->msd_RedrawReason, msg->flags, */
1072 /* data->BufferPos, data->DispPos, data->NumChars, data->Buffer)); */
1074 DoSuperMethodA(cl
,obj
,(Msg
)msg
);
1076 if (!(msg
->flags
& MADF_DRAWUPDATE
) && !(msg
->flags
& MADF_DRAWOBJECT
))
1079 SetFont(_rp(obj
), _font(obj
));
1080 if (data
->is_active
)
1081 textpen
= data
->active_text
.p_pen
;
1083 textpen
= data
->inactive_text
.p_pen
;
1085 /* Update the stringdata in case of user change */
1086 UpdateStringData(cl
, obj
);
1087 /* Update the DispPos and DispCount fields so that the gadget renders properly */
1088 UpdateDisp(cl
, obj
);
1090 text_top
= _mtop(obj
)
1091 + ((_mheight(obj
) - _rp(obj
)->Font
->tf_YSize
) >> 1)
1092 + _rp(obj
)->Font
->tf_Baseline
;
1094 dispstr
= data
->Buffer
+ data
->DispPos
;
1095 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1096 textleft_save
= text_left
= GetTextLeft(cl
, obj
);
1098 // little flicker improvement, dont redraw first part of string
1099 // when adding a char
1100 if (msg
->flags
& MADF_DRAWUPDATE
&&
1101 data
->msd_RedrawReason
== DO_ADDCHAR
&&
1102 data
->msd_Align
== MUIV_String_Format_Left
&&
1105 text_left
+= TextLength(_rp(obj
), dispstr
, data
->BufferPos
- 1);
1106 dispstr
+= data
->BufferPos
- 1;
1107 dispstrlen
-= data
->BufferPos
- 1;
1108 DoMethod(obj
, MUIM_DrawBackground
, text_left
, _mtop(obj
),
1109 _mwidth(obj
) - text_left
+ _mleft(obj
), _mheight(obj
),
1110 text_left
, _mtop(obj
), 0);
1112 else if (msg
->flags
& MADF_DRAWUPDATE
)
1114 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), _mtop(obj
),
1115 _mwidth(obj
), _mheight(obj
), _mleft(obj
), _mtop(obj
), 0);
1118 SetABPenDrMd(_rp(obj
), textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1119 Move(_rp(obj
), text_left
, text_top
);
1121 if ((data
->msd_Flags
& MSDF_MARKING
) && Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
1123 TextM(obj
, data
, dispstr
, dispstrlen
, markstart
- data
->DispPos
,
1124 markstop
- data
->DispPos
);
1129 Text(_rp(obj
), dispstr
, dispstrlen
);
1131 if (data
->is_active
) // active, draw cursor
1133 UWORD cursoroffset
= data
->BufferPos
- data
->DispPos
;
1135 dispstr
= data
->Buffer
+ data
->DispPos
;
1136 text_left
= textleft_save
;
1138 SetABPenDrMd(_rp(obj
), data
->active_text
.p_pen
, data
->cursor
.p_pen
, JAM2
);
1139 text_left
+= TextLength(_rp(obj
), dispstr
, cursoroffset
);
1142 Move(_rp(obj
), text_left
, text_top
);
1144 ((data
->BufferPos
< data
->NumChars
)
1145 ? dispstr
+ cursoroffset
1151 data
->msd_RedrawReason
= NO_REASON
;
1155 /**************************************************************************
1156 Returns wether object needs redrawing
1157 **************************************************************************/
1158 static int String_HandleVanillakey(struct IClass
*cl
, Object
* obj
,
1159 unsigned char code
, UWORD qual
)
1161 struct MUI_StringData
*data
= (struct MUI_StringData
*)INST_DATA(cl
, obj
);
1164 D(bug("String_HandleVanillakey: code=%d qual=%d\n", code
, qual
));
1169 doinput
= (data
->msd_Flags
& MSDF_NOINPUT
) ? FALSE
: TRUE
;
1171 if (doinput
&& (code
== '\b')) /* backspace */
1173 if (Buffer_KillMarked(data
))
1178 if (data
->BufferPos
> 0)
1182 if ((qual
& IEQUALIFIER_LSHIFT
) || (qual
& IEQUALIFIER_RSHIFT
))
1184 shift
= data
->BufferPos
;
1185 data
->msd_RedrawReason
= NEW_CONTENTS
;
1190 data
->msd_RedrawReason
= DO_BACKSPACE
;
1193 strcpy(&data
->Buffer
[data
->BufferPos
- shift
],
1194 &data
->Buffer
[data
->BufferPos
]);
1195 data
->BufferPos
-= shift
;
1196 data
->NumChars
-= shift
;
1202 if (doinput
&& (code
== 21)) // ctrl-u == NAK (like shift-bs)
1204 if (Buffer_KillMarked(data
))
1209 if (data
->BufferPos
> 0)
1211 strcpy(&data
->Buffer
[0],
1212 &data
->Buffer
[data
->BufferPos
]);
1213 data
->NumChars
-= data
->BufferPos
;
1214 data
->BufferPos
= 0;
1215 data
->msd_RedrawReason
= NEW_CONTENTS
;
1221 if (doinput
&& (code
== 127)) /* del */
1223 if (!Buffer_KillMarked(data
))
1225 if ((qual
& IEQUALIFIER_LSHIFT
) || (qual
& IEQUALIFIER_RSHIFT
))
1227 data
->Buffer
[data
->BufferPos
] = 0;
1228 data
->NumChars
= data
->BufferPos
;
1229 data
->msd_RedrawReason
= NEW_CONTENTS
;
1233 if (data
->BufferPos
< data
->NumChars
)
1235 strcpy(&data
->Buffer
[data
->BufferPos
],
1236 &data
->Buffer
[data
->BufferPos
+1]);
1240 data
->msd_RedrawReason
= DO_DELETE
;
1246 if (doinput
&& (code
== 11)) // ctrl-k == VT == \v (like shift-del)
1248 if (!Buffer_KillMarked(data
))
1250 data
->Buffer
[data
->BufferPos
] = 0;
1251 data
->NumChars
= data
->BufferPos
;
1252 data
->msd_RedrawReason
= NEW_CONTENTS
;
1257 if (doinput
&& (code
== 24)) /* ctrl x == ascii cancel */
1259 if (!Buffer_KillMarked(data
))
1261 data
->Buffer
[0] = 0;
1262 data
->BufferPos
= 0;
1264 data
->msd_RedrawReason
= NEW_CONTENTS
;
1269 if (code
== 1) // ctrl-a, linestart
1271 data
->BufferPos
= 0;
1272 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
1276 if (code
== 26) // ctrl-z, lineend
1278 data
->BufferPos
= data
->NumChars
;
1279 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
1283 if (((ToLower(code
) == 'c') || (ToLower(code
) == 'x')) &&
1284 (qual
& IEQUALIFIER_RCOMMAND
))
1286 WORD markstart
, markstop
;
1288 if ((data
->msd_Flags
& MSDF_MARKING
) && Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
1290 clipboard_write_text(&data
->Buffer
[markstart
], markstop
- markstart
);
1292 if (doinput
&& (ToLower(code
) == 'x'))
1294 Buffer_KillMarked(data
);
1298 data
->BufferPos
= markstop
;
1299 data
->msd_Flags
&= ~MSDF_MARKING
;
1306 if (doinput
&& (ToLower(code
) == 'v') && (qual
& IEQUALIFIER_RCOMMAND
))
1310 struct Locale
*locale
= OpenLocale(NULL
);
1312 retval
= Buffer_KillMarked(data
);
1313 if ((text
= clipboard_read_text()))
1315 STRPTR text2
= text
;
1318 while((c
= *text2
++))
1320 if (!IsPrint(locale
, c
)) break;
1321 if (!(Buffer_AddChar(data
, c
))) break;
1322 if (!retval
) retval
= 1;
1325 clipboard_free_text(text
);
1328 CloseLocale(locale
);
1333 if (data
->msd_Accept
!= NULL
)
1335 /* Check if character is accepted */
1336 if (NULL
== strchr(data
->msd_Accept
, code
))
1340 if (data
->msd_Reject
!= NULL
)
1342 /* Check if character is rejected */
1343 if (NULL
!= strchr(data
->msd_Reject
, code
))
1352 struct Locale
*locale
= OpenLocale(NULL
);
1354 if(!(code
>= 0x09 && code
<= 0x0D) && IsPrint(locale
, code
))
1356 Buffer_KillMarked(data
);
1357 if (Buffer_AddChar(data
, code
))
1359 data
->msd_RedrawReason
= DO_ADDCHAR
;
1364 CloseLocale(locale
);
1367 data
->msd_RedrawReason
= DO_UNKNOWN
;
1372 /**************************************************************************
1374 **************************************************************************/
1375 IPTR
String__MUIM_HandleEvent(struct IClass
*cl
, Object
* obj
,
1376 struct MUIP_HandleEvent
*msg
)
1378 struct MUI_StringData
*data
= (struct MUI_StringData
*) INST_DATA(cl
, obj
);
1381 LONG muikey
= msg
->muikey
;
1382 BOOL cursor_kills_marking
= FALSE
;
1384 if ((data
->msd_Flags
& MSDF_MARKING
) && !(data
->msd_Flags
& MSDF_KEYMARKING
))
1386 cursor_kills_marking
= TRUE
;
1389 if (muikey
== MUIKEY_NONE
)
1391 if (msg
->imsg
->Class
== IDCMP_RAWKEY
)
1393 static LONG muikeytable
[3][2] =
1395 {MUIKEY_LEFT
, MUIKEY_RIGHT
},
1396 {MUIKEY_WORDLEFT
, MUIKEY_WORDRIGHT
},
1397 {MUIKEY_LINESTART
, MUIKEY_LINEEND
}
1399 WORD dirindex
= -1, amountindex
= 0;
1401 switch(msg
->imsg
->Code
)
1413 muikey
= MUIKEY_LINESTART
;
1417 muikey
= MUIKEY_LINEEND
;
1423 if ((dirindex
!= -1) && (muikey
== MUIKEY_NONE
))
1425 if (msg
->imsg
->Qualifier
& (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
1429 else if (msg
->imsg
->Qualifier
& IEQUALIFIER_CONTROL
)
1434 muikey
= muikeytable
[amountindex
][dirindex
];
1440 D(bug("String_HandleEvent: muikey %d, imsg %p is_active=%d\n", muikey
,
1441 msg
->imsg
, data
->is_active
));
1442 if (muikey
!= MUIKEY_NONE
&& data
->is_active
)
1444 retval
= MUI_EventHandlerRC_Eat
;
1449 if (cursor_kills_marking
)
1452 data
->BufferPos
= MIN(data
->BufferPos
, data
->MarkPos
);
1453 if (data
->BufferPos
> 0) data
->BufferPos
--;
1455 data
->msd_Flags
&= ~MSDF_MARKING
;
1457 else if (data
->BufferPos
> 0)
1462 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1466 if (cursor_kills_marking
)
1469 data
->BufferPos
= MAX(data
->BufferPos
, data
->MarkPos
);
1470 data
->msd_Flags
&= ~MSDF_MARKING
;
1472 else if (data
->BufferPos
< data
->NumChars
)
1476 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1479 case MUIKEY_WORDLEFT
:
1480 if (data
->BufferPos
> 0)
1482 data
->BufferPos
= Buffer_GetPrevWordIndex(data
, data
->BufferPos
);
1484 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1486 if (cursor_kills_marking
)
1488 data
->msd_Flags
&= ~MSDF_MARKING
;
1492 case MUIKEY_WORDRIGHT
:
1493 if (data
->BufferPos
< data
->NumChars
)
1495 data
->BufferPos
= Buffer_GetSuccWordIndex(data
, data
->BufferPos
);
1497 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1499 if (cursor_kills_marking
)
1501 data
->msd_Flags
&= ~MSDF_MARKING
;
1505 case MUIKEY_LINESTART
:
1506 data
->BufferPos
= 0;
1508 if (cursor_kills_marking
)
1510 data
->msd_Flags
&= ~MSDF_MARKING
;
1514 case MUIKEY_LINEEND
:
1515 data
->BufferPos
= data
->NumChars
;
1517 if (cursor_kills_marking
)
1519 data
->msd_Flags
&= ~MSDF_MARKING
;
1524 if (data
->msd_AttachedList
)
1525 set(data
->msd_AttachedList
,
1526 MUIA_List_Active
, MUIV_List_Active_Up
);
1529 if (data
->msd_AttachedList
)
1530 set(data
->msd_AttachedList
,
1531 MUIA_List_Active
, MUIV_List_Active_Down
);
1534 if (data
->msd_AttachedList
)
1535 set(data
->msd_AttachedList
,
1536 MUIA_List_Active
, MUIV_List_Active_PageUp
);
1538 case MUIKEY_PAGEDOWN
:
1539 if (data
->msd_AttachedList
)
1540 set(data
->msd_AttachedList
,
1541 MUIA_List_Active
, MUIV_List_Active_PageDown
);
1544 if (data
->msd_AttachedList
)
1545 set(data
->msd_AttachedList
,
1546 MUIA_List_Active
, MUIV_List_Active_Top
);
1549 if (data
->msd_AttachedList
)
1550 set(data
->msd_AttachedList
,
1551 MUIA_List_Active
, MUIV_List_Active_Bottom
);
1553 case MUIKEY_PRESS
: {
1556 get(obj
, MUIA_String_Contents
, &buf
);
1558 if (data
->msd_Flags
& MSDF_STAYACTIVE
)
1560 /* Do not change active object */
1562 else if (data
->msd_Flags
& MSDF_ADVANCEONCR
)
1564 set(_win(obj
), MUIA_Window_ActiveObject
, MUIV_Window_ActiveObject_Next
);
1566 else if (!(data
->msd_Flags
& MSDF_STAYACTIVE
))
1568 set(_win(obj
), MUIA_Window_ActiveObject
, MUIV_Window_ActiveObject_None
);
1571 set(obj
, MUIA_String_Acknowledge
, buf
);
1574 case MUIKEY_WINDOW_CLOSE
:
1575 data
->is_active
= FALSE
;
1576 set(obj
, MUIA_Background
,
1577 (IPTR
)muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
1578 DoMethod(obj
, MUIM_GoInactive
);
1585 } // if (muikey != MUIKEY_NONE)
1589 UWORD code
= msg
->imsg
->Code
;
1590 //UWORD qual = msg->imsg->Qualifier;
1591 WORD x
= msg
->imsg
->MouseX
;
1592 WORD y
= msg
->imsg
->MouseY
;
1594 //bug("String_HandleEvent: parsing imsg %p, class=%ld\n", msg->imsg, msg->imsg->Class);
1596 switch (msg
->imsg
->Class
)
1598 case IDCMP_MOUSEBUTTONS
: /* set cursor and activate it */
1599 if (code
== SELECTDOWN
)
1601 //bug("String_HandleEvent: code == SELECTDOWN, x=%d y=%d\n", x, y);
1603 if (_isinobject(x
, y
))
1605 UWORD text_left
, text_right
;
1607 retval
= MUI_EventHandlerRC_Eat
;
1609 CurrentTime(&data
->NewClick_Sec
, &data
->NewClick_Micro
);
1610 if (DoubleClick(data
->OldClick_Sec
, data
->OldClick_Micro
,
1611 data
->NewClick_Sec
, data
->NewClick_Micro
))
1617 data
->MultiClick
= 0;
1619 data
->OldClick_Sec
= data
->NewClick_Sec
;
1620 data
->OldClick_Micro
= data
->NewClick_Micro
;
1622 //kprintf("multiclick %d\n", data->MultiClick);
1624 if (!data
->is_active
)
1626 //bug("String got button, lets activate\n");
1627 data
->is_active
= TRUE
;
1628 data
->msd_RedrawReason
= WENT_ACTIVE
;
1630 set(obj
, MUIA_Background
,
1631 (IPTR
)muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_active
);
1633 //DoMethod(obj, MUIM_GoActive);
1634 set(_win(obj
), MUIA_Window_ActiveObject
, obj
);
1635 // let other objects a chance to get desactivated
1639 if (!(data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
))
1641 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
1642 data
->ehn
.ehn_Events
|= IDCMP_MOUSEMOVE
;
1643 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
1646 text_left
= GetTextLeft (cl
, obj
);
1647 text_right
= GetTextRight(cl
, obj
);
1649 /* Check if mouseclick is inside displayed text */
1650 if ((x
>= text_left
) && (x
<= text_right
))
1652 /* Find new cursor pos. */
1653 struct TextExtent te
;
1655 STRPTR dispstr
= data
->Buffer
+ data
->DispPos
;
1657 newpos
= data
->DispPos
1658 + TextFit(_rp(obj
), dispstr
, data
->NumChars
- data
->DispPos
,
1660 x
- text_left
, _rp(obj
)->Font
->tf_YSize
);
1662 if (data
->BufferPos
!= newpos
)
1664 data
->BufferPos
= newpos
;
1668 else if (x
< text_left
)
1670 /* Click on empty space at left. Set cursor to first visible */
1671 if (data
->BufferPos
!= data
->DispPos
)
1673 data
->BufferPos
= data
->DispPos
;
1679 /* Click on empty space at right. Set cursor to last visible */
1680 if (data
->BufferPos
!= data
->DispPos
+ data
->DispCount
)
1682 data
->BufferPos
= data
->DispPos
+ data
->DispCount
;
1685 } /* if (click is on text or not) */
1687 data
->MarkPos
= data
->BufferPos
;
1689 if (data
->MultiClick
== 0)
1691 if (data
->msd_Flags
& MSDF_MARKING
)
1693 data
->msd_Flags
&= ~MSDF_MARKING
;
1697 else if (data
->MultiClick
&& Buffer_GetMarkedRange(data
, NULL
, NULL
))
1699 data
->msd_Flags
|= MSDF_MARKING
;
1704 } /* is in object */
1705 else if (data
->is_active
&& !(data
->msd_Flags
& MSDF_STAYACTIVE
)) /* and click not on object */
1707 data
->is_active
= FALSE
;
1708 set(obj
, MUIA_Background
,
1709 (IPTR
)muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
1710 //DoMethod(obj, MUIM_GoInactive);
1711 // let other objects a chance to get activated
1714 } /* if (code == SELECTDOWN) */
1715 else if (code
== SELECTUP
)
1717 if (data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
)
1719 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
1720 data
->ehn
.ehn_Events
&= ~IDCMP_MOUSEMOVE
;
1721 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
1726 case IDCMP_MOUSEMOVE
:
1727 if (data
->is_active
)
1729 UWORD text_left
, text_right
;
1731 if (!(data
->msd_Flags
& MSDF_MARKING
))
1733 data
->msd_Flags
|= MSDF_MARKING
;
1736 text_left
= GetTextLeft (cl
, obj
);
1737 text_right
= GetTextRight(cl
, obj
);
1739 /* Check if mouseclick is inside displayed text */
1740 if ((x
>= text_left
) && (x
<= text_right
))
1742 /* Find new cursor pos. */
1743 struct TextExtent te
;
1745 STRPTR dispstr
= data
->Buffer
+ data
->DispPos
;
1747 newpos
= data
->DispPos
1748 + TextFit(_rp(obj
), dispstr
, data
->NumChars
- data
->DispPos
,
1750 x
- text_left
, _rp(obj
)->Font
->tf_YSize
);
1752 if (data
->BufferPos
!= newpos
)
1754 WORD old_markstart
= 0, old_markstop
= 0;
1755 WORD markstart
= 0, markstop
= 0;
1756 BOOL was_marked
, is_marked
;
1758 was_marked
= Buffer_AnythingMarked(data
) &&
1759 Buffer_GetMarkedRange(data
, &old_markstart
, &old_markstop
);
1761 data
->BufferPos
= newpos
;
1763 is_marked
= Buffer_AnythingMarked(data
) &&
1764 Buffer_GetMarkedRange(data
, &markstart
, &markstop
);
1766 if ((was_marked
!= is_marked
) ||
1767 (old_markstart
!= markstart
) ||
1768 (old_markstop
!= markstop
))
1774 else if ((x
< text_left
) && (data
->BufferPos
> 0))
1778 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1780 else if ((x
> text_right
) && (data
->BufferPos
< data
->NumChars
))
1784 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1786 //kprintf(" ---- bp: %d\n", data->BufferPos);
1794 //bug("String_HandleEvent: idcmp_rawkey\n");
1796 if (!data
->is_active
)
1799 code
= ConvertKey(msg
->imsg
);
1802 switch(msg
->imsg
->Code
)
1804 case 0x64: /* LALT */
1805 case 0x65: /* RALT */
1806 case 0x64 | IECODE_UP_PREFIX
:
1807 case 0x65 | IECODE_UP_PREFIX
:
1808 if (msg
->imsg
->Qualifier
& (IEQUALIFIER_LALT
| IEQUALIFIER_RALT
))
1810 data
->MarkPos
= data
->BufferPos
;
1811 data
->msd_Flags
|= (MSDF_MARKING
| MSDF_KEYMARKING
);
1815 data
->msd_Flags
&= ~MSDF_KEYMARKING
;
1824 update
= String_HandleVanillakey(cl
, obj
, code
, msg
->imsg
->Qualifier
);
1826 retval
= MUI_EventHandlerRC_Eat
;
1835 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1837 //D(bug("String eh return %ld\n", retval));
1842 /**************************************************************************
1843 MUIM_Export : to export an objects "contents" to a dataspace object.
1844 **************************************************************************/
1845 IPTR
String__MUIM_Export(struct IClass
*cl
, Object
*obj
, struct MUIP_Export
*msg
)
1847 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1851 if (data
->msd_useSecret
)
1852 buf
= data
->SecBuffer
;
1856 if ((id
= muiNotifyData(obj
)->mnd_ObjectID
))
1859 DoMethod(msg
->dataspace
, MUIM_Dataspace_Add
,
1864 DoMethod(msg
->dataspace
, MUIM_Dataspace_Remove
,
1871 /**************************************************************************
1872 MUIM_Import : to import an objects "contents" from a dataspace object.
1873 **************************************************************************/
1874 IPTR
String__MUIM_Import(struct IClass
*cl
, Object
*obj
, struct MUIP_Import
*msg
)
1879 if ((id
= muiNotifyData(obj
)->mnd_ObjectID
))
1881 if ((s
= (STRPTR
)DoMethod(msg
->dataspace
, MUIM_Dataspace_Find
, (IPTR
)id
)))
1883 set(obj
, MUIA_String_Contents
, s
);
1889 /**************************************************************************
1891 **************************************************************************/
1892 IPTR
String__MUIM_GoActive(struct IClass
* cl
, Object
* obj
, Msg msg
)
1894 struct MUI_StringData
*data
= (struct MUI_StringData
*) INST_DATA(cl
, obj
);
1896 //D(bug("String_GoActive %p\n", obj));
1897 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
1898 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
| IDCMP_RAWKEY
;
1899 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
1900 data
->is_active
= TRUE
;
1901 data
->msd_Flags
&= ~MSDF_KEYMARKING
;
1902 data
->msd_RedrawReason
= WENT_ACTIVE
;
1904 set(obj
, MUIA_Background
,
1905 (IPTR
)muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_active
);
1909 /**************************************************************************
1911 **************************************************************************/
1912 IPTR
String__MUIM_GoInactive(struct IClass
* cl
, Object
* obj
, Msg msg
)
1914 struct MUI_StringData
*data
= (struct MUI_StringData
*) INST_DATA(cl
, obj
);
1916 //D(bug("String_GoInactive %p\n", obj));
1918 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
)&data
->ehn
);
1919 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
1920 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
)&data
->ehn
);
1921 data
->is_active
= FALSE
;
1922 data
->msd_RedrawReason
= WENT_INACTIVE
;
1923 data
->MultiClick
= 0;
1926 set(obj
, MUIA_Background
,
1927 (IPTR
)muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
1931 /**************************************************************************
1932 MUIM_String_ClearSelected (BetterString)
1933 **************************************************************************/
1934 IPTR
String__MUIM_ClearSelected(struct IClass
* cl
, Object
* obj
, struct MUIP_String_ClearSelected
*msg
)
1936 struct MUI_StringData
*data
= (struct MUI_StringData
*) INST_DATA(cl
, obj
);
1938 //D(bug("String_ClearSelected %p\n", obj));
1940 if (Buffer_KillMarked(data
))
1942 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
1948 /**************************************************************************
1949 MUIM_String_Insert (BetterString)
1950 **************************************************************************/
1951 IPTR
String__MUIM_Insert(struct IClass
* cl
, Object
* obj
, struct MUIP_String_Insert
*msg
)
1953 struct MUI_StringData
*data
= (struct MUI_StringData
*) INST_DATA(cl
, obj
);
1955 ULONG old_bufferpos
;
1956 ULONG num_inserted
= 0;
1958 //D(bug("String_Insert %p\n", obj));
1960 switch((ULONG
)msg
->pos
)
1962 case MUIV_String_Insert_StartOfString
:
1966 case MUIV_String_Insert_EndOfString
:
1967 pos
= data
->NumChars
;
1970 case MUIV_String_Insert_BufferPos
:
1971 pos
= data
->BufferPos
;
1979 if ((pos
< 0) || (pos
> data
->NumChars
)) return 0;
1981 old_bufferpos
= data
->BufferPos
;
1982 data
->BufferPos
= pos
;
1984 while(msg
->text
[num_inserted
] && Buffer_AddChar(data
, msg
->text
[num_inserted
]))
1991 if (old_bufferpos
>= pos
)
1993 data
->BufferPos
= old_bufferpos
+ num_inserted
;
1997 data
->BufferPos
= old_bufferpos
;
2000 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2006 /**************************************************************************
2007 MUIM_String_FileNameStart (BetterString)
2008 **************************************************************************/
2009 IPTR
String__MUIM_FileNameStart(struct IClass
* cl
, Object
* obj
, struct MUIP_String_FileNameStart
*msg
)
2011 struct MUI_StringData
*data
= (struct MUI_StringData
*) INST_DATA(cl
, obj
);
2014 //D(bug("String_FileNameStart %p\n", obj));
2016 if (data
->msd_useSecret
)
2018 buf
= data
->SecBuffer
;
2024 #warning "TODO: Implement String_FileNameStart correctly!"
2029 BOOPSI_DISPATCHER(IPTR
, String_Dispatcher
, cl
, obj
, msg
)
2031 switch (msg
->MethodID
)
2033 case OM_NEW
: return String__OM_NEW(cl
, obj
, (struct opSet
*) msg
);
2034 case OM_DISPOSE
: return String__OM_DISPOSE(cl
, obj
, msg
);
2035 case OM_SET
: return String__OM_SET(cl
, obj
, (struct opSet
*)msg
);
2036 case OM_GET
: return String__OM_GET(cl
, obj
, (struct opGet
*)msg
);
2038 case MUIM_Setup
: return String__MUIM_Setup(cl
, obj
, (APTR
)msg
);
2039 case MUIM_Cleanup
: return String__MUIM_Cleanup(cl
, obj
, (APTR
)msg
);
2040 case MUIM_AskMinMax
: return String__MUIM_AskMinMax(cl
, obj
, (APTR
)msg
);
2041 case MUIM_Draw
: return String__MUIM_Draw(cl
, obj
, (APTR
)msg
);
2042 case MUIM_Export
: return String__MUIM_Export(cl
, obj
, (APTR
)msg
);
2043 case MUIM_Import
: return String__MUIM_Import(cl
, obj
, (APTR
)msg
);
2044 case MUIM_GoActive
: return String__MUIM_GoActive(cl
, obj
, (APTR
)msg
);
2045 case MUIM_GoInactive
: return String__MUIM_GoInactive(cl
,obj
,(APTR
)msg
);
2046 case MUIM_HandleEvent
: return String__MUIM_HandleEvent(cl
,obj
,(APTR
)msg
);
2047 case MUIM_String_ClearSelected
: return String__MUIM_ClearSelected(cl
,obj
,(APTR
)msg
); /* BetterString */
2048 case MUIM_String_Insert
: return String__MUIM_Insert(cl
,obj
,(APTR
)msg
); /* BetterString */
2049 case MUIM_String_FileNameStart
: return String__MUIM_FileNameStart(cl
,obj
,(APTR
)msg
); /* BetterString */
2052 return DoSuperMethodA(cl
, obj
, msg
);
2054 BOOPSI_DISPATCHER_END
2060 const struct __MUIBuiltinClass _MUI_String_desc
= {
2063 sizeof(struct MUI_StringData
),
2064 (void*)String_Dispatcher