2 Copyright © 2003-2018, 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
;
49 CONST_STRPTR msd_Accept
; /* MUIA_String_Accept */
50 CONST_STRPTR msd_Reject
; /* MUIA_String_Reject */
52 struct Hook
*msd_EditHook
;
53 Object
*msd_AttachedList
;
54 LONG msd_RedrawReason
;
57 /* Fields mostly ripped from rom/intuition/strgadgets.c */
58 STRPTR Buffer
; /* char container */
59 STRPTR SecBuffer
; /* Buffer for secret string */
60 STRPTR VisualBuffer
; /* Pointer to either Buffer or SecBuffer */
61 ULONG BufferSize
; /* memory allocated */
62 ULONG NumChars
; /* string length */
63 ULONG BufferPos
; /* cursor (insert/delete) position */
64 ULONG MarkPos
; /* cursor text marking start pos */
65 LONG DispPos
; /* leftmost visible char */
66 ULONG DispCount
; /* number of visible chars */
76 struct MUI_EventHandlerNode ehn
;
77 struct MUI_PenSpec_intern inactive_text
;
78 struct MUI_PenSpec_intern active_text
;
79 struct MUI_PenSpec_intern marked_text
;
80 struct MUI_PenSpec_intern marked_bg
;
81 struct MUI_PenSpec_intern cursor
;
86 #define MSDF_ADVANCEONCR (1<<0)
87 #define MSDF_LONELYEDITHOOK (1<<1)
88 #define MSDF_MARKING (1<<2)
89 #define MSDF_KEYMARKING (1<<3)
90 #define MSDF_NOINPUT (1<<4)
91 #define MSDF_STAYACTIVE (1<<5)
108 #define SECRET_CHAR '*'
111 /****** String.mui/MUIA_String_Accept ****************************************
114 * MUIA_String_Accept -- (V4) [ISG], STRPTR
117 * A string containing the characters to be accepted by the string
118 * gadget. If NULL is specified, all characters are accepted. The
119 * character list is case sensitive.
122 * MUIA_String_Reject takes precedence over MUIA_String_Accept.
124 * The specified string is not cached within the object.
129 ******************************************************************************
133 /****** String.mui/MUIA_String_Reject ****************************************
136 * MUIA_String_Reject -- (V4) [ISG], STRPTR
139 * A string containing the characters to be rejected by the string
140 * gadget. If NULL is specified, no characters are rejected. The
141 * character list is case sensitive.
144 * MUIA_String_Reject takes precedence over MUIA_String_Accept.
146 * The specified string is not cached within the object.
151 ******************************************************************************
155 /****** String.mui/MUIA_String_BufferPos *************************************
158 * MUIA_String_BufferPos -- (V4) [ISG], STRPTR
161 * The cursor's position relative to the start of the string.
164 * The MUI AutoDocs claim this attribute is not initialisable.
166 ******************************************************************************
170 /**************************************************************************
172 Allocate memory for buffer
173 **************************************************************************/
174 static BOOL
Buffer_Alloc(struct MUI_StringData
*data
)
179 (STRPTR
) AllocVec(data
->BufferSize
* sizeof(char), MEMF_ANY
);
180 if (NULL
== data
->Buffer
)
182 bug("[MUI:String] Buffer_Alloc: Failed to allocate %ld bytes for buffer1\n",
183 data
->BufferSize
* sizeof(char));
186 if (data
->msd_useSecret
)
189 (STRPTR
) AllocVec(data
->BufferSize
* sizeof(char), MEMF_ANY
);
190 if (NULL
== data
->SecBuffer
)
192 bug("[MUI:String] Buffer_Alloc: Failed to allocate %ld bytes for buffer2\n",
193 data
->BufferSize
* sizeof(char));
194 FreeVec(data
->Buffer
);
199 /* Initialise maximum number of asterisks we'll need */
200 for (i
= 0; i
< data
->BufferSize
- 1; i
++)
201 data
->SecBuffer
[i
] = SECRET_CHAR
;
203 data
->VisualBuffer
= data
->SecBuffer
;
206 data
->VisualBuffer
= data
->Buffer
;
211 static inline VOID
PrepareVisualBuffer(struct MUI_StringData
*data
)
213 if (data
->msd_useSecret
)
214 data
->VisualBuffer
[data
->NumChars
] = '\0';
217 static inline VOID
CleanVisualBuffer(struct MUI_StringData
*data
)
219 if (data
->msd_useSecret
)
220 data
->VisualBuffer
[data
->NumChars
] = SECRET_CHAR
;
223 /**************************************************************************
224 Buffer_SetNewContents
225 Initialize buffer with a string, replace former content if any
226 **************************************************************************/
227 static BOOL
Buffer_SetNewContents(struct MUI_StringData
*data
,
230 if (NULL
== data
->Buffer
)
240 data
->NumChars
= strlen(str
);
241 if (data
->NumChars
>= data
->BufferSize
)
242 data
->NumChars
= data
->BufferSize
- 1;
244 strncpy(data
->Buffer
, str
, data
->BufferSize
);
245 data
->Buffer
[data
->BufferSize
- 1] = 0;
248 // avoid to BufferPos jumps to end of string if characters are inserted
250 if (data
->BufferPos
> data
->NumChars
)
251 data
->BufferPos
= data
->NumChars
;
256 /**************************************************************************
258 Add a char on cursor position
259 **************************************************************************/
260 static BOOL
Buffer_AddChar(struct MUI_StringData
*data
, unsigned char code
)
264 if (data
->Buffer
== NULL
)
267 if (data
->NumChars
+ 1 >= data
->BufferSize
)
270 dst
= &data
->Buffer
[data
->BufferPos
+ 1];
272 memmove(dst
, &data
->Buffer
[data
->BufferPos
],
273 data
->NumChars
- data
->BufferPos
);
275 dst
[data
->NumChars
- data
->BufferPos
] = 0;
283 static WORD
Buffer_GetWordStartIndex(struct MUI_StringData
*data
,
286 WORD index
= startindex
;
290 if (data
->Buffer
[index
- 1] == ' ')
300 static WORD
Buffer_GetWordEndIndex(struct MUI_StringData
*data
,
303 WORD index
= startindex
;
305 while (index
< data
->NumChars
)
307 if (data
->Buffer
[index
] == ' ')
317 static WORD
Buffer_GetPrevWordIndex(struct MUI_StringData
*data
,
320 WORD index
= startindex
;
327 ((data
->Buffer
[index
- 1] == ' ') &&
328 (data
->Buffer
[index
] != ' ')))
338 static WORD
Buffer_GetSuccWordIndex(struct MUI_StringData
*data
,
341 WORD index
= startindex
;
343 while (index
< data
->NumChars
)
347 if ((index
== data
->NumChars
) ||
348 ((data
->Buffer
[index
- 1] == ' ') &&
349 (data
->Buffer
[index
] != ' ')))
358 static BOOL
Buffer_GetMarkedRange(struct MUI_StringData
*data
, WORD
*start
,
361 WORD markstart
= data
->MarkPos
;
362 WORD markstop
= data
->BufferPos
;
364 markstart
= MIN(markstart
, data
->NumChars
);
365 markstart
= MAX(markstart
, 0);
367 markstop
= MIN(markstop
, data
->NumChars
);
368 markstop
= MAX(markstop
, 0);
370 if (markstart
> markstop
)
372 markstart
^= markstop
;
373 markstop
^= markstart
;
374 markstart
^= markstop
;
377 switch (data
->MultiClick
)
385 markstart
= Buffer_GetWordStartIndex(data
, markstart
);
386 markstop
= Buffer_GetWordEndIndex(data
, markstop
);
392 markstop
= data
->NumChars
;
397 if (markstart
== markstop
)
405 //kprintf("Buffer_GetMarkedRange: returning %d .. %d\n",
406 // markstart, markstop);
411 static BOOL
Buffer_AnythingMarked(struct MUI_StringData
*data
)
413 if (!(data
->msd_Flags
& MSDF_MARKING
))
416 return Buffer_GetMarkedRange(data
, NULL
, NULL
);
419 static BOOL
Buffer_KillMarked(struct MUI_StringData
*data
)
421 WORD markstart
= data
->MarkPos
;
422 WORD markstop
= data
->BufferPos
;
425 //kprintf("\nBuffer_KillMarked 1 markpos %d bufferpos %d numchars %d\n",
426 // markstart, markstop, data->NumChars);
428 if (!(data
->msd_Flags
& MSDF_MARKING
))
431 data
->msd_Flags
&= ~MSDF_MARKING
;
433 if (!Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
436 //kprintf("Buffer_KillMarked 2 markstart %d markstop %d\n",
437 // markstart, markstop);
439 if (markstart
> markstop
)
441 markstart
^= markstop
;
442 markstop
^= markstart
;
443 markstart
^= markstop
;
446 marklen
= markstop
- markstart
;
448 //kprintf("Buffer_KillMarked: markstart %d markstop %d\n",
449 // markstart, markstop);
451 memmove(&data
->Buffer
[markstart
],
452 &data
->Buffer
[markstart
+ marklen
],
453 data
->NumChars
- markstart
- marklen
+ 1);
454 data
->NumChars
-= marklen
;
455 data
->BufferPos
= markstart
;
460 /**************************************************************************
462 **************************************************************************/
463 IPTR
String__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
465 struct MUI_StringData
*data
;
466 struct TagItem
*tags
, *tag
;
467 CONST_STRPTR str
= NULL
;
470 obj
= (Object
*) DoSuperNewTags(cl
, obj
, NULL
,
471 /* MUIA_FillArea, TRUE, */
472 TAG_MORE
, (IPTR
) msg
->ops_AttrList
);
476 data
= INST_DATA(cl
, obj
);
477 data
->msd_useSecret
= FALSE
;
478 data
->msd_Align
= MUIV_String_Format_Left
;
479 data
->BufferSize
= 80;
482 Buffer_SetNewContents(data
, ""); /* <-- isn't this pointless? */
484 /* parse initial taglist */
485 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
489 case MUIA_String_Accept
:
490 data
->msd_Accept
= (CONST_STRPTR
) tag
->ti_Data
;
493 case MUIA_String_Reject
:
494 data
->msd_Reject
= (CONST_STRPTR
) tag
->ti_Data
;
497 case MUIA_String_AdvanceOnCR
:
498 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
502 case MUIA_String_BufferPos
:
503 data
->BufferPos
= (ULONG
) tag
->ti_Data
;
506 case MUIA_String_AttachedList
:
507 data
->msd_AttachedList
= (Object
*) tag
->ti_Data
;
510 case MUIA_String_Secret
:
511 data
->msd_useSecret
= (BOOL
) tag
->ti_Data
;
514 case MUIA_String_Contents
:
515 str
= (CONST_STRPTR
) tag
->ti_Data
;
518 case MUIA_String_EditHook
:
519 data
->msd_EditHook
= (struct Hook
*)tag
->ti_Data
;
522 case MUIA_String_Format
:
523 data
->msd_Align
= (LONG
) tag
->ti_Data
;
526 case MUIA_String_Integer
:
527 snprintf(integerbuf
, 19, "%ld", tag
->ti_Data
);
531 case MUIA_String_LonelyEditHook
:
532 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
533 MSDF_LONELYEDITHOOK
);
536 case MUIA_String_MaxLen
:
537 data
->BufferSize
= tag
->ti_Data
;
538 if (data
->BufferSize
< 1)
539 data
->BufferSize
= 1;
542 case MUIA_String_Columns
: /* BetterString */
543 data
->Columns
= (WORD
) tag
->ti_Data
;
546 case MUIA_String_NoInput
: /* BetterString */
547 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_NOINPUT
);
550 case MUIA_String_StayActive
: /* BetterString */
551 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
558 if (Buffer_Alloc(data
))
560 Buffer_SetNewContents(data
, str
);
563 if (NULL
== data
->Buffer
)
565 CoerceMethod(cl
, obj
, OM_DISPOSE
);
569 D(bug("[MUI:String] New(%p)\n", obj
));
571 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
572 data
->ehn
.ehn_Priority
= 0;
573 data
->ehn
.ehn_Flags
= 0;
574 data
->ehn
.ehn_Object
= obj
;
575 data
->ehn
.ehn_Class
= cl
;
577 CurrentTime(&data
->OldClick_Sec
, &data
->OldClick_Micro
);
582 /**************************************************************************
584 **************************************************************************/
585 IPTR
String__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
587 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
589 FreeVec(data
->Buffer
);
590 FreeVec(data
->SecBuffer
);
592 D(bug("[MUI:String] Dispose %p\n", obj
));
594 return DoSuperMethodA(cl
, obj
, msg
);
597 /**************************************************************************
599 **************************************************************************/
600 IPTR
String__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
602 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
603 struct TagItem
*tags
= msg
->ops_AttrList
;
606 while ((tag
= NextTagItem(&tags
)) != NULL
)
610 case MUIA_String_Contents
:
611 Buffer_SetNewContents(data
, (STRPTR
) tag
->ti_Data
);
612 data
->msd_RedrawReason
= NEW_CONTENTS
;
613 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
614 MUI_Redraw(obj
, MADF_DRAWOBJECT
);
617 case MUIA_String_Accept
:
618 data
->msd_Accept
= (CONST_STRPTR
) tag
->ti_Data
;
621 case MUIA_String_Reject
:
622 data
->msd_Reject
= (CONST_STRPTR
) tag
->ti_Data
;
625 case MUIA_String_AttachedList
:
626 data
->msd_AttachedList
= (Object
*) tag
->ti_Data
;
629 case MUIA_String_Integer
:
633 snprintf(buf
, 19, "%ld", tag
->ti_Data
);
634 set(obj
, MUIA_String_Contents
, buf
);
638 case MUIA_String_AdvanceOnCR
:
639 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
643 case MUIA_String_BufferPos
:
644 data
->BufferPos
= (ULONG
) tag
->ti_Data
;
645 data
->msd_Flags
&= ~MSDF_MARKING
;
646 data
->msd_RedrawReason
= MOVE_CURSOR
;
647 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
650 case MUIA_String_DisplayPos
:
651 data
->BufferPos
= (ULONG
) tag
->ti_Data
;
652 data
->DispPos
= data
->BufferPos
; // move both pos
653 data
->msd_Flags
&= ~MSDF_MARKING
;
654 data
->msd_RedrawReason
= MOVE_CURSOR
;
655 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
658 case MUIA_String_NoInput
: /* BetterString */
659 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_NOINPUT
);
662 case MUIA_String_StayActive
: /* BetterString */
663 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
667 case MUIA_String_SelectSize
: /* BetterString */
668 // TODO: Implement OM_SET(MUIA_String_SelectSize)!
674 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
678 /**************************************************************************
680 **************************************************************************/
681 IPTR
String__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
683 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
685 #define STORE *(msg->opg_Storage)
686 switch (msg
->opg_AttrID
)
688 case MUIA_String_Contents
:
689 STORE
= (IPTR
) data
->Buffer
;
692 case MUIA_String_Secret
:
693 STORE
= (IPTR
) data
->msd_useSecret
;
696 case MUIA_String_Accept
:
697 STORE
= (IPTR
) data
->msd_Accept
;
700 case MUIA_String_Reject
:
701 STORE
= (IPTR
) data
->msd_Reject
;
704 case MUIA_String_AttachedList
:
705 STORE
= (IPTR
) data
->msd_AttachedList
;
708 case MUIA_String_Format
:
709 STORE
= (IPTR
) data
->msd_Align
;
712 case MUIA_String_Integer
:
716 get(obj
, MUIA_String_Contents
, &buf
);
720 StrToLong(buf
, &val
);
726 case MUIA_String_MaxLen
:
727 STORE
= (IPTR
) data
->BufferSize
;
730 case MUIA_String_AdvanceOnCR
:
731 STORE
= (data
->msd_Flags
& MSDF_ADVANCEONCR
) ? TRUE
: FALSE
;
734 case MUIA_String_BufferPos
:
735 STORE
= data
->BufferPos
;
738 case MUIA_String_DisplayPos
:
739 STORE
= data
->DispPos
;
742 case MUIA_String_NoInput
: /* BetterString */
743 STORE
= (data
->msd_Flags
& MSDF_NOINPUT
) ? TRUE
: FALSE
;
746 case MUIA_String_StayActive
: /* BetterString */
747 STORE
= (data
->msd_Flags
& MSDF_STAYACTIVE
) ? TRUE
: FALSE
;
750 case MUIA_String_SelectSize
: /* BetterString */
751 if (data
->msd_Flags
& MSDF_MARKING
)
753 WORD markstart
, markstop
;
755 if (Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
757 LONG size
= markstop
- markstart
;
759 if (data
->MarkPos
< data
->BufferPos
)
774 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
778 /**************************************************************************
780 **************************************************************************/
781 IPTR
String__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
782 struct MUIP_Setup
*msg
)
784 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
786 if (0 == DoSuperMethodA(cl
, obj
, (Msg
) msg
))
789 data
->is_active
= FALSE
;
790 set(obj
, MUIA_Background
,
791 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
793 zune_pen_spec_to_intern(
794 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
795 string_text_inactive
, &data
->inactive_text
);
796 zune_penspec_setup(&data
->inactive_text
, muiRenderInfo(obj
));
798 zune_pen_spec_to_intern(
799 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
800 string_text_active
, &data
->active_text
);
801 zune_penspec_setup(&data
->active_text
, muiRenderInfo(obj
));
803 zune_pen_spec_to_intern(
804 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
805 string_text_marked
, &data
->marked_text
);
806 zune_penspec_setup(&data
->marked_text
, muiRenderInfo(obj
));
808 zune_pen_spec_to_intern(
809 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
810 string_bg_marked
, &data
->marked_bg
);
811 zune_penspec_setup(&data
->marked_bg
, muiRenderInfo(obj
));
813 zune_pen_spec_to_intern(
814 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
815 string_cursor
, &data
->cursor
);
816 zune_penspec_setup(&data
->cursor
, muiRenderInfo(obj
));
818 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
822 /**************************************************************************
824 **************************************************************************/
825 IPTR
String__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
826 struct MUIP_Cleanup
*msg
)
828 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
830 D(bug("[MUI:String] Cleanup %p\n", obj
));
831 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
833 zune_penspec_cleanup(&data
->inactive_text
);
834 zune_penspec_cleanup(&data
->active_text
);
835 zune_penspec_cleanup(&data
->marked_text
);
836 zune_penspec_cleanup(&data
->marked_bg
);
837 zune_penspec_cleanup(&data
->cursor
);
839 return (DoSuperMethodA(cl
, obj
, (Msg
) msg
));
842 /**************************************************************************
844 **************************************************************************/
845 IPTR
String__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
,
846 struct MUIP_AskMinMax
*msg
)
848 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
850 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
852 if (data
->Columns
>= 0)
854 msg
->MinMaxInfo
->MinWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
855 msg
->MinMaxInfo
->DefWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
856 msg
->MinMaxInfo
->MaxWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
860 msg
->MinMaxInfo
->MinWidth
+= _font(obj
)->tf_XSize
* 4;
861 msg
->MinMaxInfo
->DefWidth
+= _font(obj
)->tf_XSize
* 12;
862 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
865 msg
->MinMaxInfo
->MinHeight
+= _font(obj
)->tf_YSize
;
866 msg
->MinMaxInfo
->DefHeight
+= _font(obj
)->tf_YSize
;
867 msg
->MinMaxInfo
->MaxHeight
+= _font(obj
)->tf_YSize
;
869 /* D(bug("String_AskMinMax(%p): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n", */
870 /* obj, msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight, */
871 /* msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight, */
872 /* msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight)); */
878 static WORD
MaxDispPos(struct IClass
*cl
, Object
*obj
)
880 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
881 WORD numfit
, max_disppos
, numchars
;
882 struct TextExtent te
;
885 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
887 /* D(bug("MaxDispPos(current length: %d, bufferpos=%d)\n", */
888 /* data->NumChars, data->BufferPos)); */
890 /* D(bug("cursor_at_end: %d\n", cursor_at_end)); */
892 if (cursor_at_end
) /* Cursor at end of string ? */
894 /* D(bug("Making cursor last char\n")); */
895 numchars
= data
->NumChars
+ 1; /* Take cursor into account */
897 /* This has already been done by UpdateDisp() which called us
898 strinfo->Buffer[strinfo->NumChars] = 0x20;
904 numchars
= data
->NumChars
;
907 /* Find the amount of characters that fit into the bbox, counting
908 ** from the last character in the buffer and forward,
910 numfit
= TextFit(_rp(obj
),
911 &(data
->Buffer
[numchars
- 1]),
912 numchars
, &te
, NULL
, -1, _mwidth(obj
), _mheight(obj
));
914 max_disppos
= numchars
- numfit
;
916 /* if ((max_disppos > 0) && (!cursor_at_end))
920 /* D(bug("Numchars w/cursor: %d, Numfit: %d, maxdisppos=%d " */
921 /* "bbox->Width = %d te->te_Width = %d\n", */
922 /* numchars, numfit, max_disppos, _mwidth(obj), te.te_Width)); */
928 static void UpdateDisp(struct IClass
*cl
, Object
*obj
)
930 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
931 struct TextExtent te
;
934 /* If the cursor is at the trailing \0, insert a SPACE instead */
935 if (data
->BufferPos
== data
->NumChars
)
936 data
->VisualBuffer
[data
->NumChars
] = ' ';
938 /* In this function we check if the cursor has gone outside
939 ** of the visible area (because of application setting
940 ** strinfo->BufferPos or strinfo->DispPos to a different value, or
941 ** because of user input).
942 ** This is made a bit difficult by the rule (R), that there
943 ** should NOT be available space on the right, and characters
944 ** scrolled out at the left, at the same time.
945 ** We have 3 possible scenarios:
946 ** 1) Cursor to the left of DispPos:
947 ** Set DispPos to the lowest of BufferPos and the
948 ** maximum allowed disppos (according to (R) ).
949 ** 2) Cursor to the right of visible area:
950 ** Set dispose sou that the cursor is the last visible character.
951 ** This afheres to (R).
952 ** 3) Cursor inside visible area. Do a check on rule (R),
953 ** and if DispPos > max allowed, then adjust it down,
954 ** so that the last character in the buffer becomes last character
955 ** displayed. (The cursor will still be visible after adjustion)
958 /* 1) Cursor to the left of visible area */
959 if (data
->BufferPos
< data
->DispPos
)
963 max_disppos
= MaxDispPos(cl
, obj
);
964 data
->DispPos
= MIN(data
->BufferPos
, max_disppos
);
966 else /* Cursor equal to the right of disppos [ 2) or 3) ] */
970 /* How many pixels are there from current 1st displayed to cursor? */
971 strsize
= TextLength(_rp(obj
),
972 data
->VisualBuffer
+ data
->DispPos
,
973 data
->BufferPos
- data
->DispPos
+ 1);
975 /* 2) More than fits into the gadget ? */
976 if (strsize
> _mwidth(obj
))
978 /* Compute new DispPos such that the cursor is at the right */
979 data
->DispPos
= data
->BufferPos
981 &(data
->VisualBuffer
[data
->BufferPos
]),
982 data
->NumChars
, &te
, NULL
, -1,
983 _mwidth(obj
), _mheight(obj
)) + 1;
985 /* D(bug("cursor right of visible area, new disppos: %d\n", */
986 /* data->DispPos)); */
988 else /* 3). Cursor inside gadget */
992 max_disppos
= MaxDispPos(cl
, obj
);
993 if (data
->DispPos
> max_disppos
)
994 data
->DispPos
= max_disppos
;
996 } /* if (cursor inside or to the right of visible area ) */
1000 /* Update the DispCount */
1001 /* It might be necessary with special handling for centre aligned gads */
1002 dispstr
= &(data
->VisualBuffer
[data
->DispPos
]);
1003 /* D(bug("DispCount before = %d\n", data->DispCount)); */
1004 data
->DispCount
= TextFit(_rp(obj
), dispstr
,
1005 data
->NumChars
- data
->DispPos
,
1006 &te
, NULL
, 1, _mwidth(obj
), _mheight(obj
));
1007 /* D(bug("DispCount after = %d\n", data->DispCount)); */
1009 /* 0-terminate string (in case we put a SPACE at the end) */
1010 data
->VisualBuffer
[data
->NumChars
] = '\0';
1014 /* Gets left position of text in the string gadget */
1015 static UWORD
GetTextLeft(struct IClass
*cl
, Object
*obj
)
1017 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1018 UWORD text_left
= 0;
1019 STRPTR dispstr
= &(data
->VisualBuffer
[data
->DispPos
]);
1023 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
1024 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1026 switch (data
->msd_Align
)
1028 case MUIV_String_Format_Left
:
1029 text_left
= _mleft(obj
);
1032 case MUIV_String_Format_Center
:
1034 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
1036 textwidth
+= TextLength(_rp(obj
), " ", 1);
1037 text_left
= _mleft(obj
) + ((_mwidth(obj
) - textwidth
) / 2);
1038 /* D(bug("GetTextLeft: dispstr=%s, dispstrlen=%d, textw=%d, " */
1040 /* dispstr, dispstrlen, textwidth, text_left)); */
1044 case MUIV_String_Format_Right
:
1046 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
1049 textwidth
+= TextLength(_rp(obj
), " ", 1);
1050 text_left
= _mleft(obj
) + (_mwidth(obj
) - 1 - textwidth
);
1057 /* Gets right offset of text in the string gadget */
1058 static UWORD
GetTextRight(struct IClass
*cl
, Object
*obj
)
1060 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1061 UWORD text_right
= 0;
1062 STRPTR dispstr
= &(data
->VisualBuffer
[data
->DispPos
]);
1066 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
1067 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1069 switch (data
->msd_Align
)
1071 case MUIV_String_Format_Left
:
1073 _mleft(obj
) + TextLength(_rp(obj
), dispstr
, dispstrlen
);
1076 case MUIV_String_Format_Center
:
1078 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
1081 textwidth
+= TextLength(_rp(obj
), " ", 1);
1082 text_right
= _mright(obj
) - ((_mwidth(obj
) - textwidth
) / 2);
1086 case MUIV_String_Format_Right
:
1087 text_right
= _mright(obj
);
1090 return (text_right
);
1094 /* Updates the stringdata in case user has set some fields */
1095 static VOID
UpdateStringData(struct IClass
*cl
, Object
*obj
)
1097 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1099 data
->NumChars
= strlen(data
->Buffer
);
1101 if (data
->BufferPos
> data
->NumChars
)
1103 data
->BufferPos
= data
->NumChars
;
1107 static VOID
TextM(Object
*obj
, struct MUI_StringData
*data
,
1108 STRPTR text
, WORD textlen
, WORD markstart
, WORD markend
)
1110 struct RastPort
*rp
= _rp(obj
);
1114 if (data
->is_active
)
1115 textpen
= data
->active_text
.p_pen
;
1117 textpen
= data
->inactive_text
.p_pen
;
1119 //kprintf("TextM: textlen %d markstart %d markend %d ... \n",
1120 // textlen, markstart, markend);
1122 /* <unmarked><marked><unmarked> */
1126 len
= MIN(markstart
, textlen
);
1131 //kprintf("A: %d ", len);
1133 SetABPenDrMd(rp
, textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1134 Text(rp
, text
, len
);
1141 len
= MIN(markend
- len
, textlen
);
1146 //kprintf("B: %d ", len);
1147 SetABPenDrMd(_rp(obj
), data
->marked_text
.p_pen
,
1148 data
->marked_bg
.p_pen
, JAM2
);
1149 Text(rp
, text
, len
);
1157 //kprintf("C: %d ", textlen);
1159 SetABPenDrMd(rp
, textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1160 Text(rp
, text
, textlen
);
1165 /**************************************************************************
1167 **************************************************************************/
1168 IPTR
String__MUIM_Draw(struct IClass
*cl
, Object
*obj
,
1169 struct MUIP_Draw
*msg
)
1171 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1177 UWORD textleft_save
;
1178 WORD markstart
= 0, markstop
= 0;
1180 /* D(bug("\nString_Draw(%p) %ldx%ldx%ldx%ld reason=%ld msgflgs=%ld " */
1182 /* "displ=%ld len=%ld buf='%s'\n",obj,_mleft(obj),_mtop(obj), */
1183 /* _mwidth(obj),_mheight(obj), data->msd_RedrawReason, msg->flags, */
1184 /* data->BufferPos, data->DispPos, data->NumChars, data->Buffer)); */
1186 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1188 if (!(msg
->flags
& MADF_DRAWUPDATE
) && !(msg
->flags
& MADF_DRAWOBJECT
))
1191 PrepareVisualBuffer(data
);
1192 SetFont(_rp(obj
), _font(obj
));
1193 if (data
->is_active
)
1194 textpen
= data
->active_text
.p_pen
;
1196 textpen
= data
->inactive_text
.p_pen
;
1198 /* Update the stringdata in case of user change */
1199 UpdateStringData(cl
, obj
);
1201 /* Update the DispPos and DispCount fields so that the gadget renders
1203 UpdateDisp(cl
, obj
);
1205 text_top
= _mtop(obj
)
1206 + ((_mheight(obj
) - _rp(obj
)->Font
->tf_YSize
) >> 1)
1207 + _rp(obj
)->Font
->tf_Baseline
;
1209 dispstr
= data
->VisualBuffer
+ data
->DispPos
;
1210 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1211 textleft_save
= text_left
= GetTextLeft(cl
, obj
);
1213 // little flicker improvement, don't redraw first part of string
1214 // when adding a char
1215 if (msg
->flags
& MADF_DRAWUPDATE
&&
1216 data
->msd_RedrawReason
== DO_ADDCHAR
&&
1217 data
->msd_Align
== MUIV_String_Format_Left
&& data
->DispPos
== 0)
1219 text_left
+= TextLength(_rp(obj
), dispstr
, data
->BufferPos
- 1);
1220 dispstr
+= data
->BufferPos
- 1;
1221 dispstrlen
-= data
->BufferPos
- 1;
1222 DoMethod(obj
, MUIM_DrawBackground
, text_left
, _mtop(obj
),
1223 _mwidth(obj
) - text_left
+ _mleft(obj
), _mheight(obj
),
1224 text_left
, _mtop(obj
), 0);
1226 else if (msg
->flags
& MADF_DRAWUPDATE
)
1228 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), _mtop(obj
),
1229 _mwidth(obj
), _mheight(obj
), _mleft(obj
), _mtop(obj
), 0);
1232 SetABPenDrMd(_rp(obj
), textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1233 Move(_rp(obj
), text_left
, text_top
);
1235 if ((data
->msd_Flags
& MSDF_MARKING
)
1236 && Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
1238 TextM(obj
, data
, dispstr
, dispstrlen
, markstart
- data
->DispPos
,
1239 markstop
- data
->DispPos
);
1244 Text(_rp(obj
), dispstr
, dispstrlen
);
1246 if (data
->is_active
) // active, draw cursor
1248 UWORD cursoroffset
= data
->BufferPos
- data
->DispPos
;
1250 dispstr
= data
->VisualBuffer
+ data
->DispPos
;
1251 text_left
= textleft_save
;
1253 SetABPenDrMd(_rp(obj
), data
->active_text
.p_pen
,
1254 data
->cursor
.p_pen
, JAM2
);
1255 text_left
+= TextLength(_rp(obj
), dispstr
, cursoroffset
);
1258 Move(_rp(obj
), text_left
, text_top
);
1260 ((data
->BufferPos
< data
->NumChars
)
1261 ? dispstr
+ cursoroffset
: (STRPTR
) " "), 1);
1265 data
->msd_RedrawReason
= NO_REASON
;
1266 CleanVisualBuffer(data
);
1271 /**************************************************************************
1272 Returns whether object needs redrawing
1273 **************************************************************************/
1274 static int String_HandleVanillakey(struct IClass
*cl
, Object
*obj
,
1275 unsigned char code
, UWORD qual
, IPTR
*retval
)
1277 struct MUI_StringData
*data
=
1278 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
1281 D(bug("[MUI:String] HandleVanillakey: code=%d qual=%d\n", code
, qual
));
1286 doinput
= (data
->msd_Flags
& MSDF_NOINPUT
) ? FALSE
: TRUE
;
1288 if (doinput
&& (code
== '\b')) /* backspace */
1290 if (Buffer_KillMarked(data
))
1295 if (data
->BufferPos
> 0)
1299 if ((qual
& IEQUALIFIER_LSHIFT
) || (qual
& IEQUALIFIER_RSHIFT
))
1301 shift
= data
->BufferPos
;
1302 data
->msd_RedrawReason
= NEW_CONTENTS
;
1307 data
->msd_RedrawReason
= DO_BACKSPACE
;
1310 D(bug("[MUI:String] HandleVanillakey: 'Backspace' count=%d pos=%d"
1311 " shift=%d\n", data
->NumChars
, data
->BufferPos
, shift
));
1312 memmove(&data
->Buffer
[data
->BufferPos
- shift
],
1313 &data
->Buffer
[data
->BufferPos
],
1314 data
->NumChars
- data
->BufferPos
+ 1);
1315 data
->BufferPos
-= shift
;
1316 data
->NumChars
-= shift
;
1322 if (doinput
&& (code
== 21)) // ctrl-u == NAK (like shift-bs)
1324 if (Buffer_KillMarked(data
))
1329 if (data
->BufferPos
> 0)
1331 D(bug("[MUI:String] HandleVanillakey: 'Ctrl-U' count=%d pos=%d\n",
1332 data
->NumChars
, data
->BufferPos
));
1333 memmove(&data
->Buffer
[0],
1334 &data
->Buffer
[data
->BufferPos
],
1335 data
->NumChars
- data
->BufferPos
+ 1);
1336 data
->NumChars
-= data
->BufferPos
;
1337 data
->BufferPos
= 0;
1338 data
->msd_RedrawReason
= NEW_CONTENTS
;
1344 if (doinput
&& (code
== 127)) /* del */
1346 if (!Buffer_KillMarked(data
))
1348 if ((qual
& IEQUALIFIER_LSHIFT
) || (qual
& IEQUALIFIER_RSHIFT
))
1350 data
->Buffer
[data
->BufferPos
] = 0;
1351 data
->NumChars
= data
->BufferPos
;
1352 data
->msd_RedrawReason
= NEW_CONTENTS
;
1356 if (data
->BufferPos
< data
->NumChars
)
1358 D(bug("[MUI:String] HandleVanillakey: 'Delete' count=%d"
1359 " pos=%d\n", data
->NumChars
, data
->BufferPos
));
1360 memmove(&data
->Buffer
[data
->BufferPos
],
1361 &data
->Buffer
[data
->BufferPos
+ 1],
1362 data
->NumChars
- data
->BufferPos
);
1366 data
->msd_RedrawReason
= DO_DELETE
;
1372 if (doinput
&& (code
== 11)) // ctrl-k == VT == \v (like shift-del)
1374 if (!Buffer_KillMarked(data
))
1376 data
->Buffer
[data
->BufferPos
] = 0;
1377 data
->NumChars
= data
->BufferPos
;
1378 data
->msd_RedrawReason
= NEW_CONTENTS
;
1383 if (doinput
&& (code
== 24)) /* ctrl x == ascii cancel */
1385 if (!Buffer_KillMarked(data
))
1387 data
->Buffer
[0] = 0;
1388 data
->BufferPos
= 0;
1390 data
->msd_RedrawReason
= NEW_CONTENTS
;
1395 if (code
== 1) // ctrl-a, linestart
1397 data
->BufferPos
= 0;
1398 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
1402 if (code
== 26) // ctrl-z, lineend
1404 data
->BufferPos
= data
->NumChars
;
1405 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
1409 if (code
== '\t') // tab
1414 if (((ToLower(code
) == 'c') || (ToLower(code
) == 'x')) &&
1415 (qual
& IEQUALIFIER_RCOMMAND
))
1417 WORD markstart
, markstop
;
1419 if ((data
->msd_Flags
& MSDF_MARKING
)
1420 && Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
1422 clipboard_write_text(&data
->Buffer
[markstart
],
1423 markstop
- markstart
);
1425 if (doinput
&& (ToLower(code
) == 'x'))
1427 Buffer_KillMarked(data
);
1431 data
->BufferPos
= markstop
;
1432 data
->msd_Flags
&= ~MSDF_MARKING
;
1439 if (doinput
&& (ToLower(code
) == 'v') && (qual
& IEQUALIFIER_RCOMMAND
))
1443 struct Locale
*locale
= OpenLocale(NULL
);
1445 retval
= Buffer_KillMarked(data
);
1446 if ((text
= clipboard_read_text()))
1448 STRPTR text2
= text
;
1451 while ((c
= *text2
++))
1453 if (!IsPrint(locale
, c
))
1455 if (!(Buffer_AddChar(data
, c
)))
1461 clipboard_free_text(text
);
1464 CloseLocale(locale
);
1469 if (data
->msd_Accept
!= NULL
)
1471 /* Check if character is accepted */
1472 if (NULL
== strchr(data
->msd_Accept
, code
))
1475 *retval
= MUI_EventHandlerRC_Eat
;
1480 if (data
->msd_Reject
!= NULL
)
1482 /* Check if character is rejected */
1483 if (NULL
!= strchr(data
->msd_Reject
, code
))
1486 *retval
= MUI_EventHandlerRC_Eat
;
1493 struct Locale
*locale
= OpenLocale(NULL
);
1495 if (!(code
>= 0x09 && code
<= 0x0D) && IsPrint(locale
, code
))
1497 Buffer_KillMarked(data
);
1498 if (Buffer_AddChar(data
, code
))
1500 data
->msd_RedrawReason
= DO_ADDCHAR
;
1505 CloseLocale(locale
);
1508 data
->msd_RedrawReason
= DO_UNKNOWN
;
1513 /**************************************************************************
1515 **************************************************************************/
1516 IPTR
String__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
,
1517 struct MUIP_HandleEvent
*msg
)
1519 struct MUI_StringData
*data
=
1520 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
1523 BOOL edited
= FALSE
;
1524 LONG muikey
= msg
->muikey
;
1525 BOOL cursor_kills_marking
= FALSE
;
1527 if ((data
->msd_Flags
& MSDF_MARKING
)
1528 && !(data
->msd_Flags
& MSDF_KEYMARKING
))
1530 cursor_kills_marking
= TRUE
;
1533 /* Convert raw keys to MUI keys for marking */
1534 if (muikey
== MUIKEY_NONE
&& msg
->imsg
!= NULL
)
1536 if (msg
->imsg
->Class
== IDCMP_RAWKEY
)
1538 static LONG muikeytable
[3][2] = {
1539 {MUIKEY_LEFT
, MUIKEY_RIGHT
},
1540 {MUIKEY_WORDLEFT
, MUIKEY_WORDRIGHT
},
1541 {MUIKEY_LINESTART
, MUIKEY_LINEEND
}
1543 WORD dirindex
= -1, amountindex
= 0;
1545 switch (msg
->imsg
->Code
)
1557 muikey
= MUIKEY_LINESTART
;
1561 muikey
= MUIKEY_LINEEND
;
1570 Qualifier
& (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
1574 else if (msg
->imsg
->Qualifier
& IEQUALIFIER_CONTROL
)
1579 muikey
= muikeytable
[amountindex
][dirindex
];
1585 D(bug("[MUI:String] HandleEvent: muikey %d, imsg %p is_active=%d\n", muikey
,
1586 msg
->imsg
, data
->is_active
));
1587 if (muikey
!= MUIKEY_NONE
&& data
->is_active
)
1589 retval
= MUI_EventHandlerRC_Eat
;
1594 if (cursor_kills_marking
)
1597 data
->BufferPos
= MIN(data
->BufferPos
, data
->MarkPos
);
1598 if (data
->BufferPos
> 0)
1601 data
->msd_Flags
&= ~MSDF_MARKING
;
1603 else if (data
->BufferPos
> 0)
1608 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1612 if (cursor_kills_marking
)
1615 data
->BufferPos
= MAX(data
->BufferPos
, data
->MarkPos
);
1616 data
->msd_Flags
&= ~MSDF_MARKING
;
1618 else if (data
->BufferPos
< data
->NumChars
)
1622 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1625 case MUIKEY_WORDLEFT
:
1626 if (data
->BufferPos
> 0)
1629 Buffer_GetPrevWordIndex(data
, data
->BufferPos
);
1631 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1633 if (cursor_kills_marking
)
1635 data
->msd_Flags
&= ~MSDF_MARKING
;
1639 case MUIKEY_WORDRIGHT
:
1640 if (data
->BufferPos
< data
->NumChars
)
1643 Buffer_GetSuccWordIndex(data
, data
->BufferPos
);
1645 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1647 if (cursor_kills_marking
)
1649 data
->msd_Flags
&= ~MSDF_MARKING
;
1653 case MUIKEY_LINESTART
:
1654 data
->BufferPos
= 0;
1656 if (cursor_kills_marking
)
1658 data
->msd_Flags
&= ~MSDF_MARKING
;
1662 case MUIKEY_LINEEND
:
1663 data
->BufferPos
= data
->NumChars
;
1665 if (cursor_kills_marking
)
1667 data
->msd_Flags
&= ~MSDF_MARKING
;
1672 if (data
->msd_AttachedList
)
1673 set(data
->msd_AttachedList
,
1674 MUIA_List_Active
, MUIV_List_Active_Up
);
1677 if (data
->msd_AttachedList
)
1678 set(data
->msd_AttachedList
,
1679 MUIA_List_Active
, MUIV_List_Active_Down
);
1682 if (data
->msd_AttachedList
)
1683 set(data
->msd_AttachedList
,
1684 MUIA_List_Active
, MUIV_List_Active_PageUp
);
1686 case MUIKEY_PAGEDOWN
:
1687 if (data
->msd_AttachedList
)
1688 set(data
->msd_AttachedList
,
1689 MUIA_List_Active
, MUIV_List_Active_PageDown
);
1692 if (data
->msd_AttachedList
)
1693 set(data
->msd_AttachedList
,
1694 MUIA_List_Active
, MUIV_List_Active_Top
);
1697 if (data
->msd_AttachedList
)
1698 set(data
->msd_AttachedList
,
1699 MUIA_List_Active
, MUIV_List_Active_Bottom
);
1706 get(obj
, MUIA_String_Contents
, &buf
);
1708 if (data
->msd_Flags
& MSDF_STAYACTIVE
)
1710 /* Do not change active object */
1712 else if (data
->msd_Flags
& MSDF_ADVANCEONCR
)
1714 set(_win(obj
), MUIA_Window_ActiveObject
,
1715 MUIV_Window_ActiveObject_Next
);
1717 else if (!(data
->msd_Flags
& MSDF_STAYACTIVE
))
1719 set(_win(obj
), MUIA_Window_ActiveObject
,
1720 MUIV_Window_ActiveObject_None
);
1723 /* Notify listeners of new string value */
1724 set(obj
, MUIA_String_Acknowledge
, buf
);
1726 /* Notify listeners of new integer value (if any) */
1727 if (StrToLong(buf
, &val
) >= 0)
1728 superset(cl
, obj
, MUIA_String_Integer
, val
);
1732 case MUIKEY_WINDOW_CLOSE
:
1733 data
->is_active
= FALSE
;
1734 set(obj
, MUIA_Background
,
1735 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
1736 DoMethod(obj
, MUIM_GoInactive
);
1743 } // if (muikey != MUIKEY_NONE)
1747 UWORD code
= msg
->imsg
->Code
;
1748 //UWORD qual = msg->imsg->Qualifier;
1749 WORD x
= msg
->imsg
->MouseX
;
1750 WORD y
= msg
->imsg
->MouseY
;
1752 //bug("String_HandleEvent: parsing imsg %p, class=%ld\n",
1753 // msg->imsg, msg->imsg->Class);
1755 switch (msg
->imsg
->Class
)
1757 case IDCMP_MOUSEBUTTONS
: /* set cursor and activate it */
1758 if (code
== SELECTDOWN
)
1760 //bug("String_HandleEvent: code == SELECTDOWN, x=%d y=%d\n",
1763 if (_isinobject(obj
, x
, y
))
1765 UWORD text_left
, text_right
;
1767 retval
= MUI_EventHandlerRC_Eat
;
1769 CurrentTime(&data
->NewClick_Sec
, &data
->NewClick_Micro
);
1770 if (DoubleClick(data
->OldClick_Sec
,
1771 data
->OldClick_Micro
, data
->NewClick_Sec
,
1772 data
->NewClick_Micro
))
1778 data
->MultiClick
= 0;
1780 data
->OldClick_Sec
= data
->NewClick_Sec
;
1781 data
->OldClick_Micro
= data
->NewClick_Micro
;
1783 //kprintf("multiclick %d\n", data->MultiClick);
1785 if (!data
->is_active
)
1787 //bug("String got button, lets activate\n");
1788 data
->is_active
= TRUE
;
1789 data
->msd_RedrawReason
= WENT_ACTIVE
;
1791 set(obj
, MUIA_Background
,
1792 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->
1795 //DoMethod(obj, MUIM_GoActive);
1796 set(_win(obj
), MUIA_Window_ActiveObject
, obj
);
1797 // let other objects a chance to get desactivated
1801 if (!(data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
))
1803 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1804 (IPTR
) & data
->ehn
);
1805 data
->ehn
.ehn_Events
|= IDCMP_MOUSEMOVE
;
1806 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1807 (IPTR
) & data
->ehn
);
1810 PrepareVisualBuffer(data
);
1811 text_left
= GetTextLeft(cl
, obj
);
1812 text_right
= GetTextRight(cl
, obj
);
1813 CleanVisualBuffer(data
);
1815 /* Check if mouseclick is inside displayed text */
1816 if ((x
>= text_left
) && (x
<= text_right
))
1818 /* Find new cursor pos. */
1819 struct TextExtent te
;
1821 STRPTR dispstr
= data
->Buffer
+ data
->DispPos
;
1823 newpos
= data
->DispPos
1824 + TextFit(_rp(obj
), dispstr
,
1825 data
->NumChars
- data
->DispPos
, &te
, NULL
, 1,
1826 x
- text_left
, _rp(obj
)->Font
->tf_YSize
);
1828 if (data
->BufferPos
!= newpos
)
1830 data
->BufferPos
= newpos
;
1834 else if (x
< text_left
)
1836 /* Click on empty space at left. Set cursor to first
1838 if (data
->BufferPos
!= data
->DispPos
)
1840 data
->BufferPos
= data
->DispPos
;
1846 /* Click on empty space at right. Set cursor to last
1848 if (data
->BufferPos
!=
1849 data
->DispPos
+ data
->DispCount
)
1852 data
->DispPos
+ data
->DispCount
;
1855 } /* if (click is on text or not) */
1857 data
->MarkPos
= data
->BufferPos
;
1859 if (data
->MultiClick
== 0)
1861 if (data
->msd_Flags
& MSDF_MARKING
)
1863 data
->msd_Flags
&= ~MSDF_MARKING
;
1867 else if (data
->MultiClick
1868 && Buffer_GetMarkedRange(data
, NULL
, NULL
))
1870 data
->msd_Flags
|= MSDF_MARKING
;
1875 } /* is in object */
1876 else if (data
->is_active
1877 && !(data
->msd_Flags
& MSDF_STAYACTIVE
))
1878 /* and click not on object */
1880 data
->is_active
= FALSE
;
1881 set(obj
, MUIA_Background
,
1882 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->
1883 string_bg_inactive
);
1884 //DoMethod(obj, MUIM_GoInactive);
1885 // let other objects a chance to get activated
1888 } /* if (code == SELECTDOWN) */
1889 else if (code
== SELECTUP
)
1891 if (data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
)
1893 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1894 (IPTR
) & data
->ehn
);
1895 data
->ehn
.ehn_Events
&= ~IDCMP_MOUSEMOVE
;
1896 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1897 (IPTR
) & data
->ehn
);
1902 case IDCMP_MOUSEMOVE
:
1903 if (data
->is_active
)
1905 UWORD text_left
, text_right
;
1907 if (!(data
->msd_Flags
& MSDF_MARKING
))
1909 data
->msd_Flags
|= MSDF_MARKING
;
1912 PrepareVisualBuffer(data
);
1913 text_left
= GetTextLeft(cl
, obj
);
1914 text_right
= GetTextRight(cl
, obj
);
1915 CleanVisualBuffer(data
);
1917 /* Check if mouseclick is inside displayed text */
1918 if ((x
>= text_left
) && (x
<= text_right
))
1920 /* Find new cursor pos. */
1921 struct TextExtent te
;
1923 STRPTR dispstr
= data
->Buffer
+ data
->DispPos
;
1925 newpos
= data
->DispPos
1926 + TextFit(_rp(obj
), dispstr
,
1927 data
->NumChars
- data
->DispPos
, &te
, NULL
, 1,
1928 x
- text_left
, _rp(obj
)->Font
->tf_YSize
);
1930 if (data
->BufferPos
!= newpos
)
1932 WORD old_markstart
= 0, old_markstop
= 0;
1933 WORD markstart
= 0, markstop
= 0;
1934 BOOL was_marked
, is_marked
;
1936 was_marked
= Buffer_AnythingMarked(data
) &&
1937 Buffer_GetMarkedRange(data
, &old_markstart
,
1940 data
->BufferPos
= newpos
;
1942 is_marked
= Buffer_AnythingMarked(data
) &&
1943 Buffer_GetMarkedRange(data
, &markstart
,
1946 if ((was_marked
!= is_marked
) ||
1947 (old_markstart
!= markstart
) ||
1948 (old_markstop
!= markstop
))
1954 else if ((x
< text_left
) && (data
->BufferPos
> 0))
1958 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1960 else if ((x
> text_right
)
1961 && (data
->BufferPos
< data
->NumChars
))
1965 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1967 //kprintf(" ---- bp: %d\n", data->BufferPos);
1975 //bug("String_HandleEvent: idcmp_rawkey\n");
1977 if (!data
->is_active
)
1980 code
= ConvertKey(msg
->imsg
);
1983 switch (msg
->imsg
->Code
)
1985 case 0x64: /* LALT */
1986 case 0x65: /* RALT */
1987 case 0x64 | IECODE_UP_PREFIX
:
1988 case 0x65 | IECODE_UP_PREFIX
:
1990 Qualifier
& (IEQUALIFIER_LALT
|
1993 data
->MarkPos
= data
->BufferPos
;
1995 (MSDF_MARKING
| MSDF_KEYMARKING
);
1999 data
->msd_Flags
&= ~MSDF_KEYMARKING
;
2009 String_HandleVanillakey(cl
, obj
, code
,
2010 msg
->imsg
->Qualifier
, &retval
);
2013 retval
= MUI_EventHandlerRC_Eat
;
2022 /* Trigger notification */
2024 superset(cl
, obj
, MUIA_String_Contents
, data
->Buffer
);
2028 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2030 //D(bug("String eh return %ld\n", retval));
2036 /**************************************************************************
2037 MUIM_Export : to export an object's "contents" to a dataspace object.
2038 **************************************************************************/
2039 IPTR
String__MUIM_Export(struct IClass
*cl
, Object
*obj
,
2040 struct MUIP_Export
*msg
)
2042 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
2045 if ((id
= muiNotifyData(obj
)->mnd_ObjectID
))
2047 if (data
->Buffer
!= NULL
)
2048 DoMethod(msg
->dataspace
, MUIM_Dataspace_Add
,
2049 (IPTR
) data
->Buffer
, data
->NumChars
+ 1, (IPTR
) id
);
2051 DoMethod(msg
->dataspace
, MUIM_Dataspace_Remove
, (IPTR
) id
);
2058 /**************************************************************************
2059 MUIM_Import : to import an object's "contents" from a dataspace object.
2060 **************************************************************************/
2061 IPTR
String__MUIM_Import(struct IClass
*cl
, Object
*obj
,
2062 struct MUIP_Import
*msg
)
2067 if ((id
= muiNotifyData(obj
)->mnd_ObjectID
))
2069 if ((s
= (STRPTR
) DoMethod(msg
->dataspace
, MUIM_Dataspace_Find
,
2072 set(obj
, MUIA_String_Contents
, s
);
2079 /**************************************************************************
2081 **************************************************************************/
2082 IPTR
String__MUIM_GoActive(struct IClass
*cl
, Object
*obj
, Msg msg
)
2084 struct MUI_StringData
*data
=
2085 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2087 //D(bug("String_GoActive %p\n", obj));
2088 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
2089 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
| IDCMP_RAWKEY
;
2090 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
2091 data
->is_active
= TRUE
;
2092 data
->msd_Flags
&= ~MSDF_KEYMARKING
;
2093 data
->msd_RedrawReason
= WENT_ACTIVE
;
2095 set(obj
, MUIA_Background
,
2096 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_active
);
2101 /**************************************************************************
2103 **************************************************************************/
2104 IPTR
String__MUIM_GoInactive(struct IClass
*cl
, Object
*obj
, Msg msg
)
2106 struct MUI_StringData
*data
=
2107 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2109 //D(bug("String_GoInactive %p\n", obj));
2111 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
2112 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
2113 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
2114 data
->is_active
= FALSE
;
2115 data
->msd_RedrawReason
= WENT_INACTIVE
;
2116 data
->MultiClick
= 0;
2119 set(obj
, MUIA_Background
,
2120 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
2125 /**************************************************************************
2126 MUIM_String_ClearSelected (BetterString)
2127 **************************************************************************/
2128 IPTR
String__MUIM_ClearSelected(struct IClass
*cl
, Object
*obj
,
2129 struct MUIP_String_ClearSelected
*msg
)
2131 struct MUI_StringData
*data
=
2132 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2134 //D(bug("String_ClearSelected %p\n", obj));
2136 if (Buffer_KillMarked(data
))
2138 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2144 /**************************************************************************
2145 MUIM_String_Insert (BetterString)
2146 **************************************************************************/
2147 IPTR
String__MUIM_Insert(struct IClass
*cl
, Object
*obj
,
2148 struct MUIP_String_Insert
*msg
)
2150 struct MUI_StringData
*data
=
2151 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2153 ULONG old_bufferpos
;
2154 ULONG num_inserted
= 0;
2156 //D(bug("String_Insert %p\n", obj));
2158 switch ((ULONG
) msg
->pos
)
2160 case MUIV_String_Insert_StartOfString
:
2164 case MUIV_String_Insert_EndOfString
:
2165 pos
= data
->NumChars
;
2168 case MUIV_String_Insert_BufferPos
:
2169 pos
= data
->BufferPos
;
2177 if ((pos
< 0) || (pos
> data
->NumChars
))
2180 old_bufferpos
= data
->BufferPos
;
2181 data
->BufferPos
= pos
;
2183 while (msg
->text
[num_inserted
]
2184 && Buffer_AddChar(data
, msg
->text
[num_inserted
]))
2191 if (old_bufferpos
>= pos
)
2193 data
->BufferPos
= old_bufferpos
+ num_inserted
;
2197 data
->BufferPos
= old_bufferpos
;
2200 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2206 /**************************************************************************
2207 MUIM_String_FileNameStart (BetterString)
2208 **************************************************************************/
2209 IPTR
String__MUIM_FileNameStart(struct IClass
*cl
, Object
*obj
,
2210 struct MUIP_String_FileNameStart
*msg
)
2212 struct MUI_StringData
*data
=
2213 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2216 //D(bug("String_FileNameStart %p\n", obj));
2220 // TODO: Implement String_FileNameStart correctly!
2225 BOOPSI_DISPATCHER(IPTR
, String_Dispatcher
, cl
, obj
, msg
)
2227 switch (msg
->MethodID
)
2230 return String__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
2232 return String__OM_DISPOSE(cl
, obj
, msg
);
2234 return String__OM_SET(cl
, obj
, (struct opSet
*)msg
);
2236 return String__OM_GET(cl
, obj
, (struct opGet
*)msg
);
2239 return String__MUIM_Setup(cl
, obj
, (APTR
) msg
);
2241 return String__MUIM_Cleanup(cl
, obj
, (APTR
) msg
);
2242 case MUIM_AskMinMax
:
2243 return String__MUIM_AskMinMax(cl
, obj
, (APTR
) msg
);
2245 return String__MUIM_Draw(cl
, obj
, (APTR
) msg
);
2247 return String__MUIM_Export(cl
, obj
, (APTR
) msg
);
2249 return String__MUIM_Import(cl
, obj
, (APTR
) msg
);
2251 return String__MUIM_GoActive(cl
, obj
, (APTR
) msg
);
2252 case MUIM_GoInactive
:
2253 return String__MUIM_GoInactive(cl
, obj
, (APTR
) msg
);
2254 case MUIM_HandleEvent
:
2255 return String__MUIM_HandleEvent(cl
, obj
, (APTR
) msg
);
2258 case MUIM_String_ClearSelected
:
2259 return String__MUIM_ClearSelected(cl
, obj
, (APTR
) msg
);
2260 case MUIM_String_Insert
:
2261 return String__MUIM_Insert(cl
, obj
, (APTR
) msg
);
2262 case MUIM_String_FileNameStart
:
2263 return String__MUIM_FileNameStart(cl
, obj
, (APTR
) msg
);
2266 return DoSuperMethodA(cl
, obj
, msg
);
2268 BOOPSI_DISPATCHER_END
2273 const struct __MUIBuiltinClass _MUI_String_desc
=
2277 sizeof(struct MUI_StringData
),
2278 (void *)String_Dispatcher