2 Copyright © 2003-2015, 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("MUIC_String: Can't 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("MUIC_String: Can't 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);
455 data
->NumChars
-= marklen
;
456 data
->BufferPos
= markstart
;
461 /**************************************************************************
463 **************************************************************************/
464 IPTR
String__OM_NEW(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
466 struct MUI_StringData
*data
;
467 struct TagItem
*tags
, *tag
;
468 CONST_STRPTR str
= NULL
;
471 obj
= (Object
*) DoSuperNewTags(cl
, obj
, NULL
,
472 /* MUIA_FillArea, TRUE, */
473 TAG_MORE
, (IPTR
) msg
->ops_AttrList
);
477 data
= INST_DATA(cl
, obj
);
478 data
->msd_useSecret
= FALSE
;
479 data
->msd_Align
= MUIV_String_Format_Left
;
480 data
->BufferSize
= 80;
483 Buffer_SetNewContents(data
, ""); /* <-- isn't this pointless? */
485 /* parse initial taglist */
486 for (tags
= msg
->ops_AttrList
; (tag
= NextTagItem(&tags
));)
490 case MUIA_String_Accept
:
491 data
->msd_Accept
= (CONST_STRPTR
) tag
->ti_Data
;
494 case MUIA_String_Reject
:
495 data
->msd_Reject
= (CONST_STRPTR
) tag
->ti_Data
;
498 case MUIA_String_AdvanceOnCR
:
499 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
503 case MUIA_String_BufferPos
:
504 data
->BufferPos
= (ULONG
) tag
->ti_Data
;
507 case MUIA_String_AttachedList
:
508 data
->msd_AttachedList
= (Object
*) tag
->ti_Data
;
511 case MUIA_String_Secret
:
512 data
->msd_useSecret
= (BOOL
) tag
->ti_Data
;
515 case MUIA_String_Contents
:
516 str
= (CONST_STRPTR
) tag
->ti_Data
;
519 case MUIA_String_EditHook
:
520 data
->msd_EditHook
= (struct Hook
*)tag
->ti_Data
;
523 case MUIA_String_Format
:
524 data
->msd_Align
= (LONG
) tag
->ti_Data
;
527 case MUIA_String_Integer
:
528 snprintf(integerbuf
, 19, "%ld", tag
->ti_Data
);
532 case MUIA_String_LonelyEditHook
:
533 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
534 MSDF_LONELYEDITHOOK
);
537 case MUIA_String_MaxLen
:
538 data
->BufferSize
= tag
->ti_Data
;
539 if (data
->BufferSize
< 1)
540 data
->BufferSize
= 1;
543 case MUIA_String_Columns
: /* BetterString */
544 data
->Columns
= (WORD
) tag
->ti_Data
;
547 case MUIA_String_NoInput
: /* BetterString */
548 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_NOINPUT
);
551 case MUIA_String_StayActive
: /* BetterString */
552 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
559 if (Buffer_Alloc(data
))
561 Buffer_SetNewContents(data
, str
);
564 if (NULL
== data
->Buffer
)
566 CoerceMethod(cl
, obj
, OM_DISPOSE
);
570 D(bug("String_New(%p)\n", obj
));
572 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
573 data
->ehn
.ehn_Priority
= 0;
574 data
->ehn
.ehn_Flags
= 0;
575 data
->ehn
.ehn_Object
= obj
;
576 data
->ehn
.ehn_Class
= cl
;
578 CurrentTime(&data
->OldClick_Sec
, &data
->OldClick_Micro
);
583 /**************************************************************************
585 **************************************************************************/
586 IPTR
String__OM_DISPOSE(struct IClass
*cl
, Object
*obj
, Msg msg
)
588 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
590 FreeVec(data
->Buffer
);
591 FreeVec(data
->SecBuffer
);
593 D(bug("String_Dispose %p\n", obj
));
595 return DoSuperMethodA(cl
, obj
, msg
);
598 /**************************************************************************
600 **************************************************************************/
601 IPTR
String__OM_SET(struct IClass
*cl
, Object
*obj
, struct opSet
*msg
)
603 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
604 struct TagItem
*tags
= msg
->ops_AttrList
;
607 while ((tag
= NextTagItem(&tags
)) != NULL
)
611 case MUIA_String_Contents
:
612 Buffer_SetNewContents(data
, (STRPTR
) tag
->ti_Data
);
613 data
->msd_RedrawReason
= NEW_CONTENTS
;
614 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
615 MUI_Redraw(obj
, MADF_DRAWOBJECT
);
618 case MUIA_String_Accept
:
619 data
->msd_Accept
= (CONST_STRPTR
) tag
->ti_Data
;
622 case MUIA_String_Reject
:
623 data
->msd_Reject
= (CONST_STRPTR
) tag
->ti_Data
;
626 case MUIA_String_AttachedList
:
627 data
->msd_AttachedList
= (Object
*) tag
->ti_Data
;
630 case MUIA_String_Integer
:
634 snprintf(buf
, 19, "%ld", tag
->ti_Data
);
635 set(obj
, MUIA_String_Contents
, buf
);
639 case MUIA_String_AdvanceOnCR
:
640 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
644 case MUIA_String_BufferPos
:
645 data
->BufferPos
= (ULONG
) tag
->ti_Data
;
646 data
->msd_Flags
&= ~MSDF_MARKING
;
647 data
->msd_RedrawReason
= MOVE_CURSOR
;
648 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
651 case MUIA_String_DisplayPos
:
652 data
->BufferPos
= (ULONG
) tag
->ti_Data
;
653 data
->DispPos
= data
->BufferPos
; // move both pos
654 data
->msd_Flags
&= ~MSDF_MARKING
;
655 data
->msd_RedrawReason
= MOVE_CURSOR
;
656 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
659 case MUIA_String_NoInput
: /* BetterString */
660 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
, MSDF_NOINPUT
);
663 case MUIA_String_StayActive
: /* BetterString */
664 _handle_bool_tag(data
->msd_Flags
, tag
->ti_Data
,
668 case MUIA_String_SelectSize
: /* BetterString */
669 // TODO: Implement OM_SET(MUIA_String_SelectSize)!
675 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
679 /**************************************************************************
681 **************************************************************************/
682 IPTR
String__OM_GET(struct IClass
*cl
, Object
*obj
, struct opGet
*msg
)
684 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
686 #define STORE *(msg->opg_Storage)
687 switch (msg
->opg_AttrID
)
689 case MUIA_String_Contents
:
690 STORE
= (IPTR
) data
->Buffer
;
693 case MUIA_String_Secret
:
694 STORE
= (IPTR
) data
->msd_useSecret
;
697 case MUIA_String_Accept
:
698 STORE
= (IPTR
) data
->msd_Accept
;
701 case MUIA_String_Reject
:
702 STORE
= (IPTR
) data
->msd_Reject
;
705 case MUIA_String_AttachedList
:
706 STORE
= (IPTR
) data
->msd_AttachedList
;
709 case MUIA_String_Format
:
710 STORE
= (IPTR
) data
->msd_Align
;
713 case MUIA_String_Integer
:
717 get(obj
, MUIA_String_Contents
, &buf
);
721 StrToLong(buf
, &val
);
727 case MUIA_String_MaxLen
:
728 STORE
= (IPTR
) data
->BufferSize
;
731 case MUIA_String_AdvanceOnCR
:
732 STORE
= (data
->msd_Flags
& MSDF_ADVANCEONCR
) ? TRUE
: FALSE
;
735 case MUIA_String_BufferPos
:
736 STORE
= data
->BufferPos
;
739 case MUIA_String_DisplayPos
:
740 STORE
= data
->DispPos
;
743 case MUIA_String_NoInput
: /* BetterString */
744 STORE
= (data
->msd_Flags
& MSDF_NOINPUT
) ? TRUE
: FALSE
;
747 case MUIA_String_StayActive
: /* BetterString */
748 STORE
= (data
->msd_Flags
& MSDF_STAYACTIVE
) ? TRUE
: FALSE
;
751 case MUIA_String_SelectSize
: /* BetterString */
752 if (data
->msd_Flags
& MSDF_MARKING
)
754 WORD markstart
, markstop
;
756 if (Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
758 LONG size
= markstop
- markstart
;
760 if (data
->MarkPos
< data
->BufferPos
)
775 return DoSuperMethodA(cl
, obj
, (Msg
) msg
);
779 /**************************************************************************
781 **************************************************************************/
782 IPTR
String__MUIM_Setup(struct IClass
*cl
, Object
*obj
,
783 struct MUIP_Setup
*msg
)
785 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
787 if (0 == DoSuperMethodA(cl
, obj
, (Msg
) msg
))
790 data
->is_active
= FALSE
;
791 set(obj
, MUIA_Background
,
792 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
794 zune_pen_spec_to_intern(
795 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
796 string_text_inactive
, &data
->inactive_text
);
797 zune_penspec_setup(&data
->inactive_text
, muiRenderInfo(obj
));
799 zune_pen_spec_to_intern(
800 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
801 string_text_active
, &data
->active_text
);
802 zune_penspec_setup(&data
->active_text
, muiRenderInfo(obj
));
804 zune_pen_spec_to_intern(
805 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
806 string_text_marked
, &data
->marked_text
);
807 zune_penspec_setup(&data
->marked_text
, muiRenderInfo(obj
));
809 zune_pen_spec_to_intern(
810 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
811 string_bg_marked
, &data
->marked_bg
);
812 zune_penspec_setup(&data
->marked_bg
, muiRenderInfo(obj
));
814 zune_pen_spec_to_intern(
815 (const struct MUI_PenSpec
*)muiGlobalInfo(obj
)->mgi_Prefs
->
816 string_cursor
, &data
->cursor
);
817 zune_penspec_setup(&data
->cursor
, muiRenderInfo(obj
));
819 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
823 /**************************************************************************
825 **************************************************************************/
826 IPTR
String__MUIM_Cleanup(struct IClass
*cl
, Object
*obj
,
827 struct MUIP_Cleanup
*msg
)
829 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
831 D(bug("String_Cleanup %p\n", obj
));
832 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
834 zune_penspec_cleanup(&data
->inactive_text
);
835 zune_penspec_cleanup(&data
->active_text
);
836 zune_penspec_cleanup(&data
->marked_text
);
837 zune_penspec_cleanup(&data
->marked_bg
);
838 zune_penspec_cleanup(&data
->cursor
);
840 return (DoSuperMethodA(cl
, obj
, (Msg
) msg
));
843 /**************************************************************************
845 **************************************************************************/
846 IPTR
String__MUIM_AskMinMax(struct IClass
*cl
, Object
*obj
,
847 struct MUIP_AskMinMax
*msg
)
849 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
851 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
853 if (data
->Columns
>= 0)
855 msg
->MinMaxInfo
->MinWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
856 msg
->MinMaxInfo
->DefWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
857 msg
->MinMaxInfo
->MaxWidth
+= _font(obj
)->tf_XSize
* data
->Columns
;
861 msg
->MinMaxInfo
->MinWidth
+= _font(obj
)->tf_XSize
* 4;
862 msg
->MinMaxInfo
->DefWidth
+= _font(obj
)->tf_XSize
* 12;
863 msg
->MinMaxInfo
->MaxWidth
= MUI_MAXMAX
;
866 msg
->MinMaxInfo
->MinHeight
+= _font(obj
)->tf_YSize
;
867 msg
->MinMaxInfo
->DefHeight
+= _font(obj
)->tf_YSize
;
868 msg
->MinMaxInfo
->MaxHeight
+= _font(obj
)->tf_YSize
;
870 /* D(bug("String_AskMinMax(%p): Min=%ldx%ld Max=%ldx%ld Def=%ldx%ld\n", */
871 /* obj, msg->MinMaxInfo->MinWidth, msg->MinMaxInfo->MinHeight, */
872 /* msg->MinMaxInfo->MaxWidth, msg->MinMaxInfo->MaxHeight, */
873 /* msg->MinMaxInfo->DefWidth, msg->MinMaxInfo->DefHeight)); */
879 static WORD
MaxDispPos(struct IClass
*cl
, Object
*obj
)
881 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
882 WORD numfit
, max_disppos
, numchars
;
883 struct TextExtent te
;
886 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
888 /* D(bug("MaxDispPos(current length: %d, bufferpos=%d)\n", */
889 /* data->NumChars, data->BufferPos)); */
891 /* D(bug("cursor_at_end: %d\n", cursor_at_end)); */
893 if (cursor_at_end
) /* Cursor at end of string ? */
895 /* D(bug("Making cursor last char\n")); */
896 numchars
= data
->NumChars
+ 1; /* Take cursor into account */
898 /* This has already been done by UpdateDisp() which called us
899 strinfo->Buffer[strinfo->NumChars] = 0x20;
905 numchars
= data
->NumChars
;
908 /* Find the amount of characters that fit into the bbox, counting
909 ** from the last character in the buffer and forward,
911 numfit
= TextFit(_rp(obj
),
912 &(data
->Buffer
[numchars
- 1]),
913 numchars
, &te
, NULL
, -1, _mwidth(obj
), _mheight(obj
));
915 max_disppos
= numchars
- numfit
;
917 /* if ((max_disppos > 0) && (!cursor_at_end))
921 /* D(bug("Numchars w/cursor: %d, Numfit: %d, maxdisppos=%d " */
922 /* "bbox->Width = %d te->te_Width = %d\n", */
923 /* numchars, numfit, max_disppos, _mwidth(obj), te.te_Width)); */
929 static void UpdateDisp(struct IClass
*cl
, Object
*obj
)
931 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
932 struct TextExtent te
;
935 /* If the cursor is at the trailing \0, insert a SPACE instead */
936 if (data
->BufferPos
== data
->NumChars
)
937 data
->VisualBuffer
[data
->NumChars
] = ' ';
939 /* In this function we check if the cursor has gone outside
940 ** of the visible area (because of application setting
941 ** strinfo->BufferPos or strinfo->DispPos to a different value, or
942 ** because of user input).
943 ** This is made a bit difficult by the rule (R), that there
944 ** should NOT be available space on the right, and characters
945 ** scrolled out at the left, at the same time.
946 ** We have 3 possible scenarios:
947 ** 1) Cursor to the left of DispPos:
948 ** Set DispPos to the lowest of BufferPos and the
949 ** maximum allowed disppos (according to (R) ).
950 ** 2) Cursor to the right of visible area:
951 ** Set dispose sou that the cursor is the last visible character.
952 ** This afheres to (R).
953 ** 3) Cursor inside visible area. Do a check on rule (R),
954 ** and if DispPos > max allowed, then adjust it down,
955 ** so that the last character in the buffer becomes last character
956 ** displayed. (The cursor will still be visible after adjustion)
959 /* 1) Cursor to the left of visible area */
960 if (data
->BufferPos
< data
->DispPos
)
964 max_disppos
= MaxDispPos(cl
, obj
);
965 data
->DispPos
= MIN(data
->BufferPos
, max_disppos
);
967 else /* Cursor equal to the right of disppos [ 2) or 3) ] */
971 /* How many pixels are there from current 1st displayed to cursor? */
972 strsize
= TextLength(_rp(obj
),
973 data
->VisualBuffer
+ data
->DispPos
,
974 data
->BufferPos
- data
->DispPos
+ 1);
976 /* 2) More than fits into the gadget ? */
977 if (strsize
> _mwidth(obj
))
979 /* Compute new DispPos such that the cursor is at the right */
980 data
->DispPos
= data
->BufferPos
982 &(data
->VisualBuffer
[data
->BufferPos
]),
983 data
->NumChars
, &te
, NULL
, -1,
984 _mwidth(obj
), _mheight(obj
)) + 1;
986 /* D(bug("cursor right of visible area, new disppos: %d\n", */
987 /* data->DispPos)); */
989 else /* 3). Cursor inside gadget */
993 max_disppos
= MaxDispPos(cl
, obj
);
994 if (data
->DispPos
> max_disppos
)
995 data
->DispPos
= max_disppos
;
997 } /* if (cursor inside or to the right of visible area ) */
1001 /* Update the DispCount */
1002 /* It might be necessary with special handling for centre aligned gads */
1003 dispstr
= &(data
->VisualBuffer
[data
->DispPos
]);
1004 /* D(bug("DispCount before = %d\n", data->DispCount)); */
1005 data
->DispCount
= TextFit(_rp(obj
), dispstr
,
1006 data
->NumChars
- data
->DispPos
,
1007 &te
, NULL
, 1, _mwidth(obj
), _mheight(obj
));
1008 /* D(bug("DispCount after = %d\n", data->DispCount)); */
1010 /* 0-terminate string (in case we put a SPACE at the end) */
1011 data
->VisualBuffer
[data
->NumChars
] = '\0';
1015 /* Gets left position of text in the string gadget */
1016 static UWORD
GetTextLeft(struct IClass
*cl
, Object
*obj
)
1018 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1019 UWORD text_left
= 0;
1020 STRPTR dispstr
= &(data
->VisualBuffer
[data
->DispPos
]);
1024 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
1025 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1027 switch (data
->msd_Align
)
1029 case MUIV_String_Format_Left
:
1030 text_left
= _mleft(obj
);
1033 case MUIV_String_Format_Center
:
1035 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
1037 textwidth
+= TextLength(_rp(obj
), " ", 1);
1038 text_left
= _mleft(obj
) + ((_mwidth(obj
) - textwidth
) / 2);
1039 /* D(bug("GetTextLeft: dispstr=%s, dispstrlen=%d, textw=%d, " */
1041 /* dispstr, dispstrlen, textwidth, text_left)); */
1045 case MUIV_String_Format_Right
:
1047 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
1050 textwidth
+= TextLength(_rp(obj
), " ", 1);
1051 text_left
= _mleft(obj
) + (_mwidth(obj
) - 1 - textwidth
);
1058 /* Gets right offset of text in the string gadget */
1059 static UWORD
GetTextRight(struct IClass
*cl
, Object
*obj
)
1061 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1062 UWORD text_right
= 0;
1063 STRPTR dispstr
= &(data
->VisualBuffer
[data
->DispPos
]);
1067 cursor_at_end
= (data
->BufferPos
== data
->NumChars
);
1068 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1070 switch (data
->msd_Align
)
1072 case MUIV_String_Format_Left
:
1074 _mleft(obj
) + TextLength(_rp(obj
), dispstr
, dispstrlen
);
1077 case MUIV_String_Format_Center
:
1079 WORD textwidth
= TextLength(_rp(obj
), dispstr
, dispstrlen
);
1082 textwidth
+= TextLength(_rp(obj
), " ", 1);
1083 text_right
= _mright(obj
) - ((_mwidth(obj
) - textwidth
) / 2);
1087 case MUIV_String_Format_Right
:
1088 text_right
= _mright(obj
);
1091 return (text_right
);
1095 /* Updates the stringdata in case user has set some fields */
1096 static VOID
UpdateStringData(struct IClass
*cl
, Object
*obj
)
1098 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1100 data
->NumChars
= strlen(data
->Buffer
);
1102 if (data
->BufferPos
> data
->NumChars
)
1104 data
->BufferPos
= data
->NumChars
;
1108 static VOID
TextM(Object
*obj
, struct MUI_StringData
*data
,
1109 STRPTR text
, WORD textlen
, WORD markstart
, WORD markend
)
1111 struct RastPort
*rp
= _rp(obj
);
1115 if (data
->is_active
)
1116 textpen
= data
->active_text
.p_pen
;
1118 textpen
= data
->inactive_text
.p_pen
;
1120 //kprintf("TextM: textlen %d markstart %d markend %d ... \n",
1121 // textlen, markstart, markend);
1123 /* <unmarked><marked><unmarked> */
1127 len
= MIN(markstart
, textlen
);
1132 //kprintf("A: %d ", len);
1134 SetABPenDrMd(rp
, textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1135 Text(rp
, text
, len
);
1142 len
= MIN(markend
- len
, textlen
);
1147 //kprintf("B: %d ", len);
1148 SetABPenDrMd(_rp(obj
), data
->marked_text
.p_pen
,
1149 data
->marked_bg
.p_pen
, JAM2
);
1150 Text(rp
, text
, len
);
1158 //kprintf("C: %d ", textlen);
1160 SetABPenDrMd(rp
, textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1161 Text(rp
, text
, textlen
);
1166 /**************************************************************************
1168 **************************************************************************/
1169 IPTR
String__MUIM_Draw(struct IClass
*cl
, Object
*obj
,
1170 struct MUIP_Draw
*msg
)
1172 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
1178 UWORD textleft_save
;
1179 WORD markstart
= 0, markstop
= 0;
1181 /* D(bug("\nString_Draw(%p) %ldx%ldx%ldx%ld reason=%ld msgflgs=%ld " */
1183 /* "displ=%ld len=%ld buf='%s'\n",obj,_mleft(obj),_mtop(obj), */
1184 /* _mwidth(obj),_mheight(obj), data->msd_RedrawReason, msg->flags, */
1185 /* data->BufferPos, data->DispPos, data->NumChars, data->Buffer)); */
1187 DoSuperMethodA(cl
, obj
, (Msg
) msg
);
1189 if (!(msg
->flags
& MADF_DRAWUPDATE
) && !(msg
->flags
& MADF_DRAWOBJECT
))
1192 PrepareVisualBuffer(data
);
1193 SetFont(_rp(obj
), _font(obj
));
1194 if (data
->is_active
)
1195 textpen
= data
->active_text
.p_pen
;
1197 textpen
= data
->inactive_text
.p_pen
;
1199 /* Update the stringdata in case of user change */
1200 UpdateStringData(cl
, obj
);
1202 /* Update the DispPos and DispCount fields so that the gadget renders
1204 UpdateDisp(cl
, obj
);
1206 text_top
= _mtop(obj
)
1207 + ((_mheight(obj
) - _rp(obj
)->Font
->tf_YSize
) >> 1)
1208 + _rp(obj
)->Font
->tf_Baseline
;
1210 dispstr
= data
->VisualBuffer
+ data
->DispPos
;
1211 dispstrlen
= MIN(data
->DispCount
, data
->NumChars
- data
->DispPos
);
1212 textleft_save
= text_left
= GetTextLeft(cl
, obj
);
1214 // little flicker improvement, don't redraw first part of string
1215 // when adding a char
1216 if (msg
->flags
& MADF_DRAWUPDATE
&&
1217 data
->msd_RedrawReason
== DO_ADDCHAR
&&
1218 data
->msd_Align
== MUIV_String_Format_Left
&& data
->DispPos
== 0)
1220 text_left
+= TextLength(_rp(obj
), dispstr
, data
->BufferPos
- 1);
1221 dispstr
+= data
->BufferPos
- 1;
1222 dispstrlen
-= data
->BufferPos
- 1;
1223 DoMethod(obj
, MUIM_DrawBackground
, text_left
, _mtop(obj
),
1224 _mwidth(obj
) - text_left
+ _mleft(obj
), _mheight(obj
),
1225 text_left
, _mtop(obj
), 0);
1227 else if (msg
->flags
& MADF_DRAWUPDATE
)
1229 DoMethod(obj
, MUIM_DrawBackground
, _mleft(obj
), _mtop(obj
),
1230 _mwidth(obj
), _mheight(obj
), _mleft(obj
), _mtop(obj
), 0);
1233 SetABPenDrMd(_rp(obj
), textpen
, _pens(obj
)[MPEN_BACKGROUND
], JAM1
);
1234 Move(_rp(obj
), text_left
, text_top
);
1236 if ((data
->msd_Flags
& MSDF_MARKING
)
1237 && Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
1239 TextM(obj
, data
, dispstr
, dispstrlen
, markstart
- data
->DispPos
,
1240 markstop
- data
->DispPos
);
1245 Text(_rp(obj
), dispstr
, dispstrlen
);
1247 if (data
->is_active
) // active, draw cursor
1249 UWORD cursoroffset
= data
->BufferPos
- data
->DispPos
;
1251 dispstr
= data
->VisualBuffer
+ data
->DispPos
;
1252 text_left
= textleft_save
;
1254 SetABPenDrMd(_rp(obj
), data
->active_text
.p_pen
,
1255 data
->cursor
.p_pen
, JAM2
);
1256 text_left
+= TextLength(_rp(obj
), dispstr
, cursoroffset
);
1259 Move(_rp(obj
), text_left
, text_top
);
1261 ((data
->BufferPos
< data
->NumChars
)
1262 ? dispstr
+ cursoroffset
: (STRPTR
) " "), 1);
1266 data
->msd_RedrawReason
= NO_REASON
;
1267 CleanVisualBuffer(data
);
1272 /**************************************************************************
1273 Returns whether object needs redrawing
1274 **************************************************************************/
1275 static int String_HandleVanillakey(struct IClass
*cl
, Object
*obj
,
1276 unsigned char code
, UWORD qual
, IPTR
*retval
)
1278 struct MUI_StringData
*data
=
1279 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
1282 D(bug("String_HandleVanillakey: code=%d qual=%d\n", code
, qual
));
1287 doinput
= (data
->msd_Flags
& MSDF_NOINPUT
) ? FALSE
: TRUE
;
1289 if (doinput
&& (code
== '\b')) /* backspace */
1291 if (Buffer_KillMarked(data
))
1296 if (data
->BufferPos
> 0)
1300 if ((qual
& IEQUALIFIER_LSHIFT
) || (qual
& IEQUALIFIER_RSHIFT
))
1302 shift
= data
->BufferPos
;
1303 data
->msd_RedrawReason
= NEW_CONTENTS
;
1308 data
->msd_RedrawReason
= DO_BACKSPACE
;
1311 strcpy(&data
->Buffer
[data
->BufferPos
- shift
],
1312 &data
->Buffer
[data
->BufferPos
]);
1313 data
->BufferPos
-= shift
;
1314 data
->NumChars
-= shift
;
1320 if (doinput
&& (code
== 21)) // ctrl-u == NAK (like shift-bs)
1322 if (Buffer_KillMarked(data
))
1327 if (data
->BufferPos
> 0)
1329 strcpy(&data
->Buffer
[0], &data
->Buffer
[data
->BufferPos
]);
1330 data
->NumChars
-= data
->BufferPos
;
1331 data
->BufferPos
= 0;
1332 data
->msd_RedrawReason
= NEW_CONTENTS
;
1338 if (doinput
&& (code
== 127)) /* del */
1340 if (!Buffer_KillMarked(data
))
1342 if ((qual
& IEQUALIFIER_LSHIFT
) || (qual
& IEQUALIFIER_RSHIFT
))
1344 data
->Buffer
[data
->BufferPos
] = 0;
1345 data
->NumChars
= data
->BufferPos
;
1346 data
->msd_RedrawReason
= NEW_CONTENTS
;
1350 if (data
->BufferPos
< data
->NumChars
)
1352 strcpy(&data
->Buffer
[data
->BufferPos
],
1353 &data
->Buffer
[data
->BufferPos
+ 1]);
1357 data
->msd_RedrawReason
= DO_DELETE
;
1363 if (doinput
&& (code
== 11)) // ctrl-k == VT == \v (like shift-del)
1365 if (!Buffer_KillMarked(data
))
1367 data
->Buffer
[data
->BufferPos
] = 0;
1368 data
->NumChars
= data
->BufferPos
;
1369 data
->msd_RedrawReason
= NEW_CONTENTS
;
1374 if (doinput
&& (code
== 24)) /* ctrl x == ascii cancel */
1376 if (!Buffer_KillMarked(data
))
1378 data
->Buffer
[0] = 0;
1379 data
->BufferPos
= 0;
1381 data
->msd_RedrawReason
= NEW_CONTENTS
;
1386 if (code
== 1) // ctrl-a, linestart
1388 data
->BufferPos
= 0;
1389 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
1393 if (code
== 26) // ctrl-z, lineend
1395 data
->BufferPos
= data
->NumChars
;
1396 data
->msd_Flags
&= ~(MSDF_MARKING
| MSDF_KEYMARKING
);
1400 if (code
== '\t') // tab
1405 if (((ToLower(code
) == 'c') || (ToLower(code
) == 'x')) &&
1406 (qual
& IEQUALIFIER_RCOMMAND
))
1408 WORD markstart
, markstop
;
1410 if ((data
->msd_Flags
& MSDF_MARKING
)
1411 && Buffer_GetMarkedRange(data
, &markstart
, &markstop
))
1413 clipboard_write_text(&data
->Buffer
[markstart
],
1414 markstop
- markstart
);
1416 if (doinput
&& (ToLower(code
) == 'x'))
1418 Buffer_KillMarked(data
);
1422 data
->BufferPos
= markstop
;
1423 data
->msd_Flags
&= ~MSDF_MARKING
;
1430 if (doinput
&& (ToLower(code
) == 'v') && (qual
& IEQUALIFIER_RCOMMAND
))
1434 struct Locale
*locale
= OpenLocale(NULL
);
1436 retval
= Buffer_KillMarked(data
);
1437 if ((text
= clipboard_read_text()))
1439 STRPTR text2
= text
;
1442 while ((c
= *text2
++))
1444 if (!IsPrint(locale
, c
))
1446 if (!(Buffer_AddChar(data
, c
)))
1452 clipboard_free_text(text
);
1455 CloseLocale(locale
);
1460 if (data
->msd_Accept
!= NULL
)
1462 /* Check if character is accepted */
1463 if (NULL
== strchr(data
->msd_Accept
, code
))
1466 *retval
= MUI_EventHandlerRC_Eat
;
1471 if (data
->msd_Reject
!= NULL
)
1473 /* Check if character is rejected */
1474 if (NULL
!= strchr(data
->msd_Reject
, code
))
1477 *retval
= MUI_EventHandlerRC_Eat
;
1484 struct Locale
*locale
= OpenLocale(NULL
);
1486 if (!(code
>= 0x09 && code
<= 0x0D) && IsPrint(locale
, code
))
1488 Buffer_KillMarked(data
);
1489 if (Buffer_AddChar(data
, code
))
1491 data
->msd_RedrawReason
= DO_ADDCHAR
;
1496 CloseLocale(locale
);
1499 data
->msd_RedrawReason
= DO_UNKNOWN
;
1504 /**************************************************************************
1506 **************************************************************************/
1507 IPTR
String__MUIM_HandleEvent(struct IClass
*cl
, Object
*obj
,
1508 struct MUIP_HandleEvent
*msg
)
1510 struct MUI_StringData
*data
=
1511 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
1514 BOOL edited
= FALSE
;
1515 LONG muikey
= msg
->muikey
;
1516 BOOL cursor_kills_marking
= FALSE
;
1518 if ((data
->msd_Flags
& MSDF_MARKING
)
1519 && !(data
->msd_Flags
& MSDF_KEYMARKING
))
1521 cursor_kills_marking
= TRUE
;
1524 /* Convert raw keys to MUI keys for marking */
1525 if (muikey
== MUIKEY_NONE
&& msg
->imsg
!= NULL
)
1527 if (msg
->imsg
->Class
== IDCMP_RAWKEY
)
1529 static LONG muikeytable
[3][2] = {
1530 {MUIKEY_LEFT
, MUIKEY_RIGHT
},
1531 {MUIKEY_WORDLEFT
, MUIKEY_WORDRIGHT
},
1532 {MUIKEY_LINESTART
, MUIKEY_LINEEND
}
1534 WORD dirindex
= -1, amountindex
= 0;
1536 switch (msg
->imsg
->Code
)
1548 muikey
= MUIKEY_LINESTART
;
1552 muikey
= MUIKEY_LINEEND
;
1561 Qualifier
& (IEQUALIFIER_LSHIFT
| IEQUALIFIER_RSHIFT
))
1565 else if (msg
->imsg
->Qualifier
& IEQUALIFIER_CONTROL
)
1570 muikey
= muikeytable
[amountindex
][dirindex
];
1576 D(bug("String_HandleEvent: muikey %d, imsg %p is_active=%d\n", muikey
,
1577 msg
->imsg
, data
->is_active
));
1578 if (muikey
!= MUIKEY_NONE
&& data
->is_active
)
1580 retval
= MUI_EventHandlerRC_Eat
;
1585 if (cursor_kills_marking
)
1588 data
->BufferPos
= MIN(data
->BufferPos
, data
->MarkPos
);
1589 if (data
->BufferPos
> 0)
1592 data
->msd_Flags
&= ~MSDF_MARKING
;
1594 else if (data
->BufferPos
> 0)
1599 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1603 if (cursor_kills_marking
)
1606 data
->BufferPos
= MAX(data
->BufferPos
, data
->MarkPos
);
1607 data
->msd_Flags
&= ~MSDF_MARKING
;
1609 else if (data
->BufferPos
< data
->NumChars
)
1613 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1616 case MUIKEY_WORDLEFT
:
1617 if (data
->BufferPos
> 0)
1620 Buffer_GetPrevWordIndex(data
, data
->BufferPos
);
1622 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1624 if (cursor_kills_marking
)
1626 data
->msd_Flags
&= ~MSDF_MARKING
;
1630 case MUIKEY_WORDRIGHT
:
1631 if (data
->BufferPos
< data
->NumChars
)
1634 Buffer_GetSuccWordIndex(data
, data
->BufferPos
);
1636 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1638 if (cursor_kills_marking
)
1640 data
->msd_Flags
&= ~MSDF_MARKING
;
1644 case MUIKEY_LINESTART
:
1645 data
->BufferPos
= 0;
1647 if (cursor_kills_marking
)
1649 data
->msd_Flags
&= ~MSDF_MARKING
;
1653 case MUIKEY_LINEEND
:
1654 data
->BufferPos
= data
->NumChars
;
1656 if (cursor_kills_marking
)
1658 data
->msd_Flags
&= ~MSDF_MARKING
;
1663 if (data
->msd_AttachedList
)
1664 set(data
->msd_AttachedList
,
1665 MUIA_List_Active
, MUIV_List_Active_Up
);
1668 if (data
->msd_AttachedList
)
1669 set(data
->msd_AttachedList
,
1670 MUIA_List_Active
, MUIV_List_Active_Down
);
1673 if (data
->msd_AttachedList
)
1674 set(data
->msd_AttachedList
,
1675 MUIA_List_Active
, MUIV_List_Active_PageUp
);
1677 case MUIKEY_PAGEDOWN
:
1678 if (data
->msd_AttachedList
)
1679 set(data
->msd_AttachedList
,
1680 MUIA_List_Active
, MUIV_List_Active_PageDown
);
1683 if (data
->msd_AttachedList
)
1684 set(data
->msd_AttachedList
,
1685 MUIA_List_Active
, MUIV_List_Active_Top
);
1688 if (data
->msd_AttachedList
)
1689 set(data
->msd_AttachedList
,
1690 MUIA_List_Active
, MUIV_List_Active_Bottom
);
1697 get(obj
, MUIA_String_Contents
, &buf
);
1699 if (data
->msd_Flags
& MSDF_STAYACTIVE
)
1701 /* Do not change active object */
1703 else if (data
->msd_Flags
& MSDF_ADVANCEONCR
)
1705 set(_win(obj
), MUIA_Window_ActiveObject
,
1706 MUIV_Window_ActiveObject_Next
);
1708 else if (!(data
->msd_Flags
& MSDF_STAYACTIVE
))
1710 set(_win(obj
), MUIA_Window_ActiveObject
,
1711 MUIV_Window_ActiveObject_None
);
1714 /* Notify listeners of new string value */
1715 set(obj
, MUIA_String_Acknowledge
, buf
);
1717 /* Notify listeners of new integer value (if any) */
1718 if (StrToLong(buf
, &val
) >= 0)
1719 superset(cl
, obj
, MUIA_String_Integer
, val
);
1723 case MUIKEY_WINDOW_CLOSE
:
1724 data
->is_active
= FALSE
;
1725 set(obj
, MUIA_Background
,
1726 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
1727 DoMethod(obj
, MUIM_GoInactive
);
1734 } // if (muikey != MUIKEY_NONE)
1738 UWORD code
= msg
->imsg
->Code
;
1739 //UWORD qual = msg->imsg->Qualifier;
1740 WORD x
= msg
->imsg
->MouseX
;
1741 WORD y
= msg
->imsg
->MouseY
;
1743 //bug("String_HandleEvent: parsing imsg %p, class=%ld\n",
1744 // msg->imsg, msg->imsg->Class);
1746 switch (msg
->imsg
->Class
)
1748 case IDCMP_MOUSEBUTTONS
: /* set cursor and activate it */
1749 if (code
== SELECTDOWN
)
1751 //bug("String_HandleEvent: code == SELECTDOWN, x=%d y=%d\n",
1754 if (_isinobject(obj
, x
, y
))
1756 UWORD text_left
, text_right
;
1758 retval
= MUI_EventHandlerRC_Eat
;
1760 CurrentTime(&data
->NewClick_Sec
, &data
->NewClick_Micro
);
1761 if (DoubleClick(data
->OldClick_Sec
,
1762 data
->OldClick_Micro
, data
->NewClick_Sec
,
1763 data
->NewClick_Micro
))
1769 data
->MultiClick
= 0;
1771 data
->OldClick_Sec
= data
->NewClick_Sec
;
1772 data
->OldClick_Micro
= data
->NewClick_Micro
;
1774 //kprintf("multiclick %d\n", data->MultiClick);
1776 if (!data
->is_active
)
1778 //bug("String got button, lets activate\n");
1779 data
->is_active
= TRUE
;
1780 data
->msd_RedrawReason
= WENT_ACTIVE
;
1782 set(obj
, MUIA_Background
,
1783 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->
1786 //DoMethod(obj, MUIM_GoActive);
1787 set(_win(obj
), MUIA_Window_ActiveObject
, obj
);
1788 // let other objects a chance to get desactivated
1792 if (!(data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
))
1794 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1795 (IPTR
) & data
->ehn
);
1796 data
->ehn
.ehn_Events
|= IDCMP_MOUSEMOVE
;
1797 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1798 (IPTR
) & data
->ehn
);
1801 PrepareVisualBuffer(data
);
1802 text_left
= GetTextLeft(cl
, obj
);
1803 text_right
= GetTextRight(cl
, obj
);
1804 CleanVisualBuffer(data
);
1806 /* Check if mouseclick is inside displayed text */
1807 if ((x
>= text_left
) && (x
<= text_right
))
1809 /* Find new cursor pos. */
1810 struct TextExtent te
;
1812 STRPTR dispstr
= data
->Buffer
+ data
->DispPos
;
1814 newpos
= data
->DispPos
1815 + TextFit(_rp(obj
), dispstr
,
1816 data
->NumChars
- data
->DispPos
, &te
, NULL
, 1,
1817 x
- text_left
, _rp(obj
)->Font
->tf_YSize
);
1819 if (data
->BufferPos
!= newpos
)
1821 data
->BufferPos
= newpos
;
1825 else if (x
< text_left
)
1827 /* Click on empty space at left. Set cursor to first
1829 if (data
->BufferPos
!= data
->DispPos
)
1831 data
->BufferPos
= data
->DispPos
;
1837 /* Click on empty space at right. Set cursor to last
1839 if (data
->BufferPos
!=
1840 data
->DispPos
+ data
->DispCount
)
1843 data
->DispPos
+ data
->DispCount
;
1846 } /* if (click is on text or not) */
1848 data
->MarkPos
= data
->BufferPos
;
1850 if (data
->MultiClick
== 0)
1852 if (data
->msd_Flags
& MSDF_MARKING
)
1854 data
->msd_Flags
&= ~MSDF_MARKING
;
1858 else if (data
->MultiClick
1859 && Buffer_GetMarkedRange(data
, NULL
, NULL
))
1861 data
->msd_Flags
|= MSDF_MARKING
;
1866 } /* is in object */
1867 else if (data
->is_active
1868 && !(data
->msd_Flags
& MSDF_STAYACTIVE
))
1869 /* and click not on object */
1871 data
->is_active
= FALSE
;
1872 set(obj
, MUIA_Background
,
1873 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->
1874 string_bg_inactive
);
1875 //DoMethod(obj, MUIM_GoInactive);
1876 // let other objects a chance to get activated
1879 } /* if (code == SELECTDOWN) */
1880 else if (code
== SELECTUP
)
1882 if (data
->ehn
.ehn_Events
& IDCMP_MOUSEMOVE
)
1884 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
,
1885 (IPTR
) & data
->ehn
);
1886 data
->ehn
.ehn_Events
&= ~IDCMP_MOUSEMOVE
;
1887 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
,
1888 (IPTR
) & data
->ehn
);
1893 case IDCMP_MOUSEMOVE
:
1894 if (data
->is_active
)
1896 UWORD text_left
, text_right
;
1898 if (!(data
->msd_Flags
& MSDF_MARKING
))
1900 data
->msd_Flags
|= MSDF_MARKING
;
1903 PrepareVisualBuffer(data
);
1904 text_left
= GetTextLeft(cl
, obj
);
1905 text_right
= GetTextRight(cl
, obj
);
1906 CleanVisualBuffer(data
);
1908 /* Check if mouseclick is inside displayed text */
1909 if ((x
>= text_left
) && (x
<= text_right
))
1911 /* Find new cursor pos. */
1912 struct TextExtent te
;
1914 STRPTR dispstr
= data
->Buffer
+ data
->DispPos
;
1916 newpos
= data
->DispPos
1917 + TextFit(_rp(obj
), dispstr
,
1918 data
->NumChars
- data
->DispPos
, &te
, NULL
, 1,
1919 x
- text_left
, _rp(obj
)->Font
->tf_YSize
);
1921 if (data
->BufferPos
!= newpos
)
1923 WORD old_markstart
= 0, old_markstop
= 0;
1924 WORD markstart
= 0, markstop
= 0;
1925 BOOL was_marked
, is_marked
;
1927 was_marked
= Buffer_AnythingMarked(data
) &&
1928 Buffer_GetMarkedRange(data
, &old_markstart
,
1931 data
->BufferPos
= newpos
;
1933 is_marked
= Buffer_AnythingMarked(data
) &&
1934 Buffer_GetMarkedRange(data
, &markstart
,
1937 if ((was_marked
!= is_marked
) ||
1938 (old_markstart
!= markstart
) ||
1939 (old_markstop
!= markstop
))
1945 else if ((x
< text_left
) && (data
->BufferPos
> 0))
1949 data
->msd_RedrawReason
= DO_CURSOR_LEFT
;
1951 else if ((x
> text_right
)
1952 && (data
->BufferPos
< data
->NumChars
))
1956 data
->msd_RedrawReason
= DO_CURSOR_RIGHT
;
1958 //kprintf(" ---- bp: %d\n", data->BufferPos);
1966 //bug("String_HandleEvent: idcmp_rawkey\n");
1968 if (!data
->is_active
)
1971 code
= ConvertKey(msg
->imsg
);
1974 switch (msg
->imsg
->Code
)
1976 case 0x64: /* LALT */
1977 case 0x65: /* RALT */
1978 case 0x64 | IECODE_UP_PREFIX
:
1979 case 0x65 | IECODE_UP_PREFIX
:
1981 Qualifier
& (IEQUALIFIER_LALT
|
1984 data
->MarkPos
= data
->BufferPos
;
1986 (MSDF_MARKING
| MSDF_KEYMARKING
);
1990 data
->msd_Flags
&= ~MSDF_KEYMARKING
;
2000 String_HandleVanillakey(cl
, obj
, code
,
2001 msg
->imsg
->Qualifier
, &retval
);
2004 retval
= MUI_EventHandlerRC_Eat
;
2013 /* Trigger notification */
2015 superset(cl
, obj
, MUIA_String_Contents
, data
->Buffer
);
2019 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2021 //D(bug("String eh return %ld\n", retval));
2027 /**************************************************************************
2028 MUIM_Export : to export an object's "contents" to a dataspace object.
2029 **************************************************************************/
2030 IPTR
String__MUIM_Export(struct IClass
*cl
, Object
*obj
,
2031 struct MUIP_Export
*msg
)
2033 struct MUI_StringData
*data
= INST_DATA(cl
, obj
);
2036 if ((id
= muiNotifyData(obj
)->mnd_ObjectID
))
2038 if (data
->Buffer
!= NULL
)
2039 DoMethod(msg
->dataspace
, MUIM_Dataspace_Add
,
2040 (IPTR
) data
->Buffer
, data
->NumChars
+ 1, (IPTR
) id
);
2042 DoMethod(msg
->dataspace
, MUIM_Dataspace_Remove
, (IPTR
) id
);
2049 /**************************************************************************
2050 MUIM_Import : to import an object's "contents" from a dataspace object.
2051 **************************************************************************/
2052 IPTR
String__MUIM_Import(struct IClass
*cl
, Object
*obj
,
2053 struct MUIP_Import
*msg
)
2058 if ((id
= muiNotifyData(obj
)->mnd_ObjectID
))
2060 if ((s
= (STRPTR
) DoMethod(msg
->dataspace
, MUIM_Dataspace_Find
,
2063 set(obj
, MUIA_String_Contents
, s
);
2070 /**************************************************************************
2072 **************************************************************************/
2073 IPTR
String__MUIM_GoActive(struct IClass
*cl
, Object
*obj
, Msg msg
)
2075 struct MUI_StringData
*data
=
2076 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2078 //D(bug("String_GoActive %p\n", obj));
2079 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
2080 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
| IDCMP_RAWKEY
;
2081 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
2082 data
->is_active
= TRUE
;
2083 data
->msd_Flags
&= ~MSDF_KEYMARKING
;
2084 data
->msd_RedrawReason
= WENT_ACTIVE
;
2086 set(obj
, MUIA_Background
,
2087 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_active
);
2092 /**************************************************************************
2094 **************************************************************************/
2095 IPTR
String__MUIM_GoInactive(struct IClass
*cl
, Object
*obj
, Msg msg
)
2097 struct MUI_StringData
*data
=
2098 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2100 //D(bug("String_GoInactive %p\n", obj));
2102 DoMethod(_win(obj
), MUIM_Window_RemEventHandler
, (IPTR
) & data
->ehn
);
2103 data
->ehn
.ehn_Events
= IDCMP_MOUSEBUTTONS
;
2104 DoMethod(_win(obj
), MUIM_Window_AddEventHandler
, (IPTR
) & data
->ehn
);
2105 data
->is_active
= FALSE
;
2106 data
->msd_RedrawReason
= WENT_INACTIVE
;
2107 data
->MultiClick
= 0;
2110 set(obj
, MUIA_Background
,
2111 (IPTR
) muiGlobalInfo(obj
)->mgi_Prefs
->string_bg_inactive
);
2116 /**************************************************************************
2117 MUIM_String_ClearSelected (BetterString)
2118 **************************************************************************/
2119 IPTR
String__MUIM_ClearSelected(struct IClass
*cl
, Object
*obj
,
2120 struct MUIP_String_ClearSelected
*msg
)
2122 struct MUI_StringData
*data
=
2123 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2125 //D(bug("String_ClearSelected %p\n", obj));
2127 if (Buffer_KillMarked(data
))
2129 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2135 /**************************************************************************
2136 MUIM_String_Insert (BetterString)
2137 **************************************************************************/
2138 IPTR
String__MUIM_Insert(struct IClass
*cl
, Object
*obj
,
2139 struct MUIP_String_Insert
*msg
)
2141 struct MUI_StringData
*data
=
2142 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2144 ULONG old_bufferpos
;
2145 ULONG num_inserted
= 0;
2147 //D(bug("String_Insert %p\n", obj));
2149 switch ((ULONG
) msg
->pos
)
2151 case MUIV_String_Insert_StartOfString
:
2155 case MUIV_String_Insert_EndOfString
:
2156 pos
= data
->NumChars
;
2159 case MUIV_String_Insert_BufferPos
:
2160 pos
= data
->BufferPos
;
2168 if ((pos
< 0) || (pos
> data
->NumChars
))
2171 old_bufferpos
= data
->BufferPos
;
2172 data
->BufferPos
= pos
;
2174 while (msg
->text
[num_inserted
]
2175 && Buffer_AddChar(data
, msg
->text
[num_inserted
]))
2182 if (old_bufferpos
>= pos
)
2184 data
->BufferPos
= old_bufferpos
+ num_inserted
;
2188 data
->BufferPos
= old_bufferpos
;
2191 MUI_Redraw(obj
, MADF_DRAWUPDATE
);
2197 /**************************************************************************
2198 MUIM_String_FileNameStart (BetterString)
2199 **************************************************************************/
2200 IPTR
String__MUIM_FileNameStart(struct IClass
*cl
, Object
*obj
,
2201 struct MUIP_String_FileNameStart
*msg
)
2203 struct MUI_StringData
*data
=
2204 (struct MUI_StringData
*)INST_DATA(cl
, obj
);
2207 //D(bug("String_FileNameStart %p\n", obj));
2211 // TODO: Implement String_FileNameStart correctly!
2216 BOOPSI_DISPATCHER(IPTR
, String_Dispatcher
, cl
, obj
, msg
)
2218 switch (msg
->MethodID
)
2221 return String__OM_NEW(cl
, obj
, (struct opSet
*)msg
);
2223 return String__OM_DISPOSE(cl
, obj
, msg
);
2225 return String__OM_SET(cl
, obj
, (struct opSet
*)msg
);
2227 return String__OM_GET(cl
, obj
, (struct opGet
*)msg
);
2230 return String__MUIM_Setup(cl
, obj
, (APTR
) msg
);
2232 return String__MUIM_Cleanup(cl
, obj
, (APTR
) msg
);
2233 case MUIM_AskMinMax
:
2234 return String__MUIM_AskMinMax(cl
, obj
, (APTR
) msg
);
2236 return String__MUIM_Draw(cl
, obj
, (APTR
) msg
);
2238 return String__MUIM_Export(cl
, obj
, (APTR
) msg
);
2240 return String__MUIM_Import(cl
, obj
, (APTR
) msg
);
2242 return String__MUIM_GoActive(cl
, obj
, (APTR
) msg
);
2243 case MUIM_GoInactive
:
2244 return String__MUIM_GoInactive(cl
, obj
, (APTR
) msg
);
2245 case MUIM_HandleEvent
:
2246 return String__MUIM_HandleEvent(cl
, obj
, (APTR
) msg
);
2249 case MUIM_String_ClearSelected
:
2250 return String__MUIM_ClearSelected(cl
, obj
, (APTR
) msg
);
2251 case MUIM_String_Insert
:
2252 return String__MUIM_Insert(cl
, obj
, (APTR
) msg
);
2253 case MUIM_String_FileNameStart
:
2254 return String__MUIM_FileNameStart(cl
, obj
, (APTR
) msg
);
2257 return DoSuperMethodA(cl
, obj
, msg
);
2259 BOOPSI_DISPATCHER_END
2264 const struct __MUIBuiltinClass _MUI_String_desc
=
2268 sizeof(struct MUI_StringData
),
2269 (void *)String_Dispatcher